From 7a233e97362d8368482f79b34438febd2a27d14c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Kov=C3=A1r?= <xkovar4@fi.muni.cz> Date: Thu, 3 Feb 2022 12:42:13 +0100 Subject: [PATCH] Resolve "Project tab improvements" --- .../java/cz/fidentis/analyst/Project.java | 12 +- .../analyst/ProjectConfiguration.java | 12 +- .../cz/fidentis/analyst/face/HumanFace.java | 31 + GUI/pom.xml | 5 + .../fidentis/analyst/batch/BatchAction.java | 2 +- .../cz/fidentis/analyst/batch/BatchPanel.java | 2 +- .../analyst/core/OutputWindowThread.java | 2 +- .../fidentis/analyst/core/ProjectTopComp.form | 441 ----------- .../analyst/dashboard/FaceStatePanel.java | 68 -- .../analyst/dashboard/FilterPanel.java | 100 --- .../analyst/project/FaceStatePanel.form | 308 ++++++++ .../analyst/project/FaceStatePanel.java | 404 ++++++++++ .../fidentis/analyst/project/FilterPanel.form | 183 +++++ .../fidentis/analyst/project/FilterPanel.java | 237 ++++++ .../ModelsTableModel.java | 54 +- .../analyst/project/ProjectPanel.form | 322 ++++++++ .../ProjectPanel.java} | 722 ++++++++---------- .../analyst/project/ProjectTopComp.java | 184 +++++ .../project/events/AllFacesLoaded.java | 28 + .../project/events/FaceDeselected.java | 14 + .../analyst/project/events/FaceSelected.java | 44 ++ .../analyst/project/events/ProjectEvent.java | 14 + .../project/events/ProjectListener.java | 23 + .../analyst/project/Bundle.properties | 35 + GUI/src/main/resources/face160x160.png | Bin 0 -> 4468 bytes GUI/src/main/resources/face16x16.png | Bin 0 -> 365 bytes GUI/src/main/resources/face200x200.png | Bin 0 -> 4801 bytes GUI/src/main/resources/face32x32.png | Bin 0 -> 745 bytes GUI/src/main/resources/filter28x28.png | Bin 0 -> 885 bytes GUI/src/main/resources/warning16x16.png | Bin 0 -> 411 bytes 30 files changed, 2198 insertions(+), 1049 deletions(-) delete mode 100644 GUI/src/main/java/cz/fidentis/analyst/core/ProjectTopComp.form delete mode 100644 GUI/src/main/java/cz/fidentis/analyst/dashboard/FaceStatePanel.java delete mode 100644 GUI/src/main/java/cz/fidentis/analyst/dashboard/FilterPanel.java create mode 100644 GUI/src/main/java/cz/fidentis/analyst/project/FaceStatePanel.form create mode 100644 GUI/src/main/java/cz/fidentis/analyst/project/FaceStatePanel.java create mode 100644 GUI/src/main/java/cz/fidentis/analyst/project/FilterPanel.form create mode 100644 GUI/src/main/java/cz/fidentis/analyst/project/FilterPanel.java rename GUI/src/main/java/cz/fidentis/analyst/{dashboard => project}/ModelsTableModel.java (53%) create mode 100644 GUI/src/main/java/cz/fidentis/analyst/project/ProjectPanel.form rename GUI/src/main/java/cz/fidentis/analyst/{core/ProjectTopComp.java => project/ProjectPanel.java} (68%) create mode 100644 GUI/src/main/java/cz/fidentis/analyst/project/ProjectTopComp.java create mode 100644 GUI/src/main/java/cz/fidentis/analyst/project/events/AllFacesLoaded.java create mode 100644 GUI/src/main/java/cz/fidentis/analyst/project/events/FaceDeselected.java create mode 100644 GUI/src/main/java/cz/fidentis/analyst/project/events/FaceSelected.java create mode 100644 GUI/src/main/java/cz/fidentis/analyst/project/events/ProjectEvent.java create mode 100644 GUI/src/main/java/cz/fidentis/analyst/project/events/ProjectListener.java create mode 100644 GUI/src/main/resources/cz/fidentis/analyst/project/Bundle.properties create mode 100644 GUI/src/main/resources/face160x160.png create mode 100644 GUI/src/main/resources/face16x16.png create mode 100644 GUI/src/main/resources/face200x200.png create mode 100644 GUI/src/main/resources/face32x32.png create mode 100644 GUI/src/main/resources/filter28x28.png create mode 100644 GUI/src/main/resources/warning16x16.png diff --git a/Comparison/src/main/java/cz/fidentis/analyst/Project.java b/Comparison/src/main/java/cz/fidentis/analyst/Project.java index 1a006fe9..14db43ce 100644 --- a/Comparison/src/main/java/cz/fidentis/analyst/Project.java +++ b/Comparison/src/main/java/cz/fidentis/analyst/Project.java @@ -4,6 +4,7 @@ import cz.fidentis.analyst.face.HumanFace; import java.io.File; import java.io.IOException; import java.nio.file.Path; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -211,18 +212,19 @@ public class Project { * @return loaded HumanFace */ public HumanFace loadFace(String name) { - //File[] files = new File[getCfg().getPaths().size()]; - //files = getCfg().openFiles().toArray(files); HumanFace face = this.getFaceByName(name); - //File file = new File(path); - //for () - //Path path = this.getCfg().pathToFaceByName(name); if (face == null) { try { Logger out = Logger.measureTime(); Path path = this.getCfg().getPathToFaceByName(name); File file = path.toFile(); face = new HumanFace(file, true); // loads also landmarks, if exist + + String pathString = path.toString(); + Path preview = Paths.get(pathString.substring(0, pathString.lastIndexOf(".")).concat("_preview.jpg")); + //Path previewSmall = Paths.get(pathString.substring(0, pathString.lastIndexOf(".")).concat("_preview_small.png")); + face.setPreview(preview); + this.addFace(face); out.printDuration("Loaded model " + face.getShortName() +" with " + face.getMeshModel().getNumVertices() + " vertices"); } catch (IOException ex) { //ex.printStackTrace(); diff --git a/Comparison/src/main/java/cz/fidentis/analyst/ProjectConfiguration.java b/Comparison/src/main/java/cz/fidentis/analyst/ProjectConfiguration.java index fb66bec4..3f42efb6 100644 --- a/Comparison/src/main/java/cz/fidentis/analyst/ProjectConfiguration.java +++ b/Comparison/src/main/java/cz/fidentis/analyst/ProjectConfiguration.java @@ -10,6 +10,7 @@ import java.util.Map; /** * This class encapsulates data important for project (re)storing such as paths * to faces or which tabs were opened + * * @author Matej Kovar */ public class ProjectConfiguration { @@ -40,7 +41,11 @@ public class ProjectConfiguration { * @return true if path was successfully added */ public boolean addPath(Path path) { - return paths.add(path); + if (paths.contains(path)) { + return false; + } + paths.add(path); + return true; } /** @@ -48,7 +53,10 @@ public class ProjectConfiguration { * @param name String of face */ public void removePath(String name) { - paths.removeIf(p -> p.toString().substring(p.toString().lastIndexOf(File.separatorChar) + 1, p.toString().lastIndexOf('.')).equals(name)); + paths.removeIf(p -> p.toString().substring( + p.toString().lastIndexOf(File.separatorChar) + 1, + p.toString().lastIndexOf('.') + ).equals(name)); } /** diff --git a/Comparison/src/main/java/cz/fidentis/analyst/face/HumanFace.java b/Comparison/src/main/java/cz/fidentis/analyst/face/HumanFace.java index 3d9275be..15cafbc9 100644 --- a/Comparison/src/main/java/cz/fidentis/analyst/face/HumanFace.java +++ b/Comparison/src/main/java/cz/fidentis/analyst/face/HumanFace.java @@ -18,6 +18,7 @@ import cz.fidentis.analyst.symmetry.Plane; import cz.fidentis.analyst.visitors.face.HumanFaceVisitor; import cz.fidentis.analyst.visitors.mesh.BoundingBox; import cz.fidentis.analyst.visitors.mesh.BoundingBox.BBox; +import java.awt.image.BufferedImage; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; @@ -28,10 +29,12 @@ import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; +import java.nio.file.Path; import java.util.Collections; import java.util.List; import java.util.ArrayList; import java.util.Objects; +import javax.imageio.ImageIO; //import org.nustaq.serialization.FSTConfiguration; //import org.nustaq.serialization.FSTObjectInput; //import org.nustaq.serialization.FSTObjectOutput; @@ -48,6 +51,7 @@ import java.util.Objects; * </p> * * @author Radek Oslejsek + * @author Matej Kovar */ public class HumanFace implements Serializable { @@ -66,6 +70,8 @@ public class HumanFace implements Serializable { private final String id; + private BufferedImage preview; + /** * Fast (de)serialization handler */ @@ -351,6 +357,31 @@ public class HumanFace implements Serializable { return ret; } + /** + * Sets preview image + * @param path Path to preview + * @return whether preview was found and successfully set or not + */ + public boolean setPreview(Path path) { + try { + if (path.toFile().exists()) { + preview = ImageIO.read(path.toFile()); + return true; + } + } catch (IOException ex) { + ex.printStackTrace(); + } + return false; + } + + /** + * Gets preview image + * @return preview photo (or {@code null}) + */ + public BufferedImage getPreview() { + return this.preview; + } + /** * Tries to find a file with landmarks definition based on the name of the face's OBJ file. * @return The file with landmarks or {@code null} diff --git a/GUI/pom.xml b/GUI/pom.xml index 4a1aeea3..7af2194f 100644 --- a/GUI/pom.xml +++ b/GUI/pom.xml @@ -154,6 +154,11 @@ <version>2.13.0</version> <type>jar</type> </dependency> + <dependency> + <groupId>com.google.guava</groupId> + <artifactId>guava</artifactId> + <version>30.1-jre</version> + </dependency> </dependencies> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> diff --git a/GUI/src/main/java/cz/fidentis/analyst/batch/BatchAction.java b/GUI/src/main/java/cz/fidentis/analyst/batch/BatchAction.java index 79f143e9..ae5c2b58 100644 --- a/GUI/src/main/java/cz/fidentis/analyst/batch/BatchAction.java +++ b/GUI/src/main/java/cz/fidentis/analyst/batch/BatchAction.java @@ -8,7 +8,7 @@ import cz.fidentis.analyst.face.HumanFace; import cz.fidentis.analyst.face.events.HumanFaceEvent; import cz.fidentis.analyst.face.events.HumanFaceListener; import cz.fidentis.analyst.core.ProgressDialog; -import cz.fidentis.analyst.core.ProjectTopComp; +import cz.fidentis.analyst.project.ProjectTopComp; import cz.fidentis.analyst.scene.DrawableFace; import java.awt.event.ActionEvent; import java.beans.PropertyChangeEvent; diff --git a/GUI/src/main/java/cz/fidentis/analyst/batch/BatchPanel.java b/GUI/src/main/java/cz/fidentis/analyst/batch/BatchPanel.java index adfd35e8..50177304 100644 --- a/GUI/src/main/java/cz/fidentis/analyst/batch/BatchPanel.java +++ b/GUI/src/main/java/cz/fidentis/analyst/batch/BatchPanel.java @@ -2,7 +2,7 @@ package cz.fidentis.analyst.batch; import cz.fidentis.analyst.Logger; import cz.fidentis.analyst.core.ControlPanel; -import cz.fidentis.analyst.core.ProjectTopComp; +import cz.fidentis.analyst.project.ProjectTopComp; import cz.fidentis.analyst.face.HumanFace; import cz.fidentis.analyst.face.HumanFaceFactory; import cz.fidentis.analyst.mesh.io.MeshObjExporter; diff --git a/GUI/src/main/java/cz/fidentis/analyst/core/OutputWindowThread.java b/GUI/src/main/java/cz/fidentis/analyst/core/OutputWindowThread.java index eed010d2..ee27fd8c 100644 --- a/GUI/src/main/java/cz/fidentis/analyst/core/OutputWindowThread.java +++ b/GUI/src/main/java/cz/fidentis/analyst/core/OutputWindowThread.java @@ -15,7 +15,7 @@ import org.openide.windows.WindowManager; * the {@link cz.fidentis.analyst.Logger} and displays them in the output window. * * This singleton is currently executed from - * the {@link cz.fidentis.analyst.core.ProjectTopComp}, which is always presented + * the {@link cz.fidentis.analyst.project.ProjectTopComp}, which is always presented * in the FIDENTIS application. * * @author Radek Oslejsek diff --git a/GUI/src/main/java/cz/fidentis/analyst/core/ProjectTopComp.form b/GUI/src/main/java/cz/fidentis/analyst/core/ProjectTopComp.form deleted file mode 100644 index 8f592816..00000000 --- a/GUI/src/main/java/cz/fidentis/analyst/core/ProjectTopComp.form +++ /dev/null @@ -1,441 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" ?> - -<!-- - - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - ---> - -<Form version="1.9" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo"> - <Properties> - <Property name="opaque" type="boolean" value="true"/> - </Properties> - <AuxValues> - <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/> - <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/> - <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/> - <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/> - <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/> - <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/> - <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/> - <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/> - <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/> - </AuxValues> - - <Layout> - <DimensionLayout dim="0"> - <Group type="103" groupAlignment="0" attributes="0"> - <Component id="mainScrollPanel" alignment="1" max="32767" attributes="0"/> - </Group> - </DimensionLayout> - <DimensionLayout dim="1"> - <Group type="103" groupAlignment="0" attributes="0"> - <Component id="mainScrollPanel" alignment="0" pref="871" max="32767" attributes="0"/> - </Group> - </DimensionLayout> - </Layout> - <SubComponents> - <Container class="javax.swing.JScrollPane" name="mainScrollPanel"> - <AuxValues> - <AuxValue name="JavaCodeGenerator_LayoutCodePost" type="java.lang.String" value="mainScrollPanel.setSize(ControlPanel.CONTROL_PANEL_WIDTH, ControlPanel.HEIGHT);"/> - </AuxValues> - - <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/> - <SubComponents> - <Container class="javax.swing.JPanel" name="mainPanel"> - - <Layout> - <DimensionLayout dim="0"> - <Group type="103" groupAlignment="0" attributes="0"> - <Group type="102" attributes="0"> - <EmptySpace max="-2" attributes="0"/> - <Group type="103" groupAlignment="0" max="-2" attributes="0"> - <Component id="buttonsPanel" max="32767" attributes="0"/> - <Component id="faceTableScrollPanel" pref="863" max="32767" attributes="0"/> - </Group> - <EmptySpace max="32767" attributes="0"/> - <Group type="103" groupAlignment="1" attributes="0"> - <Group type="102" alignment="1" attributes="0"> - <Component id="newProjectButton" min="-2" max="-2" attributes="0"/> - <EmptySpace type="separate" max="-2" attributes="0"/> - <Component id="saveProjectButton" min="-2" max="-2" attributes="0"/> - <EmptySpace type="separate" max="-2" attributes="0"/> - <Component id="openProjectButton" min="-2" max="-2" attributes="0"/> - </Group> - <Group type="103" alignment="1" groupAlignment="0" max="-2" attributes="0"> - <Component id="filterPanel" pref="363" max="32767" attributes="0"/> - <Component id="infoPanel" pref="363" max="32767" attributes="0"/> - </Group> - </Group> - <EmptySpace min="-2" pref="20" max="-2" attributes="0"/> - </Group> - </Group> - </DimensionLayout> - <DimensionLayout dim="1"> - <Group type="103" groupAlignment="0" attributes="0"> - <Group type="102" attributes="0"> - <EmptySpace max="-2" attributes="0"/> - <Group type="103" groupAlignment="0" attributes="0"> - <Group type="103" groupAlignment="0" attributes="0"> - <Group type="102" attributes="0"> - <Component id="buttonsPanel" min="-2" max="-2" attributes="0"/> - <EmptySpace min="-2" pref="6" max="-2" attributes="0"/> - </Group> - <Group type="102" alignment="1" attributes="0"> - <Group type="103" groupAlignment="3" attributes="0"> - <Component id="saveProjectButton" alignment="3" min="-2" max="-2" attributes="0"/> - <Component id="openProjectButton" alignment="3" min="-2" max="-2" attributes="0"/> - </Group> - <EmptySpace type="separate" max="-2" attributes="0"/> - </Group> - </Group> - <Group type="102" alignment="1" attributes="0"> - <Component id="newProjectButton" min="-2" max="-2" attributes="0"/> - <EmptySpace type="separate" max="-2" attributes="0"/> - </Group> - </Group> - <Group type="103" groupAlignment="0" max="-2" attributes="0"> - <Group type="102" attributes="0"> - <Component id="filterPanel" min="-2" max="-2" attributes="0"/> - <EmptySpace min="-2" pref="28" max="-2" attributes="0"/> - <Component id="infoPanel" min="-2" pref="316" max="-2" attributes="0"/> - </Group> - <Component id="faceTableScrollPanel" max="32767" attributes="0"/> - </Group> - <EmptySpace max="-2" attributes="0"/> - </Group> - </Group> - </DimensionLayout> - </Layout> - <SubComponents> - <Container class="javax.swing.JPanel" name="buttonsPanel"> - <Properties> - <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor"> - <Border info="org.netbeans.modules.form.compat2.border.EtchedBorderInfo"> - <EtchetBorder/> - </Border> - </Property> - <Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor"> - <Dimension value="[0, 0]"/> - </Property> - </Properties> - - <Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/> - <SubComponents> - <Component class="javax.swing.JButton" name="addButton"> - <Properties> - <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor"> - <Font name="Tahoma" size="12" style="0"/> - </Property> - <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> - <ResourceString bundle="cz/fidentis/analyst/core/Bundle.properties" key="ProjectTopComp.addButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> - </Property> - </Properties> - <Events> - <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="addButtonMouseClicked"/> - </Events> - <Constraints> - <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription"> - <GridBagConstraints gridX="0" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="20" ipadY="0" insetsTop="16" insetsLeft="16" insetsBottom="13" insetsRight="4" anchor="13" weightX="0.0" weightY="0.0"/> - </Constraint> - </Constraints> - </Component> - <Component class="javax.swing.JButton" name="removeButton"> - <Properties> - <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor"> - <Font name="Tahoma" size="12" style="0"/> - </Property> - <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> - <ResourceString bundle="cz/fidentis/analyst/core/Bundle.properties" key="ProjectTopComp.removeButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> - </Property> - </Properties> - <Events> - <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="removeButtonMouseClicked"/> - </Events> - <Constraints> - <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription"> - <GridBagConstraints gridX="1" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="16" insetsLeft="22" insetsBottom="13" insetsRight="4" anchor="18" weightX="0.0" weightY="0.0"/> - </Constraint> - </Constraints> - </Component> - <Component class="javax.swing.JButton" name="selectAllButton"> - <Properties> - <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor"> - <Font name="Tahoma" size="12" style="0"/> - </Property> - <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> - <ResourceString bundle="cz/fidentis/analyst/core/Bundle.properties" key="ProjectTopComp.selectAllButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> - </Property> - </Properties> - <Events> - <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="selectAllButtonMouseClicked"/> - </Events> - <Constraints> - <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription"> - <GridBagConstraints gridX="2" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="16" insetsLeft="22" insetsBottom="13" insetsRight="4" anchor="18" weightX="0.0" weightY="0.0"/> - </Constraint> - </Constraints> - </Component> - <Component class="javax.swing.JButton" name="deselectAllButton"> - <Properties> - <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor"> - <Font name="Tahoma" size="12" style="0"/> - </Property> - <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> - <ResourceString bundle="cz/fidentis/analyst/core/Bundle.properties" key="ProjectTopComp.deselectAllButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> - </Property> - </Properties> - <Events> - <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="deselectAllButtonMouseClicked"/> - </Events> - <Constraints> - <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription"> - <GridBagConstraints gridX="3" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="16" insetsLeft="22" insetsBottom="13" insetsRight="4" anchor="18" weightX="0.0" weightY="0.0"/> - </Constraint> - </Constraints> - </Component> - <Component class="javax.swing.JButton" name="inflateButton"> - <Properties> - <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor"> - <Font name="Tahoma" size="12" style="0"/> - </Property> - <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> - <ResourceString bundle="cz/fidentis/analyst/core/Bundle.properties" key="ProjectTopComp.inflateButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> - </Property> - <Property name="alignmentX" type="float" value="0.5"/> - </Properties> - <Events> - <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="inflateButtonMouseClicked"/> - </Events> - <Constraints> - <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription"> - <GridBagConstraints gridX="4" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="16" insetsLeft="22" insetsBottom="13" insetsRight="4" anchor="18" weightX="0.0" weightY="0.0"/> - </Constraint> - </Constraints> - </Component> - <Component class="javax.swing.JButton" name="oneOnOneButton"> - <Properties> - <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor"> - <Font name="Tahoma" size="12" style="1"/> - </Property> - <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> - <ResourceString bundle="cz/fidentis/analyst/core/Bundle.properties" key="ProjectTopComp.oneOnOneButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> - </Property> - <Property name="alignmentX" type="float" value="0.5"/> - </Properties> - <Events> - <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="oneOnOneButtonMouseClicked"/> - </Events> - <Constraints> - <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription"> - <GridBagConstraints gridX="6" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="16" insetsLeft="11" insetsBottom="13" insetsRight="4" anchor="18" weightX="0.0" weightY="0.0"/> - </Constraint> - </Constraints> - </Component> - <Component class="javax.swing.JButton" name="manyToManyButton"> - <Properties> - <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor"> - <Font name="Tahoma" size="12" style="1"/> - </Property> - <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> - <ResourceString bundle="cz/fidentis/analyst/core/Bundle.properties" key="ProjectTopComp.manyToManyButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> - </Property> - </Properties> - <Events> - <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="manyToManyButtonMouseClicked"/> - </Events> - <Constraints> - <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription"> - <GridBagConstraints gridX="5" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="16" insetsLeft="30" insetsBottom="13" insetsRight="4" anchor="18" weightX="0.0" weightY="0.0"/> - </Constraint> - </Constraints> - </Component> - <Component class="javax.swing.JButton" name="analyseButton"> - <Properties> - <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor"> - <Font name="Tahoma" size="12" style="1"/> - </Property> - <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> - <ResourceString bundle="cz/fidentis/analyst/core/Bundle.properties" key="ProjectTopComp.analyseButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> - </Property> - </Properties> - <Events> - <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="analyseButtonMouseClicked"/> - </Events> - <Constraints> - <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription"> - <GridBagConstraints gridX="7" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="16" insetsLeft="11" insetsBottom="13" insetsRight="4" anchor="10" weightX="0.0" weightY="0.0"/> - </Constraint> - </Constraints> - </Component> - </SubComponents> - </Container> - <Container class="javax.swing.JScrollPane" name="faceTableScrollPanel"> - <Properties> - <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor"> - <Dimension value="[812, 750]"/> - </Property> - </Properties> - <AuxValues> - <AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/> - </AuxValues> - - <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/> - <SubComponents> - <Component class="javax.swing.JTable" name="table"> - <Properties> - <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor" postCode="table.getTableHeader().setOpaque(false);
table.getTableHeader().setBackground(new java.awt.Color(204,204,204));
table.getTableHeader().setFont(new java.awt.Font("Tahoma", 0, 18));
model.addTableModelListener(new TableModelListener() {

 public void tableChanged(TableModelEvent e) {
 jTable1TableChanged(e);
 }
});"> - <Font name="Tahoma" size="18" style="0"/> - </Property> - <Property name="model" type="javax.swing.table.TableModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor" postCode="table.getColumnModel().getColumn(0).setMaxWidth(50);
table.getColumnModel().getColumn(2).setMaxWidth(75);
table.getTableHeader().getColumnModel().getColumn(0).setMaxWidth(50);
table.getTableHeader().getColumnModel().getColumn(2).setMaxWidth(75);"> - <Connection code="model" type="code"/> - </Property> - <Property name="columnModel" type="javax.swing.table.TableColumnModel" editor="org.netbeans.modules.form.editors2.TableColumnModelEditor"> - <TableColumnModel selectionModel="0"/> - </Property> - <Property name="dragEnabled" type="boolean" value="true"/> - <Property name="rowHeight" type="int" value="40"/> - <Property name="selectionBackground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor"> - <Color blue="ff" green="cc" red="66" type="rgb"/> - </Property> - <Property name="selectionMode" type="int" value="0"/> - <Property name="tableHeader" type="javax.swing.table.JTableHeader" editor="org.netbeans.modules.form.editors2.JTableHeaderEditor"> - <TableHeader reorderingAllowed="false" resizingAllowed="true"/> - </Property> - </Properties> - <Events> - <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="tableMouseClicked"/> - </Events> - <AuxValues> - <AuxValue name="JavaCodeGenerator_InitCodePre" type="java.lang.String" value="table.setSize(faceTableScrollPanel.getWidth(), faceTableScrollPanel.getHeight());"/> - </AuxValues> - </Component> - </SubComponents> - </Container> - <Container class="javax.swing.JPanel" name="filterPanel"> - <Properties> - <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor"> - <Border info="org.netbeans.modules.form.compat2.border.EtchedBorderInfo"> - <EtchetBorder/> - </Border> - </Property> - <Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor"> - <Dimension value="[342, 424]"/> - </Property> - <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor"> - <Dimension value="[342, 424]"/> - </Property> - </Properties> - - <Layout> - <DimensionLayout dim="0"> - <Group type="103" groupAlignment="0" attributes="0"> - <EmptySpace min="0" pref="359" max="32767" attributes="0"/> - </Group> - </DimensionLayout> - <DimensionLayout dim="1"> - <Group type="103" groupAlignment="0" attributes="0"> - <EmptySpace min="0" pref="420" max="32767" attributes="0"/> - </Group> - </DimensionLayout> - </Layout> - </Container> - <Container class="javax.swing.JPanel" name="infoPanel"> - <Properties> - <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor"> - <Border info="org.netbeans.modules.form.compat2.border.EtchedBorderInfo"> - <EtchetBorder/> - </Border> - </Property> - <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor"> - <Dimension value="[349, 363]"/> - </Property> - </Properties> - <AuxValues> - <AuxValue name="JavaCodeGenerator_LayoutCodePost" type="java.lang.String" value="infoPanel.setVisible(false);"/> - </AuxValues> - - <Layout> - <DimensionLayout dim="0"> - <Group type="103" groupAlignment="0" attributes="0"> - <EmptySpace min="0" pref="0" max="32767" attributes="0"/> - </Group> - </DimensionLayout> - <DimensionLayout dim="1"> - <Group type="103" groupAlignment="0" attributes="0"> - <EmptySpace min="0" pref="312" max="32767" attributes="0"/> - </Group> - </DimensionLayout> - </Layout> - </Container> - <Component class="javax.swing.JButton" name="saveProjectButton"> - <Properties> - <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor"> - <Font name="Tahoma" size="12" style="0"/> - </Property> - <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor"> - <Image iconType="3" name="/save100x24.png"/> - </Property> - <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> - <ResourceString bundle="cz/fidentis/analyst/core/Bundle.properties" key="ProjectTopComp.saveProjectButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> - </Property> - </Properties> - <AccessibilityProperties> - <Property name="AccessibleContext.accessibleName" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> - <ResourceString bundle="cz/fidentis/analyst/core/Bundle.properties" key="ProjectTopComp.saveProjectButton.AccessibleContext.accessibleName" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> - </Property> - </AccessibilityProperties> - <Events> - <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="saveProjectButtonMouseClicked"/> - </Events> - </Component> - <Component class="javax.swing.JButton" name="openProjectButton"> - <Properties> - <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor"> - <Font name="Tahoma" size="12" style="0"/> - </Property> - <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor"> - <Image iconType="3" name="/open100x24.png"/> - </Property> - <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> - <ResourceString bundle="cz/fidentis/analyst/core/Bundle.properties" key="ProjectTopComp.openProjectButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> - </Property> - </Properties> - <Events> - <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="openProjectButtonMouseClicked"/> - </Events> - </Component> - <Component class="javax.swing.JButton" name="newProjectButton"> - <Properties> - <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor"> - <Image iconType="3" name="/new100x24.png"/> - </Property> - <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> - <ResourceString bundle="cz/fidentis/analyst/core/Bundle.properties" key="ProjectTopComp.newProjectButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> - </Property> - </Properties> - <Events> - <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="newProjectButtonMouseClicked"/> - </Events> - </Component> - </SubComponents> - </Container> - </SubComponents> - </Container> - </SubComponents> -</Form> diff --git a/GUI/src/main/java/cz/fidentis/analyst/dashboard/FaceStatePanel.java b/GUI/src/main/java/cz/fidentis/analyst/dashboard/FaceStatePanel.java deleted file mode 100644 index 173f96e0..00000000 --- a/GUI/src/main/java/cz/fidentis/analyst/dashboard/FaceStatePanel.java +++ /dev/null @@ -1,68 +0,0 @@ -package cz.fidentis.analyst.dashboard; - -import cz.fidentis.analyst.core.ControlPanelBuilder; -import cz.fidentis.analyst.face.HumanFace; -import javax.swing.ImageIcon; -import javax.swing.JLabel; -import javax.swing.JPanel; - -/** - * Panel for showing face state information - * - * @author Matej Kovar - */ -public final class FaceStatePanel extends JPanel { - - private final JPanel controlPanel; - - private final ImageIcon notCheck = new ImageIcon(FaceStatePanel.class.getClassLoader().getResource("/" + "notCheck16x16.png")); - private final ImageIcon check = new ImageIcon(FaceStatePanel.class.getClassLoader().getResource("/" + "check16x16.png")); - private final JLabel hasKDtree; - private final JLabel hasFeaturePoints; - private final JLabel tmp1; - private final JLabel tmp2; - private final JLabel tmp3; - - /** - * Constructor - * @param controlPanel control panel where components will be added - * @param face HumanFace, its state info will be shown - */ - public FaceStatePanel(JPanel controlPanel, HumanFace face) { - - this.controlPanel = controlPanel; - this.controlPanel.removeAll(); - ControlPanelBuilder builder = new ControlPanelBuilder(this.controlPanel); - - builder.addCaptionLine("Face state"); - builder.addLine(); - - hasKDtree = builder.addLabelLine("Has KD-tree calculated"); - if (face.hasKdTree()) { - hasKDtree.setIcon(check); - } else { - hasKDtree.setIcon(notCheck); - } - builder.addLine(); - - hasFeaturePoints = builder.addLabelLine("Has Feature points"); - if (face.hasFeaturePoints()) { - hasFeaturePoints.setIcon(check); - } else { - hasFeaturePoints.setIcon(notCheck); - } - builder.addLine(); - - tmp1 = builder.addLabelLine("..."); - tmp1.setIcon(notCheck); - builder.addLine(); - - tmp2 = builder.addLabelLine("..."); - tmp2.setIcon(notCheck); - builder.addLine(); - - tmp3 = builder.addLabelLine("..."); - tmp3.setIcon(notCheck); - builder.addLine(); - } -} diff --git a/GUI/src/main/java/cz/fidentis/analyst/dashboard/FilterPanel.java b/GUI/src/main/java/cz/fidentis/analyst/dashboard/FilterPanel.java deleted file mode 100644 index 9c352f39..00000000 --- a/GUI/src/main/java/cz/fidentis/analyst/dashboard/FilterPanel.java +++ /dev/null @@ -1,100 +0,0 @@ -package cz.fidentis.analyst.dashboard; - -import cz.fidentis.analyst.core.ControlPanelBuilder; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import javax.swing.JCheckBox; -import javax.swing.JPanel; - -/** - * Panel for showing filter options - * - * @author Matej Kovar - */ -public final class FilterPanel extends JPanel { - - private final JPanel controlPanel; - - private boolean kdTreeFilter = false; - private boolean featurePointsFilter = false; - private boolean alphabeticalFilter = false; - - - /** - * Constructor - * @param controlPanel control panel where components will be added - * @param action ActionListener - */ - public FilterPanel(JPanel controlPanel, ActionListener action) { - - this.controlPanel = controlPanel; - ControlPanelBuilder builder = new ControlPanelBuilder(this.controlPanel); - - builder.addCaptionLine("Filter"); - builder.addLine(); - - builder.addCheckBoxOptionLine( - null, - "has KD-tree", - false, - (ActionEvent e) -> { - kdTreeFilter = (((JCheckBox) e.getSource()).isSelected()); - } - ); - builder.addLine(); - - builder.addCheckBoxOptionLine( - null, - "has feature points", - false, - (ActionEvent e) -> { - featurePointsFilter = (((JCheckBox) e.getSource()).isSelected()); - } - ); - builder.addLine(); - - builder.addCheckBoxOptionLine( - null, - "...", - false, - null - ); - builder.addLine(); - - builder.addCheckBoxOptionLine( - null, - "...", - false, - null - ); - builder.addLine(); - - builder.addCheckBoxOptionLine( - null, - "alphabetical", - false, - (ActionEvent e) -> { - alphabeticalFilter = (((JCheckBox) e.getSource()).isSelected()); - } - ); - builder.addLine(); - - builder.addButton( - "Apply filter", - action - ); - } - - public boolean isKdTreeFilter() { - return kdTreeFilter; - } - - public boolean isFeaturePointsFilter() { - return featurePointsFilter; - } - - public boolean isAlphaBeticalFilter() { - return alphabeticalFilter; - } - -} diff --git a/GUI/src/main/java/cz/fidentis/analyst/project/FaceStatePanel.form b/GUI/src/main/java/cz/fidentis/analyst/project/FaceStatePanel.form new file mode 100644 index 00000000..496cdadc --- /dev/null +++ b/GUI/src/main/java/cz/fidentis/analyst/project/FaceStatePanel.form @@ -0,0 +1,308 @@ +<?xml version="1.0" encoding="UTF-8" ?> + +<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo"> + <AuxValues> + <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/> + <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/> + <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/> + <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/> + <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/> + <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/> + <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/> + <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/> + <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/> + </AuxValues> + + <Layout> + <DimensionLayout dim="0"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" attributes="0"> + <EmptySpace max="-2" attributes="0"/> + <Group type="103" groupAlignment="0" attributes="0"> + <Component id="filePanel" max="32767" attributes="0"/> + <Component id="facePanel" alignment="0" max="32767" attributes="0"/> + <Component id="photoPanel" alignment="0" min="-2" max="-2" attributes="0"/> + </Group> + <EmptySpace max="-2" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + <DimensionLayout dim="1"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" alignment="0" attributes="0"> + <EmptySpace min="-2" pref="6" max="-2" attributes="0"/> + <Component id="photoPanel" min="-2" max="-2" attributes="0"/> + <EmptySpace type="unrelated" max="-2" attributes="0"/> + <Component id="filePanel" min="-2" max="-2" attributes="0"/> + <EmptySpace type="separate" max="-2" attributes="0"/> + <Component id="facePanel" max="32767" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + </Layout> + <SubComponents> + <Container class="javax.swing.JPanel" name="filePanel"> + <Properties> + <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor"> + <Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo"> + <TitledBorder title="<FaceStatePanel.filePanel.border.title>"> + <ResourceString PropertyName="titleX" bundle="cz/fidentis/analyst/project/Bundle.properties" key="FaceStatePanel.filePanel.border.title" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + <Font PropertyName="font" name="Dialog" size="12" style="1"/> + </TitledBorder> + </Border> + </Property> + </Properties> + <AccessibilityProperties> + <Property name="AccessibleContext.accessibleName" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="cz/fidentis/analyst/project/Bundle.properties" key="FaceStatePanel.filePanel.AccessibleContext.accessibleName" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + </Property> + </AccessibilityProperties> + + <Layout> + <DimensionLayout dim="0"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" attributes="0"> + <EmptySpace max="-2" attributes="0"/> + <Group type="103" groupAlignment="0" attributes="0"> + <Component id="pathLabel" alignment="0" min="-2" max="-2" attributes="0"/> + <Component id="sizeLabel" alignment="0" min="-2" max="-2" attributes="0"/> + </Group> + <EmptySpace min="-2" pref="49" max="-2" attributes="0"/> + <Group type="103" groupAlignment="0" attributes="0"> + <Component id="sizeOutput" min="-2" max="-2" attributes="0"/> + <Component id="pathOutput" min="-2" max="-2" attributes="0"/> + </Group> + <EmptySpace max="32767" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + <DimensionLayout dim="1"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" alignment="0" attributes="0"> + <EmptySpace max="-2" attributes="0"/> + <Group type="103" groupAlignment="3" attributes="0"> + <Component id="pathLabel" alignment="3" min="-2" max="-2" attributes="0"/> + <Component id="pathOutput" alignment="3" min="-2" max="-2" attributes="0"/> + </Group> + <EmptySpace min="-2" pref="13" max="-2" attributes="0"/> + <Group type="103" groupAlignment="3" attributes="0"> + <Component id="sizeLabel" alignment="3" min="-2" max="-2" attributes="0"/> + <Component id="sizeOutput" alignment="3" min="-2" max="-2" attributes="0"/> + </Group> + <EmptySpace pref="41" max="32767" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + </Layout> + <SubComponents> + <Component class="javax.swing.JLabel" name="pathLabel"> + <Properties> + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="cz/fidentis/analyst/project/Bundle.properties" key="FaceStatePanel.pathLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + </Property> + <Property name="enabled" type="boolean" value="false"/> + </Properties> + </Component> + <Component class="javax.swing.JLabel" name="sizeLabel"> + <Properties> + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="cz/fidentis/analyst/project/Bundle.properties" key="FaceStatePanel.sizeLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + </Property> + <Property name="enabled" type="boolean" value="false"/> + </Properties> + </Component> + <Component class="javax.swing.JLabel" name="pathOutput"> + <Properties> + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="cz/fidentis/analyst/project/Bundle.properties" key="FaceStatePanel.pathOutput.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + </Property> + </Properties> + </Component> + <Component class="javax.swing.JLabel" name="sizeOutput"> + <Properties> + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="cz/fidentis/analyst/project/Bundle.properties" key="FaceStatePanel.sizeOutput.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + </Property> + </Properties> + </Component> + </SubComponents> + </Container> + <Container class="javax.swing.JPanel" name="facePanel"> + <Properties> + <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor"> + <Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo"> + <TitledBorder title="<FaceStatePanel.facePanel.border.title>"> + <ResourceString PropertyName="titleX" bundle="cz/fidentis/analyst/project/Bundle.properties" key="FaceStatePanel.facePanel.border.title" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + <Font PropertyName="font" name="Dialog" size="12" style="1"/> + </TitledBorder> + </Border> + </Property> + </Properties> + + <Layout> + <DimensionLayout dim="0"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" attributes="0"> + <EmptySpace max="-2" attributes="0"/> + <Group type="103" groupAlignment="0" attributes="0"> + <Component id="kdTreeLabel" alignment="0" min="-2" max="-2" attributes="0"/> + <Component id="featurePointsLoadedLabel" alignment="0" min="-2" max="-2" attributes="0"/> + </Group> + <EmptySpace min="-2" pref="22" max="-2" attributes="0"/> + <Group type="103" groupAlignment="0" attributes="0"> + <Component id="hasFPOutput" min="-2" max="-2" attributes="0"/> + <Component id="hasKDOutput" min="-2" max="-2" attributes="0"/> + </Group> + <EmptySpace pref="423" max="32767" attributes="0"/> + </Group> + <Group type="102" alignment="1" attributes="0"> + <EmptySpace max="32767" attributes="0"/> + <Component id="warningLabel" min="-2" max="-2" attributes="0"/> + <EmptySpace type="unrelated" max="-2" attributes="0"/> + <Group type="103" groupAlignment="0" attributes="0"> + <Component id="faceNotLoadedLabel" min="-2" max="-2" attributes="0"/> + <Component id="loadFaceButton" min="-2" max="-2" attributes="0"/> + </Group> + <EmptySpace min="-2" pref="33" max="-2" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + <DimensionLayout dim="1"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" alignment="0" attributes="0"> + <EmptySpace max="-2" attributes="0"/> + <Group type="103" groupAlignment="3" attributes="0"> + <Component id="kdTreeLabel" alignment="3" min="-2" max="-2" attributes="0"/> + <Component id="hasKDOutput" alignment="3" min="-2" max="-2" attributes="0"/> + </Group> + <EmptySpace type="separate" max="-2" attributes="0"/> + <Group type="103" groupAlignment="3" attributes="0"> + <Component id="featurePointsLoadedLabel" alignment="3" min="-2" max="-2" attributes="0"/> + <Component id="hasFPOutput" alignment="3" min="-2" max="-2" attributes="0"/> + </Group> + <EmptySpace min="-2" pref="56" max="-2" attributes="0"/> + <Group type="103" groupAlignment="1" attributes="0"> + <Component id="warningLabel" min="-2" max="-2" attributes="0"/> + <Component id="faceNotLoadedLabel" min="-2" max="-2" attributes="0"/> + </Group> + <EmptySpace type="unrelated" max="-2" attributes="0"/> + <Component id="loadFaceButton" min="-2" max="-2" attributes="0"/> + <EmptySpace pref="44" max="32767" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + </Layout> + <SubComponents> + <Component class="javax.swing.JLabel" name="kdTreeLabel"> + <Properties> + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="cz/fidentis/analyst/project/Bundle.properties" key="FaceStatePanel.kdTreeLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + </Property> + <Property name="enabled" type="boolean" value="false"/> + </Properties> + </Component> + <Component class="javax.swing.JLabel" name="featurePointsLoadedLabel"> + <Properties> + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="cz/fidentis/analyst/project/Bundle.properties" key="FaceStatePanel.featurePointsLoadedLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + </Property> + <Property name="enabled" type="boolean" value="false"/> + </Properties> + </Component> + <Component class="javax.swing.JLabel" name="hasKDOutput"> + <Properties> + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="cz/fidentis/analyst/project/Bundle.properties" key="FaceStatePanel.hasKDOutput.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + </Property> + </Properties> + </Component> + <Component class="javax.swing.JLabel" name="hasFPOutput"> + <Properties> + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="cz/fidentis/analyst/project/Bundle.properties" key="FaceStatePanel.hasFPOutput.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + </Property> + </Properties> + </Component> + <Component class="javax.swing.JLabel" name="faceNotLoadedLabel"> + <Properties> + <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor"> + <Font name="Tahoma" size="12" style="1"/> + </Property> + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="cz/fidentis/analyst/project/Bundle.properties" key="FaceStatePanel.faceNotLoadedLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + </Property> + </Properties> + <AuxValues> + <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="faceNotLoadedLabel.setVisible(false);"/> + </AuxValues> + </Component> + <Component class="javax.swing.JButton" name="loadFaceButton"> + <Properties> + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="cz/fidentis/analyst/project/Bundle.properties" key="FaceStatePanel.loadFaceButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + </Property> + </Properties> + <AuxValues> + <AuxValue name="JavaCodeGenerator_InitCodePre" type="java.lang.String" value="loadFaceButton.setVisible(false);"/> + </AuxValues> + </Component> + <Component class="javax.swing.JLabel" name="warningLabel"> + <Properties> + <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor" postCode="warningLabel.setVisible(false);"> + <Image iconType="3" name="/warning16x16.png"/> + </Property> + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="cz/fidentis/analyst/project/Bundle.properties" key="FaceStatePanel.warningLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + </Property> + </Properties> + </Component> + </SubComponents> + </Container> + <Container class="javax.swing.JPanel" name="photoPanel"> + <Properties> + <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor"> + <Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo"> + <TitledBorder title="<FaceStatePanel.photoPanel.border.title>"> + <ResourceString PropertyName="titleX" bundle="cz/fidentis/analyst/project/Bundle.properties" key="FaceStatePanel.photoPanel.border.title" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + <Font PropertyName="font" name="Dialog" size="12" style="1"/> + </TitledBorder> + </Border> + </Property> + </Properties> + + <Layout> + <DimensionLayout dim="0"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" alignment="0" attributes="0"> + <EmptySpace min="-2" pref="55" max="-2" attributes="0"/> + <Component id="photo" min="-2" max="-2" attributes="0"/> + <EmptySpace min="-2" pref="55" max="-2" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + <DimensionLayout dim="1"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" alignment="0" attributes="0"> + <EmptySpace max="32767" attributes="0"/> + <Component id="photo" min="-2" max="-2" attributes="0"/> + <EmptySpace max="32767" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + </Layout> + <SubComponents> + <Component class="javax.swing.JLabel" name="photo"> + <Properties> + <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor"> + <Image iconType="3" name="/face160x160.png"/> + </Property> + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="cz/fidentis/analyst/project/Bundle.properties" key="FaceStatePanel.photo.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + </Property> + </Properties> + </Component> + </SubComponents> + </Container> + </SubComponents> +</Form> diff --git a/GUI/src/main/java/cz/fidentis/analyst/project/FaceStatePanel.java b/GUI/src/main/java/cz/fidentis/analyst/project/FaceStatePanel.java new file mode 100644 index 00000000..4cd359e1 --- /dev/null +++ b/GUI/src/main/java/cz/fidentis/analyst/project/FaceStatePanel.java @@ -0,0 +1,404 @@ +package cz.fidentis.analyst.project; + +import cz.fidentis.analyst.core.ControlPanel; +import cz.fidentis.analyst.project.events.FaceDeselected; +import cz.fidentis.analyst.project.events.ProjectListener; +import cz.fidentis.analyst.project.events.FaceSelected; +import cz.fidentis.analyst.project.events.ProjectEvent; +import cz.fidentis.analyst.face.HumanFace; +import java.awt.Image; +import java.awt.event.ActionListener; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import javax.imageio.ImageIO; +import javax.swing.ImageIcon; + +/** + * + * @author Matej Kovar + */ +public class FaceStatePanel extends ControlPanel implements ProjectListener { + + private final ImageIcon notCheck = new ImageIcon(FaceStatePanel.class.getClassLoader().getResource("/" + "notCheck16x16.png")); + private final ImageIcon check = new ImageIcon(FaceStatePanel.class.getClassLoader().getResource("/" + "check16x16.png")); + //private final ImageIcon warning = new ImageIcon(FaceStatePanel.class.getClassLoader().getResource("/" + "warning16x16.png")); + private final ImageIcon anonymousFace = new ImageIcon(FaceStatePanel.class.getClassLoader().getResource("/" + "face160x160.png")); + + public static final String ICON = "head28x28.png"; + public static final String NAME = "Face State"; + + + /** + * Panel with face information + * @param loadFaceListener ActionListener listens when load face button is clicked + */ + public FaceStatePanel(ActionListener loadFaceListener) { + + this.setName(NAME); + initComponents(); + loadFaceButton.addActionListener(loadFaceListener); + //210 140 + + } + + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents + private void initComponents() { + + filePanel = new javax.swing.JPanel(); + pathLabel = new javax.swing.JLabel(); + sizeLabel = new javax.swing.JLabel(); + pathOutput = new javax.swing.JLabel(); + sizeOutput = new javax.swing.JLabel(); + facePanel = new javax.swing.JPanel(); + kdTreeLabel = new javax.swing.JLabel(); + featurePointsLoadedLabel = new javax.swing.JLabel(); + hasKDOutput = new javax.swing.JLabel(); + hasFPOutput = new javax.swing.JLabel(); + faceNotLoadedLabel = new javax.swing.JLabel(); + loadFaceButton = new javax.swing.JButton(); + warningLabel = new javax.swing.JLabel(); + photoPanel = new javax.swing.JPanel(); + photo = new javax.swing.JLabel(); + + filePanel.setBorder(javax.swing.BorderFactory.createTitledBorder(null, org.openide.util.NbBundle.getMessage(FaceStatePanel.class, "FaceStatePanel.filePanel.border.title"), javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, new java.awt.Font("Dialog", 1, 12))); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(pathLabel, org.openide.util.NbBundle.getMessage(FaceStatePanel.class, "FaceStatePanel.pathLabel.text")); // NOI18N + pathLabel.setEnabled(false); + + org.openide.awt.Mnemonics.setLocalizedText(sizeLabel, org.openide.util.NbBundle.getMessage(FaceStatePanel.class, "FaceStatePanel.sizeLabel.text")); // NOI18N + sizeLabel.setEnabled(false); + + org.openide.awt.Mnemonics.setLocalizedText(pathOutput, org.openide.util.NbBundle.getMessage(FaceStatePanel.class, "FaceStatePanel.pathOutput.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(sizeOutput, org.openide.util.NbBundle.getMessage(FaceStatePanel.class, "FaceStatePanel.sizeOutput.text")); // NOI18N + + javax.swing.GroupLayout filePanelLayout = new javax.swing.GroupLayout(filePanel); + filePanel.setLayout(filePanelLayout); + filePanelLayout.setHorizontalGroup( + filePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(filePanelLayout.createSequentialGroup() + .addContainerGap() + .addGroup(filePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(pathLabel) + .addComponent(sizeLabel)) + .addGap(49, 49, 49) + .addGroup(filePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(sizeOutput) + .addComponent(pathOutput)) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + filePanelLayout.setVerticalGroup( + filePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(filePanelLayout.createSequentialGroup() + .addContainerGap() + .addGroup(filePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(pathLabel) + .addComponent(pathOutput)) + .addGap(13, 13, 13) + .addGroup(filePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(sizeLabel) + .addComponent(sizeOutput)) + .addContainerGap(41, Short.MAX_VALUE)) + ); + + facePanel.setBorder(javax.swing.BorderFactory.createTitledBorder(null, org.openide.util.NbBundle.getMessage(FaceStatePanel.class, "FaceStatePanel.facePanel.border.title"), javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, new java.awt.Font("Dialog", 1, 12))); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(kdTreeLabel, org.openide.util.NbBundle.getMessage(FaceStatePanel.class, "FaceStatePanel.kdTreeLabel.text")); // NOI18N + kdTreeLabel.setEnabled(false); + + org.openide.awt.Mnemonics.setLocalizedText(featurePointsLoadedLabel, org.openide.util.NbBundle.getMessage(FaceStatePanel.class, "FaceStatePanel.featurePointsLoadedLabel.text")); // NOI18N + featurePointsLoadedLabel.setEnabled(false); + + org.openide.awt.Mnemonics.setLocalizedText(hasKDOutput, org.openide.util.NbBundle.getMessage(FaceStatePanel.class, "FaceStatePanel.hasKDOutput.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(hasFPOutput, org.openide.util.NbBundle.getMessage(FaceStatePanel.class, "FaceStatePanel.hasFPOutput.text")); // NOI18N + + faceNotLoadedLabel.setFont(new java.awt.Font("Tahoma", 1, 12)); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(faceNotLoadedLabel, org.openide.util.NbBundle.getMessage(FaceStatePanel.class, "FaceStatePanel.faceNotLoadedLabel.text")); // NOI18N + faceNotLoadedLabel.setVisible(false); + + loadFaceButton.setVisible(false); + org.openide.awt.Mnemonics.setLocalizedText(loadFaceButton, org.openide.util.NbBundle.getMessage(FaceStatePanel.class, "FaceStatePanel.loadFaceButton.text")); // NOI18N + + warningLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/warning16x16.png"))); // NOI18N + warningLabel.setVisible(false); + org.openide.awt.Mnemonics.setLocalizedText(warningLabel, org.openide.util.NbBundle.getMessage(FaceStatePanel.class, "FaceStatePanel.warningLabel.text")); // NOI18N + + javax.swing.GroupLayout facePanelLayout = new javax.swing.GroupLayout(facePanel); + facePanel.setLayout(facePanelLayout); + facePanelLayout.setHorizontalGroup( + facePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(facePanelLayout.createSequentialGroup() + .addContainerGap() + .addGroup(facePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(kdTreeLabel) + .addComponent(featurePointsLoadedLabel)) + .addGap(22, 22, 22) + .addGroup(facePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(hasFPOutput) + .addComponent(hasKDOutput)) + .addContainerGap(423, Short.MAX_VALUE)) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, facePanelLayout.createSequentialGroup() + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(warningLabel) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addGroup(facePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(faceNotLoadedLabel) + .addComponent(loadFaceButton)) + .addGap(33, 33, 33)) + ); + facePanelLayout.setVerticalGroup( + facePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(facePanelLayout.createSequentialGroup() + .addContainerGap() + .addGroup(facePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(kdTreeLabel) + .addComponent(hasKDOutput)) + .addGap(18, 18, 18) + .addGroup(facePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(featurePointsLoadedLabel) + .addComponent(hasFPOutput)) + .addGap(56, 56, 56) + .addGroup(facePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(warningLabel) + .addComponent(faceNotLoadedLabel)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(loadFaceButton) + .addContainerGap(44, Short.MAX_VALUE)) + ); + + photoPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(null, org.openide.util.NbBundle.getMessage(FaceStatePanel.class, "FaceStatePanel.photoPanel.border.title"), javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, new java.awt.Font("Dialog", 1, 12))); // NOI18N + + photo.setIcon(new javax.swing.ImageIcon(getClass().getResource("/face160x160.png"))); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(photo, org.openide.util.NbBundle.getMessage(FaceStatePanel.class, "FaceStatePanel.photo.text")); // NOI18N + + javax.swing.GroupLayout photoPanelLayout = new javax.swing.GroupLayout(photoPanel); + photoPanel.setLayout(photoPanelLayout); + photoPanelLayout.setHorizontalGroup( + photoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(photoPanelLayout.createSequentialGroup() + .addGap(55, 55, 55) + .addComponent(photo) + .addGap(55, 55, 55)) + ); + photoPanelLayout.setVerticalGroup( + photoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(photoPanelLayout.createSequentialGroup() + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(photo) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(filePanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(facePanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(photoPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addContainerGap()) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addGap(6, 6, 6) + .addComponent(photoPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(filePanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(18, 18, 18) + .addComponent(facePanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addContainerGap()) + ); + + filePanel.getAccessibleContext().setAccessibleName(org.openide.util.NbBundle.getMessage(FaceStatePanel.class, "FaceStatePanel.filePanel.AccessibleContext.accessibleName")); // NOI18N + }// </editor-fold>//GEN-END:initComponents + + /** + * Shows face information on panel + * @param face HumanFace + * @param name String + * @param path Path + */ + public void showFaceState(HumanFace face, String name, Path path) { + + photo.setIcon(getPhoto(face, path)); + pathOutput.setText(getPathText(path)); + sizeOutput.setText(getSizeText(path)); + hasKDOutput.setIcon(getKdTree(face)); + hasFPOutput.setIcon(getFeaturePoints(face)); + checkFaceLoaded(face); + } + + @Override + public ImageIcon getIcon() { + return new ImageIcon(FaceStatePanel.class.getClassLoader().getResource("/" + ICON)); + } + + /** + * Gets photo which would be displayed on photo panel + * @param face HumanFace + * @param path Path + * @return ImageIcon either loaded face preview or anonymous face when preview is not found + */ + private ImageIcon getPhoto(HumanFace face, Path path) { + + ImageIcon image; + + if (face != null) { + if (face.getPreview() != null) { + return new ImageIcon(face.getPreview().getScaledInstance(240, 160, Image.SCALE_FAST)); + } + return anonymousFace; + } + + if (path != null && path.toFile().exists()) { + + String pathString = path.toString(); + Path preview = Paths.get(pathString.substring(0, pathString.lastIndexOf(".")).concat("_preview.jpg")); + + try { + image = new ImageIcon(ImageIO.read(preview.toFile()).getScaledInstance(240, 160, Image.SCALE_FAST)); + return image; + } catch (IOException ex) { + //Exceptions.printStackTrace(ex);) + } + } + return anonymousFace; + } + + /** + * Gets path text + * @param path Path + * @return String path + */ + private String getPathText(Path path) { + + if (path != null) { + pathLabel.setEnabled(true); + return path.toString(); + } + pathLabel.setEnabled(false); + return ""; + } + + /** + * Gets size of model ".obj" + * @param path Path + * @return String size in kB + */ + private String getSizeText(Path path) { + + if (path != null && path.toFile().exists()) { + + try { + long bytes = Files.size(path); + sizeLabel.setEnabled(true); + return String.format("%,d kB", bytes / 1024); + + } catch (IOException ex) { + //Exceptions.printStackTrace(ex); + // TODO HANDLE EXCEPTION + } + } + sizeLabel.setEnabled(false); + return ""; + } + + /** + * Gets icon which shows if face has calculated KD-tree + * @param face HumanFace + * @return ImageIcon either check or notCheck + */ + private ImageIcon getKdTree(HumanFace face) { + if (face == null) { + kdTreeLabel.setEnabled(false); + return null; + } + + kdTreeLabel.setEnabled(true); + if (face.hasKdTree()) { + return check; + } + return notCheck; + } + + /** + * Gets icon which shows if face has featurePoints + * @param face HumanFace + * @return ImageIcon either check or notCheck + */ + private ImageIcon getFeaturePoints(HumanFace face) { + + if (face == null) { + featurePointsLoadedLabel.setEnabled(false); + return null; + } + + featurePointsLoadedLabel.setEnabled(true); + if (face.hasFeaturePoints() || face.findLandmarks() != null) { + return check; + } + return notCheck; + } + + /** + * Checks whether face is loaded in project or not + * If not, button which loads currently selected face to project shows up + * @param face HumanFace + */ + private void checkFaceLoaded(HumanFace face) { + warningLabel.setVisible(face == null); + faceNotLoadedLabel.setVisible(face == null); + loadFaceButton.setVisible(face == null); + } + + /** + * All information is returned to basic value + */ + public void deselectFace() { + this.showFaceState(null, null, null); + warningLabel.setVisible(false); + faceNotLoadedLabel.setVisible(false); + loadFaceButton.setVisible(false); + } + + @Override + public void acceptEvent(ProjectEvent event) { + if (event.getClass() == FaceSelected.class) { + FaceSelected evt = (FaceSelected)event; + this.showFaceState(evt.getFace(), evt.getName(), evt.getPath()); + } else if (event.getClass() == FaceDeselected.class){ + this.deselectFace(); + } + } + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JLabel faceNotLoadedLabel; + private javax.swing.JPanel facePanel; + private javax.swing.JLabel featurePointsLoadedLabel; + private javax.swing.JPanel filePanel; + private javax.swing.JLabel hasFPOutput; + private javax.swing.JLabel hasKDOutput; + private javax.swing.JLabel kdTreeLabel; + private javax.swing.JButton loadFaceButton; + private javax.swing.JLabel pathLabel; + private javax.swing.JLabel pathOutput; + private javax.swing.JLabel photo; + private javax.swing.JPanel photoPanel; + private javax.swing.JLabel sizeLabel; + private javax.swing.JLabel sizeOutput; + private javax.swing.JLabel warningLabel; + // End of variables declaration//GEN-END:variables + +} diff --git a/GUI/src/main/java/cz/fidentis/analyst/project/FilterPanel.form b/GUI/src/main/java/cz/fidentis/analyst/project/FilterPanel.form new file mode 100644 index 00000000..7e703acc --- /dev/null +++ b/GUI/src/main/java/cz/fidentis/analyst/project/FilterPanel.form @@ -0,0 +1,183 @@ +<?xml version="1.0" encoding="UTF-8" ?> + +<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo"> + <AuxValues> + <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/> + <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/> + <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/> + <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/> + <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/> + <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/> + <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/> + <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/> + <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/> + </AuxValues> + + <Layout> + <DimensionLayout dim="0"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" alignment="0" attributes="0"> + <EmptySpace max="-2" attributes="0"/> + <Component id="filterPanel" max="32767" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + <DimensionLayout dim="1"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" alignment="0" attributes="0"> + <EmptySpace max="-2" attributes="0"/> + <Component id="filterPanel" min="-2" max="-2" attributes="0"/> + <EmptySpace pref="270" max="32767" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + </Layout> + <SubComponents> + <Container class="javax.swing.JPanel" name="filterPanel"> + <Properties> + <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor"> + <Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo"> + <TitledBorder title="<FilterPanel.filterPanel.border.title>"> + <ResourceString PropertyName="titleX" bundle="cz/fidentis/analyst/project/Bundle.properties" key="FilterPanel.filterPanel.border.title" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + <Font PropertyName="font" name="Dialog" size="12" style="1"/> + </TitledBorder> + </Border> + </Property> + </Properties> + + <Layout> + <DimensionLayout dim="0"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" alignment="0" attributes="0"> + <EmptySpace min="-2" pref="38" max="-2" attributes="0"/> + <Group type="103" groupAlignment="1" attributes="0"> + <Component id="applyFilterButton" min="-2" max="-2" attributes="0"/> + <Group type="103" groupAlignment="0" attributes="0"> + <Component id="alphabetical" min="-2" max="-2" attributes="0"/> + <Component id="hasKD" min="-2" max="-2" attributes="0"/> + <Component id="hasFP" min="-2" max="-2" attributes="0"/> + </Group> + </Group> + <EmptySpace pref="201" max="32767" attributes="0"/> + <Component id="loadAllModelsButton" min="-2" max="-2" attributes="0"/> + <EmptySpace min="-2" pref="89" max="-2" attributes="0"/> + </Group> + <Group type="102" alignment="1" attributes="0"> + <EmptySpace max="32767" attributes="0"/> + <Component id="warningLabel" min="-2" max="-2" attributes="0"/> + <EmptySpace type="unrelated" max="-2" attributes="0"/> + <Component id="faceNotLoadedLabel" min="-2" max="-2" attributes="0"/> + <EmptySpace min="-2" pref="22" max="-2" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + <DimensionLayout dim="1"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" alignment="0" attributes="0"> + <EmptySpace min="-2" pref="40" max="-2" attributes="0"/> + <Component id="hasFP" min="-2" max="-2" attributes="0"/> + <EmptySpace type="separate" max="-2" attributes="0"/> + <Component id="hasKD" min="-2" max="-2" attributes="0"/> + <EmptySpace type="separate" max="-2" attributes="0"/> + <Component id="alphabetical" min="-2" max="-2" attributes="0"/> + <EmptySpace min="-2" pref="19" max="-2" attributes="0"/> + <Group type="103" groupAlignment="1" attributes="0"> + <Component id="warningLabel" min="-2" max="-2" attributes="0"/> + <Component id="faceNotLoadedLabel" min="-2" max="-2" attributes="0"/> + </Group> + <EmptySpace min="-2" pref="23" max="-2" attributes="0"/> + <Group type="103" groupAlignment="3" attributes="0"> + <Component id="applyFilterButton" alignment="3" min="-2" max="-2" attributes="0"/> + <Component id="loadAllModelsButton" alignment="3" min="-2" max="-2" attributes="0"/> + </Group> + <EmptySpace pref="69" max="32767" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + </Layout> + <SubComponents> + <Component class="javax.swing.JCheckBox" name="hasFP"> + <Properties> + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="cz/fidentis/analyst/project/Bundle.properties" key="FilterPanel.hasFP.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + </Property> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="hasFPActionPerformed"/> + </Events> + </Component> + <Component class="javax.swing.JCheckBox" name="hasKD"> + <Properties> + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="cz/fidentis/analyst/project/Bundle.properties" key="FilterPanel.hasKD.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + </Property> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="hasKDActionPerformed"/> + </Events> + </Component> + <Component class="javax.swing.JCheckBox" name="alphabetical"> + <Properties> + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="cz/fidentis/analyst/project/Bundle.properties" key="FilterPanel.alphabetical.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + </Property> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="alphabeticalActionPerformed"/> + </Events> + </Component> + <Component class="javax.swing.JButton" name="applyFilterButton"> + <Properties> + <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor"> + <Font name="Tahoma" size="12" style="1"/> + </Property> + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="cz/fidentis/analyst/project/Bundle.properties" key="FilterPanel.applyFilterButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + </Property> + <Property name="enabled" type="boolean" value="false"/> + </Properties> + </Component> + <Component class="javax.swing.JLabel" name="warningLabel"> + <Properties> + <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor"> + <Image iconType="3" name="/warning16x16.png"/> + </Property> + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="cz/fidentis/analyst/project/Bundle.properties" key="FilterPanel.warningLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + </Property> + </Properties> + <AuxValues> + <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="warningLabel.setVisible(false);"/> + </AuxValues> + </Component> + <Component class="javax.swing.JLabel" name="faceNotLoadedLabel"> + <Properties> + <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor"> + <Font name="Tahoma" size="12" style="1"/> + </Property> + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="cz/fidentis/analyst/project/Bundle.properties" key="FilterPanel.faceNotLoadedLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + </Property> + </Properties> + <AuxValues> + <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="faceNotLoadedLabel.setVisible(false);"/> + </AuxValues> + </Component> + <Component class="javax.swing.JButton" name="loadAllModelsButton"> + <Properties> + <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor"> + <Font name="Tahoma" size="12" style="1"/> + </Property> + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="cz/fidentis/analyst/project/Bundle.properties" key="FilterPanel.loadAllModelsButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + </Property> + </Properties> + <AuxValues> + <AuxValue name="JavaCodeGenerator_ListenersCodePost" type="java.lang.String" value="loadAllModelsButton.setVisible(false);"/> + </AuxValues> + </Component> + </SubComponents> + </Container> + </SubComponents> +</Form> diff --git a/GUI/src/main/java/cz/fidentis/analyst/project/FilterPanel.java b/GUI/src/main/java/cz/fidentis/analyst/project/FilterPanel.java new file mode 100644 index 00000000..40911de8 --- /dev/null +++ b/GUI/src/main/java/cz/fidentis/analyst/project/FilterPanel.java @@ -0,0 +1,237 @@ +package cz.fidentis.analyst.project; + +import cz.fidentis.analyst.core.ControlPanel; +import cz.fidentis.analyst.project.events.AllFacesLoaded; +import cz.fidentis.analyst.project.events.ProjectEvent; +import cz.fidentis.analyst.project.events.ProjectListener; +import java.awt.event.ActionListener; +import javax.swing.ImageIcon; +import javax.swing.JCheckBox; + +/** + * + * @author Matej Kovar + */ +public class FilterPanel extends ControlPanel implements ProjectListener { + + private boolean kdTreeFilter = false; + private boolean featurePointsFilter = false; + private boolean alphabeticalFilter = false; + + + public static final String ICON = "filter28x28.png"; + public static final String NAME = "Filter"; + + /** + * Creates new form FilterPanel + */ + public FilterPanel(ActionListener listenerLoadAllFaces) { + this.setName(NAME); + initComponents(); + loadAllModelsButton.addActionListener(listenerLoadAllFaces); + //applyFilterButton.addActionListener(buttonListener); + } + + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents + private void initComponents() { + + filterPanel = new javax.swing.JPanel(); + hasFP = new javax.swing.JCheckBox(); + hasKD = new javax.swing.JCheckBox(); + alphabetical = new javax.swing.JCheckBox(); + applyFilterButton = new javax.swing.JButton(); + warningLabel = new javax.swing.JLabel(); + faceNotLoadedLabel = new javax.swing.JLabel(); + loadAllModelsButton = new javax.swing.JButton(); + + filterPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(null, org.openide.util.NbBundle.getMessage(FilterPanel.class, "FilterPanel.filterPanel.border.title"), javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, new java.awt.Font("Dialog", 1, 12))); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(hasFP, org.openide.util.NbBundle.getMessage(FilterPanel.class, "FilterPanel.hasFP.text")); // NOI18N + hasFP.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + hasFPActionPerformed(evt); + } + }); + + org.openide.awt.Mnemonics.setLocalizedText(hasKD, org.openide.util.NbBundle.getMessage(FilterPanel.class, "FilterPanel.hasKD.text")); // NOI18N + hasKD.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + hasKDActionPerformed(evt); + } + }); + + org.openide.awt.Mnemonics.setLocalizedText(alphabetical, org.openide.util.NbBundle.getMessage(FilterPanel.class, "FilterPanel.alphabetical.text")); // NOI18N + alphabetical.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + alphabeticalActionPerformed(evt); + } + }); + + applyFilterButton.setFont(new java.awt.Font("Tahoma", 1, 12)); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(applyFilterButton, org.openide.util.NbBundle.getMessage(FilterPanel.class, "FilterPanel.applyFilterButton.text")); // NOI18N + applyFilterButton.setEnabled(false); + + warningLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/warning16x16.png"))); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(warningLabel, org.openide.util.NbBundle.getMessage(FilterPanel.class, "FilterPanel.warningLabel.text")); // NOI18N + warningLabel.setVisible(false); + + faceNotLoadedLabel.setFont(new java.awt.Font("Tahoma", 1, 12)); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(faceNotLoadedLabel, org.openide.util.NbBundle.getMessage(FilterPanel.class, "FilterPanel.faceNotLoadedLabel.text")); // NOI18N + faceNotLoadedLabel.setVisible(false); + + loadAllModelsButton.setFont(new java.awt.Font("Tahoma", 1, 12)); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(loadAllModelsButton, org.openide.util.NbBundle.getMessage(FilterPanel.class, "FilterPanel.loadAllModelsButton.text")); // NOI18N + loadAllModelsButton.setVisible(false); + + javax.swing.GroupLayout filterPanelLayout = new javax.swing.GroupLayout(filterPanel); + filterPanel.setLayout(filterPanelLayout); + filterPanelLayout.setHorizontalGroup( + filterPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(filterPanelLayout.createSequentialGroup() + .addGap(38, 38, 38) + .addGroup(filterPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(applyFilterButton) + .addGroup(filterPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(alphabetical) + .addComponent(hasKD) + .addComponent(hasFP))) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 201, Short.MAX_VALUE) + .addComponent(loadAllModelsButton) + .addGap(89, 89, 89)) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, filterPanelLayout.createSequentialGroup() + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(warningLabel) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(faceNotLoadedLabel) + .addGap(22, 22, 22)) + ); + filterPanelLayout.setVerticalGroup( + filterPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(filterPanelLayout.createSequentialGroup() + .addGap(40, 40, 40) + .addComponent(hasFP) + .addGap(18, 18, 18) + .addComponent(hasKD) + .addGap(18, 18, 18) + .addComponent(alphabetical) + .addGap(19, 19, 19) + .addGroup(filterPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(warningLabel) + .addComponent(faceNotLoadedLabel)) + .addGap(23, 23, 23) + .addGroup(filterPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(applyFilterButton) + .addComponent(loadAllModelsButton)) + .addContainerGap(69, Short.MAX_VALUE)) + ); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addComponent(filterPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addContainerGap()) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addComponent(filterPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap(270, Short.MAX_VALUE)) + ); + }// </editor-fold>//GEN-END:initComponents + + /** + * Sets attribute to corresponding value based on checkbox + * @param evt + */ + private void hasFPActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_hasFPActionPerformed + featurePointsFilter = (((JCheckBox)evt.getSource()).isSelected()); + }//GEN-LAST:event_hasFPActionPerformed + + /** + * Sets attribute to corresponding value based on checkbox + * @param evt + */ + private void hasKDActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_hasKDActionPerformed + kdTreeFilter = (((JCheckBox)evt.getSource()).isSelected()); + }//GEN-LAST:event_hasKDActionPerformed + + /** + * Sets attribute to corresponding value based on checkbox + * @param evt + */ + private void alphabeticalActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_alphabeticalActionPerformed + alphabeticalFilter = (((JCheckBox)evt.getSource()).isSelected()); + }//GEN-LAST:event_alphabeticalActionPerformed + + @Override + public ImageIcon getIcon() { + return new ImageIcon(FilterPanel.class.getClassLoader().getResource("/" + ICON)); + } + + /** + * Sets ActionListener to apply filter button + * @param applyFilterListener ActionListener + */ + public void setFilterActionListener(ActionListener applyFilterListener) { + applyFilterButton.addActionListener(applyFilterListener); + } + + public boolean isKdTreeFilter() { + return kdTreeFilter; + } + + public boolean isFeaturePointsFilter() { + return featurePointsFilter; + } + + public boolean isAlphabeticalFilter() { + return alphabeticalFilter; + } + + /** + * Checks if all faces in list are loaded. If not, button which loads all + * faces from list shows up + * @param isAllFacesLoaded Boolean + */ + public void checkAllFacesLoaded(boolean isAllFacesLoaded) { + + warningLabel.setVisible(!isAllFacesLoaded); + faceNotLoadedLabel.setVisible(!isAllFacesLoaded); + loadAllModelsButton.setVisible(!isAllFacesLoaded); + applyFilterButton.setEnabled(isAllFacesLoaded); + } + + @Override + public void acceptEvent(ProjectEvent event) { + + if (event.getClass() == AllFacesLoaded.class) { + + AllFacesLoaded evt = (AllFacesLoaded)event; + this.checkAllFacesLoaded(evt.isAllFacesLoaded()); + } + } + + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JCheckBox alphabetical; + private javax.swing.JButton applyFilterButton; + private javax.swing.JLabel faceNotLoadedLabel; + private javax.swing.JPanel filterPanel; + private javax.swing.JCheckBox hasFP; + private javax.swing.JCheckBox hasKD; + private javax.swing.JButton loadAllModelsButton; + private javax.swing.JLabel warningLabel; + // End of variables declaration//GEN-END:variables + +} diff --git a/GUI/src/main/java/cz/fidentis/analyst/dashboard/ModelsTableModel.java b/GUI/src/main/java/cz/fidentis/analyst/project/ModelsTableModel.java similarity index 53% rename from GUI/src/main/java/cz/fidentis/analyst/dashboard/ModelsTableModel.java rename to GUI/src/main/java/cz/fidentis/analyst/project/ModelsTableModel.java index e7e979ed..ae5643e0 100644 --- a/GUI/src/main/java/cz/fidentis/analyst/dashboard/ModelsTableModel.java +++ b/GUI/src/main/java/cz/fidentis/analyst/project/ModelsTableModel.java @@ -1,21 +1,24 @@ -package cz.fidentis.analyst.dashboard; +package cz.fidentis.analyst.project; -import cz.fidentis.analyst.face.events.HumanFaceEvent; -import cz.fidentis.analyst.face.events.HumanFaceListener; -import cz.fidentis.analyst.face.events.KdTreeEvent; +import java.awt.Image; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.nio.file.Path; +import javax.imageio.ImageIO; import javax.swing.ImageIcon; import javax.swing.table.DefaultTableModel; +import org.openide.util.Exceptions; /** * List of faces TableModel * * @author Matej Kovar */ -public class ModelsTableModel extends DefaultTableModel implements HumanFaceListener { - - private final ImageIcon notCheck = new ImageIcon(FaceStatePanel.class.getClassLoader().getResource("/" + "notCheck16x16.png")); - private final ImageIcon check = new ImageIcon(FaceStatePanel.class.getClassLoader().getResource("/" + "check16x16.png")); +public class ModelsTableModel extends DefaultTableModel { + //private final ImageIcon notCheck = new ImageIcon(FaceStatePanel.class.getClassLoader().getResource("/" + "notCheck16x16.png")); + //private final ImageIcon check = new ImageIcon(FaceStatePanel.class.getClassLoader().getResource("/" + "check16x16.png")); + private final ImageIcon previewBasic = new ImageIcon(FaceStatePanel.class.getClassLoader().getResource("/" + "face32x32.png")); /** * Constructor * @param columnNames names of Columns @@ -60,17 +63,22 @@ public class ModelsTableModel extends DefaultTableModel implements HumanFaceList * @param name String name of the face * @param hasKD Boolean if face has KD tree calculated */ - public void addRowWithName(String name, boolean hasKD) { - if (hasKD) { - addRow(new Object[]{false, name, check}); + public void addRowWithName(String name, Path path) { + if (!path.toFile().exists()) { + addRow(new Object[]{false, name, previewBasic}); } else { - addRow(new Object[]{false, name, notCheck}); + try { + BufferedImage image = ImageIO.read(path.toFile()); + addRow(new Object[]{false, name, new ImageIcon(image.getScaledInstance(75, 50, Image.SCALE_FAST))}); + } catch (IOException ex) { + Exceptions.printStackTrace(ex); + } + } } /* * - public void sortAlphabeticaly() { List<String> rows = new ArrayList(); for (int i = 0; i < getRowCount(); i++) { @@ -79,25 +87,5 @@ public class ModelsTableModel extends DefaultTableModel implements HumanFaceList Collections.sort(rows); } */ - - @Override - public void acceptEvent(HumanFaceEvent event) { - if (!(event instanceof KdTreeEvent)) { - return; - } - KdTreeEvent ev = (KdTreeEvent) event; - String name = ev.getName(); - for (int i = 0; i < getRowCount(); i++) { - if (getValueAt(i, 1).equals(name)) { - if (ev.isCalculated()) { - this.setValueAt(check, i, 2); - } else { - this.setValueAt(notCheck, i, 2); - } - - break; - } - } - } } diff --git a/GUI/src/main/java/cz/fidentis/analyst/project/ProjectPanel.form b/GUI/src/main/java/cz/fidentis/analyst/project/ProjectPanel.form new file mode 100644 index 00000000..f6842bed --- /dev/null +++ b/GUI/src/main/java/cz/fidentis/analyst/project/ProjectPanel.form @@ -0,0 +1,322 @@ +<?xml version="1.0" encoding="UTF-8" ?> + +<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo"> + <AuxValues> + <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/> + <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/> + <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/> + <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/> + <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/> + <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/> + <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/> + <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/> + <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/> + </AuxValues> + + <Layout> + <DimensionLayout dim="0"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" alignment="0" attributes="0"> + <EmptySpace min="-2" pref="41" max="-2" attributes="0"/> + <Group type="103" groupAlignment="1" attributes="0"> + <Component id="saveProjectButton" min="-2" max="-2" attributes="0"/> + <Group type="102" alignment="1" attributes="0"> + <Group type="103" groupAlignment="0" max="-2" attributes="0"> + <Component id="buttonsPanel" alignment="0" max="32767" attributes="0"/> + <Component id="faceTableScrollPanel" alignment="0" min="-2" pref="863" max="-2" attributes="0"/> + </Group> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" alignment="0" attributes="0"> + <EmptySpace min="-2" pref="78" max="-2" attributes="0"/> + <Component id="newProjectButton" min="-2" max="-2" attributes="0"/> + </Group> + <Group type="102" alignment="1" attributes="0"> + <EmptySpace max="-2" attributes="0"/> + <Component id="openProjectButton" min="-2" max="-2" attributes="0"/> + </Group> + </Group> + </Group> + </Group> + <EmptySpace pref="41" max="32767" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + <DimensionLayout dim="1"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" alignment="0" attributes="0"> + <EmptySpace min="-2" pref="12" max="-2" attributes="0"/> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" alignment="0" attributes="0"> + <Component id="buttonsPanel" min="-2" max="-2" attributes="0"/> + <EmptySpace min="-2" pref="6" max="-2" attributes="0"/> + </Group> + <Group type="102" alignment="1" attributes="0"> + <Component id="newProjectButton" min="-2" max="-2" attributes="0"/> + <EmptySpace type="separate" max="-2" attributes="0"/> + </Group> + </Group> + <Group type="103" groupAlignment="0" attributes="0"> + <Component id="faceTableScrollPanel" min="-2" pref="768" max="-2" attributes="0"/> + <Group type="102" alignment="0" attributes="0"> + <Component id="saveProjectButton" min="-2" max="-2" attributes="0"/> + <EmptySpace type="separate" max="-2" attributes="0"/> + <Component id="openProjectButton" min="-2" max="-2" attributes="0"/> + </Group> + </Group> + <EmptySpace max="32767" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + </Layout> + <SubComponents> + <Container class="javax.swing.JPanel" name="buttonsPanel"> + <Properties> + <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor"> + <Border info="org.netbeans.modules.form.compat2.border.EtchedBorderInfo"> + <EtchetBorder/> + </Border> + </Property> + <Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor"> + <Dimension value="[0, 0]"/> + </Property> + </Properties> + + <Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/> + <SubComponents> + <Component class="javax.swing.JButton" name="addButton"> + <Properties> + <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor"> + <Font name="Tahoma" size="12" style="0"/> + </Property> + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="cz/fidentis/analyst/project/Bundle.properties" key="ProjectPanel.addButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + </Property> + </Properties> + <Events> + <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="addButtonMouseClicked"/> + </Events> + <Constraints> + <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription"> + <GridBagConstraints gridX="0" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="20" ipadY="0" insetsTop="16" insetsLeft="16" insetsBottom="13" insetsRight="4" anchor="13" weightX="0.0" weightY="0.0"/> + </Constraint> + </Constraints> + </Component> + <Component class="javax.swing.JButton" name="removeButton"> + <Properties> + <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor"> + <Font name="Tahoma" size="12" style="0"/> + </Property> + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="cz/fidentis/analyst/project/Bundle.properties" key="ProjectPanel.removeButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + </Property> + </Properties> + <Events> + <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="removeButtonMouseClicked"/> + </Events> + <Constraints> + <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription"> + <GridBagConstraints gridX="1" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="16" insetsLeft="22" insetsBottom="13" insetsRight="4" anchor="18" weightX="0.0" weightY="0.0"/> + </Constraint> + </Constraints> + </Component> + <Component class="javax.swing.JButton" name="selectAllButton"> + <Properties> + <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor"> + <Font name="Tahoma" size="12" style="0"/> + </Property> + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="cz/fidentis/analyst/project/Bundle.properties" key="ProjectPanel.selectAllButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + </Property> + </Properties> + <Events> + <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="selectAllButtonMouseClicked"/> + </Events> + <Constraints> + <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription"> + <GridBagConstraints gridX="2" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="16" insetsLeft="22" insetsBottom="13" insetsRight="4" anchor="18" weightX="0.0" weightY="0.0"/> + </Constraint> + </Constraints> + </Component> + <Component class="javax.swing.JButton" name="deselectAllButton"> + <Properties> + <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor"> + <Font name="Tahoma" size="12" style="0"/> + </Property> + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="cz/fidentis/analyst/project/Bundle.properties" key="ProjectPanel.deselectAllButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + </Property> + </Properties> + <Events> + <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="deselectAllButtonMouseClicked"/> + </Events> + <Constraints> + <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription"> + <GridBagConstraints gridX="3" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="16" insetsLeft="22" insetsBottom="13" insetsRight="4" anchor="18" weightX="0.0" weightY="0.0"/> + </Constraint> + </Constraints> + </Component> + <Component class="javax.swing.JButton" name="inflateButton"> + <Properties> + <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor"> + <Font name="Tahoma" size="12" style="0"/> + </Property> + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="cz/fidentis/analyst/project/Bundle.properties" key="ProjectPanel.inflateButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + </Property> + <Property name="alignmentX" type="float" value="0.5"/> + </Properties> + <Events> + <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="inflateButtonMouseClicked"/> + </Events> + <Constraints> + <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription"> + <GridBagConstraints gridX="4" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="16" insetsLeft="22" insetsBottom="13" insetsRight="4" anchor="18" weightX="0.0" weightY="0.0"/> + </Constraint> + </Constraints> + </Component> + <Component class="javax.swing.JButton" name="oneOnOneButton"> + <Properties> + <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor"> + <Font name="Tahoma" size="12" style="1"/> + </Property> + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="cz/fidentis/analyst/project/Bundle.properties" key="ProjectPanel.oneOnOneButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + </Property> + <Property name="alignmentX" type="float" value="0.5"/> + </Properties> + <Events> + <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="oneOnOneButtonMouseClicked"/> + </Events> + <Constraints> + <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription"> + <GridBagConstraints gridX="6" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="16" insetsLeft="11" insetsBottom="13" insetsRight="4" anchor="18" weightX="0.0" weightY="0.0"/> + </Constraint> + </Constraints> + </Component> + <Component class="javax.swing.JButton" name="manyToManyButton"> + <Properties> + <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor"> + <Font name="Tahoma" size="12" style="1"/> + </Property> + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="cz/fidentis/analyst/project/Bundle.properties" key="ProjectPanel.manyToManyButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + </Property> + </Properties> + <Events> + <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="manyToManyButtonMouseClicked"/> + </Events> + <Constraints> + <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription"> + <GridBagConstraints gridX="5" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="16" insetsLeft="30" insetsBottom="13" insetsRight="4" anchor="18" weightX="0.0" weightY="0.0"/> + </Constraint> + </Constraints> + </Component> + <Component class="javax.swing.JButton" name="analyseButton"> + <Properties> + <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor"> + <Font name="Tahoma" size="12" style="1"/> + </Property> + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="cz/fidentis/analyst/project/Bundle.properties" key="ProjectPanel.analyseButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + </Property> + </Properties> + <Events> + <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="analyseButtonMouseClicked"/> + </Events> + <Constraints> + <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription"> + <GridBagConstraints gridX="7" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="16" insetsLeft="11" insetsBottom="13" insetsRight="4" anchor="10" weightX="0.0" weightY="0.0"/> + </Constraint> + </Constraints> + </Component> + </SubComponents> + </Container> + <Container class="javax.swing.JScrollPane" name="faceTableScrollPanel"> + <Properties> + <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor"> + <Dimension value="[812, 750]"/> + </Property> + </Properties> + <AuxValues> + <AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/> + </AuxValues> + + <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/> + <SubComponents> + <Component class="javax.swing.JTable" name="table"> + <Properties> + <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor" postCode="table.getTableHeader().setOpaque(false);
table.getTableHeader().setBackground(new java.awt.Color(204,204,204));
table.getTableHeader().setFont(new java.awt.Font("Tahoma", 0, 18));
model.addTableModelListener(new TableModelListener() {
 public void tableChanged(TableModelEvent e) {
 jTable1TableChanged(e);
 }
});"> + <Font name="Tahoma" size="18" style="0"/> + </Property> + <Property name="model" type="javax.swing.table.TableModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor" postCode="table.getColumnModel().getColumn(0).setMaxWidth(50);
table.getColumnModel().getColumn(2).setMaxWidth(75);
table.getTableHeader().getColumnModel().getColumn(0).setMaxWidth(50);
table.getTableHeader().getColumnModel().getColumn(2).setMaxWidth(75);"> + <Connection code="model" type="code"/> + </Property> + <Property name="columnModel" type="javax.swing.table.TableColumnModel" editor="org.netbeans.modules.form.editors2.TableColumnModelEditor"> + <TableColumnModel selectionModel="0"/> + </Property> + <Property name="dragEnabled" type="boolean" value="true"/> + <Property name="rowHeight" type="int" value="60"/> + <Property name="selectionBackground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor"> + <Color blue="ff" green="cc" red="66" type="rgb"/> + </Property> + <Property name="selectionMode" type="int" value="0"/> + <Property name="tableHeader" type="javax.swing.table.JTableHeader" editor="org.netbeans.modules.form.editors2.JTableHeaderEditor"> + <TableHeader reorderingAllowed="false" resizingAllowed="true"/> + </Property> + </Properties> + <Events> + <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="tableMouseClicked"/> + </Events> + <AuxValues> + <AuxValue name="JavaCodeGenerator_InitCodePre" type="java.lang.String" value="table.setSize(faceTableScrollPanel.getWidth(), faceTableScrollPanel.getHeight());"/> + </AuxValues> + </Component> + </SubComponents> + </Container> + <Component class="javax.swing.JButton" name="saveProjectButton"> + <Properties> + <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor"> + <Font name="Tahoma" size="12" style="0"/> + </Property> + <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor"> + <Image iconType="3" name="/save100x24.png"/> + </Property> + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="cz/fidentis/analyst/project/Bundle.properties" key="ProjectPanel.saveProjectButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + </Property> + </Properties> + <Events> + <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="saveProjectButtonMouseClicked"/> + </Events> + </Component> + <Component class="javax.swing.JButton" name="openProjectButton"> + <Properties> + <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor"> + <Font name="Tahoma" size="12" style="0"/> + </Property> + <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor"> + <Image iconType="3" name="/open100x24.png"/> + </Property> + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="cz/fidentis/analyst/project/Bundle.properties" key="ProjectPanel.openProjectButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + </Property> + </Properties> + <Events> + <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="openProjectButtonMouseClicked"/> + </Events> + </Component> + <Component class="javax.swing.JButton" name="newProjectButton"> + <Properties> + <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor"> + <Image iconType="3" name="/new100x24.png"/> + </Property> + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="cz/fidentis/analyst/project/Bundle.properties" key="ProjectPanel.newProjectButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + </Property> + </Properties> + <Events> + <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="newProjectButtonMouseClicked"/> + </Events> + </Component> + </SubComponents> +</Form> diff --git a/GUI/src/main/java/cz/fidentis/analyst/core/ProjectTopComp.java b/GUI/src/main/java/cz/fidentis/analyst/project/ProjectPanel.java similarity index 68% rename from GUI/src/main/java/cz/fidentis/analyst/core/ProjectTopComp.java rename to GUI/src/main/java/cz/fidentis/analyst/project/ProjectPanel.java index 40caf20e..2d7a4632 100644 --- a/GUI/src/main/java/cz/fidentis/analyst/core/ProjectTopComp.java +++ b/GUI/src/main/java/cz/fidentis/analyst/project/ProjectPanel.java @@ -1,16 +1,16 @@ -package cz.fidentis.analyst.core; +package cz.fidentis.analyst.project; -import cz.fidentis.analyst.ProjectConfiguration; import com.fasterxml.jackson.databind.ObjectMapper; -import org.netbeans.api.settings.ConvertAsProperties; -import org.openide.awt.ActionID; -import org.openide.awt.ActionReference; -import org.openide.windows.TopComponent; -import org.openide.util.NbBundle.Messages; +import com.google.common.eventbus.EventBus; import cz.fidentis.analyst.Project; +import cz.fidentis.analyst.ProjectConfiguration; +import cz.fidentis.analyst.core.FaceTab; +import cz.fidentis.analyst.project.events.AllFacesLoaded; +import cz.fidentis.analyst.project.events.FaceDeselected; +import cz.fidentis.analyst.project.events.FaceSelected; +import cz.fidentis.analyst.project.events.ProjectListener; import cz.fidentis.analyst.face.HumanFace; -import cz.fidentis.analyst.dashboard.ModelsTableModel; -import cz.fidentis.analyst.dashboard.FilterPanel; +import cz.fidentis.analyst.face.events.HumanFaceEvent; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.File; @@ -24,6 +24,7 @@ import javax.swing.AbstractAction; import javax.swing.ImageIcon; import javax.swing.JFileChooser; import javax.swing.JOptionPane; +import javax.swing.JPanel; import javax.swing.event.TableModelEvent; import javax.swing.event.TableModelListener; import javax.swing.filechooser.FileNameExtensionFilter; @@ -31,77 +32,35 @@ import org.openide.filesystems.FileChooserBuilder; import org.openide.util.Exceptions; /** - * The main panel enabling analysts to select the primary and secondary faces, - * and to perform basic batch processing. This panel also serves as an entry - * point for detailed face analysis and face-to-face comparison. * * @author Matej Kovar */ -@ConvertAsProperties( - dtd = "-//cz.fidentis.analyst.gui//Dashboard//EN", - autostore = false -) -@TopComponent.Description( - preferredID = "ProjectTopComp", - //iconBase="SET/PATH/TO/ICON/HERE", - persistenceType = TopComponent.PERSISTENCE_ALWAYS -) -@TopComponent.Registration(mode = "editor", openAtStartup = true) -@ActionID(category = "Window", id = "cz.fidentis.analyst.gui.ProjectTopComp") -@ActionReference(path = "Menu/Window" /*, position = 333 */) -@TopComponent.OpenActionRegistration( - displayName = "#CTL_ProjectTopCompAction", - preferredID = "ProjectTopComp" -) -@Messages({ - "CTL_ProjectTopCompAction=Project", - "CTL_ProjectTopCompTopComponent=Project", - "HINT_ProjectTopCompTopComponent=This is a Project window" -}) -public final class ProjectTopComp extends TopComponent { - +public class ProjectPanel extends JPanel { + private Project project; private List<FaceTab> tabs = new ArrayList<>(); - private ModelsTableModel model = new ModelsTableModel(new Object[]{"", "Models", "KD-tree"}, 0); - - private FilterPanel fp; - + private ModelsTableModel model = new ModelsTableModel(new Object[]{"", "Models", "Preview"}, 0); + /* List of indexes of selected Rows */ private List<Integer> selectedRows = new ArrayList<>(); private ObjectMapper mapper = new ObjectMapper(); + private final transient EventBus eventBus; + /** - * Creates new ProjectTopComp, initializes new project + * Creates new form ProjectPanel */ - public ProjectTopComp() { - project = new Project(); - - initComponents(); - setName(Bundle.CTL_ProjectTopCompTopComponent()); - setToolTipText(Bundle.HINT_ProjectTopCompTopComponent()); - putClientProperty(TopComponent.PROP_CLOSING_DISABLED, Boolean.TRUE); - putClientProperty(TopComponent.PROP_DRAGGING_DISABLED, Boolean.TRUE); - putClientProperty(TopComponent.PROP_UNDOCKING_DISABLED, Boolean.TRUE); + public ProjectPanel() { - ActionListener listener = new AbstractAction() { - @Override - public void actionPerformed(ActionEvent e) { - applyFilter(); - } - }; + project = new Project(); - //fp = new FilterPanel(filterPanel, listener); + initComponents(); + eventBus = new EventBus(); - - // Execute infinite OutputWindowThread that redirects messages logged - // via Logger into the standard output window - OutputWindowThread.execute(); - openExistingOrNewProject(); - } /** @@ -109,12 +68,11 @@ public final class ProjectTopComp extends TopComponent { * WARNING: Do NOT modify this code. The content of this method is always * regenerated by the Form Editor. */ + @SuppressWarnings("unchecked") // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents private void initComponents() { java.awt.GridBagConstraints gridBagConstraints; - mainScrollPanel = new javax.swing.JScrollPane(); - mainPanel = new javax.swing.JPanel(); buttonsPanel = new javax.swing.JPanel(); addButton = new javax.swing.JButton(); removeButton = new javax.swing.JButton(); @@ -126,20 +84,16 @@ public final class ProjectTopComp extends TopComponent { analyseButton = new javax.swing.JButton(); faceTableScrollPanel = new javax.swing.JScrollPane(); table = new javax.swing.JTable(); - filterPanel = new javax.swing.JPanel(); - infoPanel = new javax.swing.JPanel(); saveProjectButton = new javax.swing.JButton(); openProjectButton = new javax.swing.JButton(); newProjectButton = new javax.swing.JButton(); - setOpaque(true); - buttonsPanel.setBorder(javax.swing.BorderFactory.createEtchedBorder()); buttonsPanel.setMinimumSize(new java.awt.Dimension(0, 0)); buttonsPanel.setLayout(new java.awt.GridBagLayout()); addButton.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N - org.openide.awt.Mnemonics.setLocalizedText(addButton, org.openide.util.NbBundle.getMessage(ProjectTopComp.class, "ProjectTopComp.addButton.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(addButton, org.openide.util.NbBundle.getMessage(ProjectPanel.class, "ProjectPanel.addButton.text")); // NOI18N addButton.addMouseListener(new java.awt.event.MouseAdapter() { public void mouseClicked(java.awt.event.MouseEvent evt) { addButtonMouseClicked(evt); @@ -154,7 +108,7 @@ public final class ProjectTopComp extends TopComponent { buttonsPanel.add(addButton, gridBagConstraints); removeButton.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N - org.openide.awt.Mnemonics.setLocalizedText(removeButton, org.openide.util.NbBundle.getMessage(ProjectTopComp.class, "ProjectTopComp.removeButton.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(removeButton, org.openide.util.NbBundle.getMessage(ProjectPanel.class, "ProjectPanel.removeButton.text")); // NOI18N removeButton.addMouseListener(new java.awt.event.MouseAdapter() { public void mouseClicked(java.awt.event.MouseEvent evt) { removeButtonMouseClicked(evt); @@ -168,7 +122,7 @@ public final class ProjectTopComp extends TopComponent { buttonsPanel.add(removeButton, gridBagConstraints); selectAllButton.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N - org.openide.awt.Mnemonics.setLocalizedText(selectAllButton, org.openide.util.NbBundle.getMessage(ProjectTopComp.class, "ProjectTopComp.selectAllButton.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(selectAllButton, org.openide.util.NbBundle.getMessage(ProjectPanel.class, "ProjectPanel.selectAllButton.text")); // NOI18N selectAllButton.addMouseListener(new java.awt.event.MouseAdapter() { public void mouseClicked(java.awt.event.MouseEvent evt) { selectAllButtonMouseClicked(evt); @@ -182,7 +136,7 @@ public final class ProjectTopComp extends TopComponent { buttonsPanel.add(selectAllButton, gridBagConstraints); deselectAllButton.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N - org.openide.awt.Mnemonics.setLocalizedText(deselectAllButton, org.openide.util.NbBundle.getMessage(ProjectTopComp.class, "ProjectTopComp.deselectAllButton.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(deselectAllButton, org.openide.util.NbBundle.getMessage(ProjectPanel.class, "ProjectPanel.deselectAllButton.text")); // NOI18N deselectAllButton.addMouseListener(new java.awt.event.MouseAdapter() { public void mouseClicked(java.awt.event.MouseEvent evt) { deselectAllButtonMouseClicked(evt); @@ -196,7 +150,7 @@ public final class ProjectTopComp extends TopComponent { buttonsPanel.add(deselectAllButton, gridBagConstraints); inflateButton.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N - org.openide.awt.Mnemonics.setLocalizedText(inflateButton, org.openide.util.NbBundle.getMessage(ProjectTopComp.class, "ProjectTopComp.inflateButton.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(inflateButton, org.openide.util.NbBundle.getMessage(ProjectPanel.class, "ProjectPanel.inflateButton.text")); // NOI18N inflateButton.setAlignmentX(0.5F); inflateButton.addMouseListener(new java.awt.event.MouseAdapter() { public void mouseClicked(java.awt.event.MouseEvent evt) { @@ -211,7 +165,7 @@ public final class ProjectTopComp extends TopComponent { buttonsPanel.add(inflateButton, gridBagConstraints); oneOnOneButton.setFont(new java.awt.Font("Tahoma", 1, 12)); // NOI18N - org.openide.awt.Mnemonics.setLocalizedText(oneOnOneButton, org.openide.util.NbBundle.getMessage(ProjectTopComp.class, "ProjectTopComp.oneOnOneButton.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(oneOnOneButton, org.openide.util.NbBundle.getMessage(ProjectPanel.class, "ProjectPanel.oneOnOneButton.text")); // NOI18N oneOnOneButton.setAlignmentX(0.5F); oneOnOneButton.addMouseListener(new java.awt.event.MouseAdapter() { public void mouseClicked(java.awt.event.MouseEvent evt) { @@ -226,7 +180,7 @@ public final class ProjectTopComp extends TopComponent { buttonsPanel.add(oneOnOneButton, gridBagConstraints); manyToManyButton.setFont(new java.awt.Font("Tahoma", 1, 12)); // NOI18N - org.openide.awt.Mnemonics.setLocalizedText(manyToManyButton, org.openide.util.NbBundle.getMessage(ProjectTopComp.class, "ProjectTopComp.manyToManyButton.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(manyToManyButton, org.openide.util.NbBundle.getMessage(ProjectPanel.class, "ProjectPanel.manyToManyButton.text")); // NOI18N manyToManyButton.addMouseListener(new java.awt.event.MouseAdapter() { public void mouseClicked(java.awt.event.MouseEvent evt) { manyToManyButtonMouseClicked(evt); @@ -240,7 +194,7 @@ public final class ProjectTopComp extends TopComponent { buttonsPanel.add(manyToManyButton, gridBagConstraints); analyseButton.setFont(new java.awt.Font("Tahoma", 1, 12)); // NOI18N - org.openide.awt.Mnemonics.setLocalizedText(analyseButton, org.openide.util.NbBundle.getMessage(ProjectTopComp.class, "ProjectTopComp.analyseButton.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(analyseButton, org.openide.util.NbBundle.getMessage(ProjectPanel.class, "ProjectPanel.analyseButton.text")); // NOI18N analyseButton.addMouseListener(new java.awt.event.MouseAdapter() { public void mouseClicked(java.awt.event.MouseEvent evt) { analyseButtonMouseClicked(evt); @@ -260,7 +214,6 @@ public final class ProjectTopComp extends TopComponent { table.getTableHeader().setBackground(new java.awt.Color(204,204,204)); table.getTableHeader().setFont(new java.awt.Font("Tahoma", 0, 18)); model.addTableModelListener(new TableModelListener() { - public void tableChanged(TableModelEvent e) { jTable1TableChanged(e); } @@ -271,7 +224,7 @@ public final class ProjectTopComp extends TopComponent { table.getTableHeader().getColumnModel().getColumn(0).setMaxWidth(50); table.getTableHeader().getColumnModel().getColumn(2).setMaxWidth(75); table.setDragEnabled(true); - table.setRowHeight(40); + table.setRowHeight(60); table.setSelectionBackground(new java.awt.Color(102, 204, 255)); table.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION); table.getTableHeader().setReorderingAllowed(false); @@ -282,40 +235,9 @@ public final class ProjectTopComp extends TopComponent { }); faceTableScrollPanel.setViewportView(table); - filterPanel.setBorder(javax.swing.BorderFactory.createEtchedBorder()); - filterPanel.setMaximumSize(new java.awt.Dimension(342, 424)); - filterPanel.setPreferredSize(new java.awt.Dimension(342, 424)); - - javax.swing.GroupLayout filterPanelLayout = new javax.swing.GroupLayout(filterPanel); - filterPanel.setLayout(filterPanelLayout); - filterPanelLayout.setHorizontalGroup( - filterPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGap(0, 359, Short.MAX_VALUE) - ); - filterPanelLayout.setVerticalGroup( - filterPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGap(0, 420, Short.MAX_VALUE) - ); - - infoPanel.setBorder(javax.swing.BorderFactory.createEtchedBorder()); - infoPanel.setPreferredSize(new java.awt.Dimension(349, 363)); - - javax.swing.GroupLayout infoPanelLayout = new javax.swing.GroupLayout(infoPanel); - infoPanel.setLayout(infoPanelLayout); - infoPanelLayout.setHorizontalGroup( - infoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGap(0, 0, Short.MAX_VALUE) - ); - infoPanelLayout.setVerticalGroup( - infoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGap(0, 312, Short.MAX_VALUE) - ); - - infoPanel.setVisible(false); - saveProjectButton.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N saveProjectButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/save100x24.png"))); // NOI18N - org.openide.awt.Mnemonics.setLocalizedText(saveProjectButton, org.openide.util.NbBundle.getMessage(ProjectTopComp.class, "ProjectTopComp.saveProjectButton.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(saveProjectButton, org.openide.util.NbBundle.getMessage(ProjectPanel.class, "ProjectPanel.saveProjectButton.text")); // NOI18N saveProjectButton.addMouseListener(new java.awt.event.MouseAdapter() { public void mouseClicked(java.awt.event.MouseEvent evt) { saveProjectButtonMouseClicked(evt); @@ -324,7 +246,7 @@ public final class ProjectTopComp extends TopComponent { openProjectButton.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N openProjectButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/open100x24.png"))); // NOI18N - org.openide.awt.Mnemonics.setLocalizedText(openProjectButton, org.openide.util.NbBundle.getMessage(ProjectTopComp.class, "ProjectTopComp.openProjectButton.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(openProjectButton, org.openide.util.NbBundle.getMessage(ProjectPanel.class, "ProjectPanel.openProjectButton.text")); // NOI18N openProjectButton.addMouseListener(new java.awt.event.MouseAdapter() { public void mouseClicked(java.awt.event.MouseEvent evt) { openProjectButtonMouseClicked(evt); @@ -332,113 +254,137 @@ public final class ProjectTopComp extends TopComponent { }); newProjectButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/new100x24.png"))); // NOI18N - org.openide.awt.Mnemonics.setLocalizedText(newProjectButton, org.openide.util.NbBundle.getMessage(ProjectTopComp.class, "ProjectTopComp.newProjectButton.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(newProjectButton, org.openide.util.NbBundle.getMessage(ProjectPanel.class, "ProjectPanel.newProjectButton.text")); // NOI18N newProjectButton.addMouseListener(new java.awt.event.MouseAdapter() { public void mouseClicked(java.awt.event.MouseEvent evt) { newProjectButtonMouseClicked(evt); } }); - javax.swing.GroupLayout mainPanelLayout = new javax.swing.GroupLayout(mainPanel); - mainPanel.setLayout(mainPanelLayout); - mainPanelLayout.setHorizontalGroup( - mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(mainPanelLayout.createSequentialGroup() - .addContainerGap() - .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) - .addComponent(buttonsPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(faceTableScrollPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 863, Short.MAX_VALUE)) - .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) - .addGroup(mainPanelLayout.createSequentialGroup() - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 52, Short.MAX_VALUE) - .addComponent(newProjectButton) - .addGap(18, 18, 18) - .addComponent(saveProjectButton) - .addGap(18, 18, 18) - .addComponent(openProjectButton)) - .addGroup(mainPanelLayout.createSequentialGroup() - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) - .addComponent(filterPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 363, Short.MAX_VALUE) - .addComponent(infoPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 363, Short.MAX_VALUE)))) - .addGap(20, 20, 20)) - ); - mainPanelLayout.setVerticalGroup( - mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(mainPanelLayout.createSequentialGroup() - .addContainerGap() - .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(mainPanelLayout.createSequentialGroup() - .addComponent(buttonsPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addGap(6, 6, 6)) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, mainPanelLayout.createSequentialGroup() - .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(saveProjectButton) - .addComponent(openProjectButton)) - .addGap(18, 18, 18))) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, mainPanelLayout.createSequentialGroup() - .addComponent(newProjectButton) - .addGap(18, 18, 18))) - .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) - .addGroup(mainPanelLayout.createSequentialGroup() - .addComponent(filterPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addGap(28, 28, 28) - .addComponent(infoPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 316, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addComponent(faceTableScrollPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) - .addContainerGap()) - ); - - saveProjectButton.getAccessibleContext().setAccessibleName(org.openide.util.NbBundle.getMessage(ProjectTopComp.class, "ProjectTopComp.saveProjectButton.AccessibleContext.accessibleName")); // NOI18N - - mainScrollPanel.setViewportView(mainPanel); - - mainScrollPanel.setSize(ControlPanel.CONTROL_PANEL_WIDTH, ControlPanel.HEIGHT); - javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(mainScrollPanel, javax.swing.GroupLayout.Alignment.TRAILING) + .addGroup(layout.createSequentialGroup() + .addGap(41, 41, 41) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(saveProjectButton) + .addGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addComponent(buttonsPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(faceTableScrollPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 863, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addGap(78, 78, 78) + .addComponent(newProjectButton)) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(openProjectButton))))) + .addContainerGap(41, Short.MAX_VALUE)) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(mainScrollPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 871, Short.MAX_VALUE) + .addGroup(layout.createSequentialGroup() + .addGap(12, 12, 12) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(buttonsPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(6, 6, 6)) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addComponent(newProjectButton) + .addGap(18, 18, 18))) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(faceTableScrollPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 768, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGroup(layout.createSequentialGroup() + .addComponent(saveProjectButton) + .addGap(18, 18, 18) + .addComponent(openProjectButton))) + .addContainerGap(12, Short.MAX_VALUE)) ); }// </editor-fold>//GEN-END:initComponents - /** - * Opens many to many tab - * @param evt - */ + public boolean isProjectSaved() { + return project.isSaved(); + } + + + private void newProjectButtonMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_newProjectButtonMouseClicked + if (loadNewProject()) { + newProject(); + } + }//GEN-LAST:event_newProjectButtonMouseClicked + + private void openProjectButtonMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_openProjectButtonMouseClicked + if (loadNewProject()) { + openProject(); + } + }//GEN-LAST:event_openProjectButtonMouseClicked + + private void saveProjectButtonMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_saveProjectButtonMouseClicked + saveProject(); + }//GEN-LAST:event_saveProjectButtonMouseClicked + + private void tableMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_tableMouseClicked + if (table.getSelectedRowCount() == 0) { + checkFaceState(null, false); + } else { + if (evt.getClickCount() == 2) { + deselectAllRows(); + model.setValueAt(true, table.getSelectedRow(), 0); + analyseButtonMouseClicked(evt); + } + checkFaceState(table.getValueAt(table.getSelectedRow(), 1).toString(), true); + + } + }//GEN-LAST:event_tableMouseClicked + + private void analyseButtonMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_analyseButtonMouseClicked + + if (selectedRows.size() == 1) { + + String name = model.getValueAt(selectedRows.get(0), 1).toString(); + HumanFace face = project.loadFace(name); + + if (project.getFaceByName(name) == null) { + project.addFace(face); + } + + + + createSingleFaceTab(face, name, false); + } else { + JOptionPane.showMessageDialog(this, "Select one model"); + } + }//GEN-LAST:event_analyseButtonMouseClicked + private void manyToManyButtonMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_manyToManyButtonMouseClicked - createManyToManyTab("N:N"); + createManyToManyTab("N:N"); }//GEN-LAST:event_manyToManyButtonMouseClicked - /** - * Opens 1:1 tab with two selected faces, otherwise pops message that you - * should select two faces - * @param evt - */ - private void oneOnOneButton1MouseClicked(java.awt.event.MouseEvent evt) { - //loadTwoModels(); + private void oneOnOneButtonMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_oneOnOneButtonMouseClicked if (selectedRows.size() == 2) { String name1 = model.getValueAt(selectedRows.get(0), 1).toString(); String name2 = model.getValueAt(selectedRows.get(1), 1).toString(); - HumanFace face1 = project.getFaceByName(name1); - HumanFace face2 = project.getFaceByName(name2); + + HumanFace face1 = project.loadFace(name1); + HumanFace face2 = project.loadFace(name2); + + if (project.getFaceByName(name1) == null) { + project.addFace(face1); + } + + if (project.getFaceByName(name2) == null) { + project.addFace(face2); + } + createFaceToFaceTab(face1, face2, name1 + ":" + name2, false); } else { JOptionPane.showMessageDialog(this, "Select two models"); } - } + }//GEN-LAST:event_oneOnOneButtonMouseClicked - /** - * Inflates models (selected will be deselected and vice versa) - * @param evt - */ private void inflateButtonMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_inflateButtonMouseClicked for (int i = 0; i < model.getRowCount(); i++) { @@ -450,45 +396,59 @@ public final class ProjectTopComp extends TopComponent { } }//GEN-LAST:event_inflateButtonMouseClicked - /** - * Deselects all models from list of models - * @param evt - */ private void deselectAllButtonMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_deselectAllButtonMouseClicked deselectAllRows(); }//GEN-LAST:event_deselectAllButtonMouseClicked - /** - * Deselects all rows - * TODO : deselect only rows which are selected (checking row by row is slow) - */ - private void deselectAllRows() { - for (int i = 0; i < model.getRowCount(); i++) { - model.setValueAt(false, i, 0); - } - } - - /** - * Selects all models from list of models - * @param evt - */ private void selectAllButtonMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_selectAllButtonMouseClicked for (int i = 0; i < model.getRowCount(); i++) { model.setValueAt(true, i, 0); } }//GEN-LAST:event_selectAllButtonMouseClicked -//GEN-FIRST:event_removeButton1MouseClicked - /** - * Removes selected models from list and project - * @param evt Removes selected faces - */ - private void removeButtonMouseClicked(java.awt.event.MouseEvent evt) { + private void removeButtonMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_removeButtonMouseClicked removeSelectedFaces(); - } -//GEN-LAST:event_removeButton1MouseClicked + }//GEN-LAST:event_removeButtonMouseClicked + + private void addButtonMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_addButtonMouseClicked + loadModel(false); + }//GEN-LAST:event_addButtonMouseClicked /** + * Registers listeners (objects concerned in the project changes) to receive events. + * If listener is {@code null}, no exception is thrown and no action is taken. + * + * @param listener Listener concerned in the project changes. + */ + public void registerListener(ProjectListener listener) { + if (eventBus != null) { + eventBus.register(listener); + } + } + + /** + * Unregisters listeners from receiving events. + * + * @param listener Registered listener + */ + public void unregisterListener(ProjectListener listener) { + if (eventBus != null) { + eventBus.unregister(listener); + } + } + + /** + * Broadcast event to registered listeners. + * + * @param evt Event to be triggered. + */ + public void announceEvent(HumanFaceEvent evt) { + if (evt != null && eventBus != null) { + eventBus.post(evt); + } + } + + /** * Removes selected faces (those which are checked in check boxes) */ private void removeSelectedFaces() { @@ -507,120 +467,19 @@ public final class ProjectTopComp extends TopComponent { project.removeFaceByName(name); model.removeRow(row); }); - selectedRows.clear(); - this.requestActive(); + selectedRows.clear(); } - - /** - * Adds new model - * @param evt - */ - private void addButtonMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_addButtonMouseClicked - loadModel(true); - }//GEN-LAST:event_addButtonMouseClicked - - /** - * Shows face state panel after clicking on face in list. Also double-click - * on face opens Analyze tab for clicked face - * @param evt - */ - private void tableMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_tableMouseClicked - if (table.getSelectedRow() == -1) { - infoPanel.setVisible(false); - } else { - - if (evt.getClickCount() == 2) { - deselectAllRows(); - model.setValueAt(true, table.getSelectedRow(), 0); - analyseButtonMouseClicked(evt); - } - infoPanel.setVisible(true); - checkFaceState(table.getValueAt(table.getSelectedRow(), 1).toString()); - } - }//GEN-LAST:event_tableMouseClicked - - /** - * Saves current project - * @param evt - */ - private void saveProjectButtonMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_saveProjectButtonMouseClicked - saveProject(); - }//GEN-LAST:event_saveProjectButtonMouseClicked - - /** - * Open new project - * @param evt - */ - private void openProjectButtonMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_openProjectButtonMouseClicked - if (loadNewProject()) { - openProject(); - } - }//GEN-LAST:event_openProjectButtonMouseClicked - - /** - * Creates new project - * @param evt - */ - private void newProjectButtonMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_newProjectButtonMouseClicked - if (loadNewProject()) { - newProject(); - } - }//GEN-LAST:event_newProjectButtonMouseClicked - + /** - * Opens 1:1 tab with two selected faces, otherwise pops message that you - * should select two faces - * @param evt + * Deselects all rows + * TODO : deselect only rows which are selected (checking row by row is slow) */ - private void oneOnOneButtonMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_oneOnOneButtonMouseClicked - - if (selectedRows.size() == 2) { - - String name1 = model.getValueAt(selectedRows.get(0), 1).toString(); - String name2 = model.getValueAt(selectedRows.get(1), 1).toString(); - - HumanFace face1 = project.loadFace(name1); - HumanFace face2 = project.loadFace(name2); - - if (project.getFaceByName(name1) == null) { - face1.registerListener(model); - project.addFace(face1); - } - - if (project.getFaceByName(name2) == null) { - face2.registerListener(model); - project.addFace(face2); - } - - createFaceToFaceTab(face1, face2, name1 + ":" + name2, false); - } else { - JOptionPane.showMessageDialog(this, "Select two models"); + private void deselectAllRows() { + for (int i = 0; i < model.getRowCount(); i++) { + model.setValueAt(false, i, 0); } - }//GEN-LAST:event_oneOnOneButtonMouseClicked - + } - /** - * Opens analysis of one selected face, otherwise pops message dialog that - * you should select just one face - * @param evt - */ - private void analyseButtonMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_analyseButtonMouseClicked - - if (selectedRows.size() == 1) { - - String name = model.getValueAt(selectedRows.get(0), 1).toString(); - HumanFace face = project.loadFace(name); - if (project.getFaceByName(name) == null) { - face.registerListener(model); - project.addFace(face); - } - - createSingleFaceTab(face, name, false); - } else { - JOptionPane.showMessageDialog(this, "Select one model"); - } - }//GEN-LAST:event_analyseButtonMouseClicked - /** * Updates selectedRows - adds new selected rows or removes deselected rows * @param e TableModelEvent @@ -643,49 +502,8 @@ public final class ProjectTopComp extends TopComponent { project.setSaved(false); } } - - // Variables declaration - do not modify//GEN-BEGIN:variables - private javax.swing.JButton addButton; - private javax.swing.JButton analyseButton; - private javax.swing.JPanel buttonsPanel; - private javax.swing.JButton deselectAllButton; - private javax.swing.JScrollPane faceTableScrollPanel; - private javax.swing.JPanel filterPanel; - private javax.swing.JButton inflateButton; - private javax.swing.JPanel infoPanel; - private javax.swing.JPanel mainPanel; - private javax.swing.JScrollPane mainScrollPanel; - private javax.swing.JButton manyToManyButton; - private javax.swing.JButton newProjectButton; - private javax.swing.JButton oneOnOneButton; - private javax.swing.JButton openProjectButton; - private javax.swing.JButton removeButton; - private javax.swing.JButton saveProjectButton; - private javax.swing.JButton selectAllButton; - private javax.swing.JTable table; - // End of variables declaration//GEN-END:variables - @Override - public void componentOpened() { - // TODO add custom code on component opening - } - - @Override - public void componentClosed() { - // TODO add custom code on component closing - } - - void writeProperties(java.util.Properties p) { - // better to version settings since initial version as advocated at - // http://wiki.apidesign.org/wiki/PropertyFiles - p.setProperty("version", "1.0"); - // TODO store your settings - } - - void readProperties(java.util.Properties p) { - String version = p.getProperty("version"); - // TODO read your settings according to their version - } + /** * Loads model selected in file chooser by user * @param loadFromFile true if models are loaded from file, else user chooses @@ -695,7 +513,7 @@ public final class ProjectTopComp extends TopComponent { File[] files; // Selects files with faces (by dialog or from JSON file) - if (loadFromFile) { + if (!loadFromFile) { files = new FileChooserBuilder(ProjectTopComp.class) .setTitle("Open human face(s)") .setDefaultWorkingDirectory(new File(System.getProperty("user.home"))) @@ -716,8 +534,17 @@ public final class ProjectTopComp extends TopComponent { Path path = Paths.get(file.getAbsolutePath()); String name = path.toString().substring(path.toString().lastIndexOf(File.separatorChar) + 1, path.toString().lastIndexOf('.')); + if (project.addNewPath(path)) { - model.addRowWithName(name, false); + + String pathString = path.toString(); + Path preview = Paths.get(pathString.substring(0, pathString.lastIndexOf(".")).concat("_preview_small.png")); + + model.addRowWithName(name, preview); + + if (eventBus != null) { + eventBus.post(new AllFacesLoaded(false)); + } } else { JOptionPane.showMessageDialog(this, String.format("Model with name %s is already loaded", name)); } @@ -743,13 +570,32 @@ public final class ProjectTopComp extends TopComponent { }); }); - this.toFront(); - this.openAtTabPosition(0); - this.requestActive(); - } - - /** + + /** + * Checks whether face is already loaded in some tab and if it is different tab + * (different tabName) than opens this face again from file (copy of face) + * @param tabName String name of tab which is about to be opened + * @param face HumanFace which will be in tab + * @return either loaded face from project or newly opened face from file + */ + private HumanFace getLoadedOrNewFace(String tabName, HumanFace face) { + for (FaceTab t : tabs) { + + if (t.hasFace(face.getShortName()) && !t.getName().equals(tabName)) { + + try { + return new HumanFace(Paths.get(face.getPath()).toFile(), true); + + } catch (IOException ex) { + Exceptions.printStackTrace(ex); + } + } + } + return face; + } + + /** * Creates and opens tab with one face * @param face which will be analyzed * @param name name of the tab (name of the model) @@ -760,8 +606,12 @@ public final class ProjectTopComp extends TopComponent { public void actionPerformed(ActionEvent e) { closeTab(e); } + }; + + face = getLoadedOrNewFace(name, face); FaceTab newTab = new FaceTab(face, null, name, tabCloseListener); + if (!tabs.contains(newTab)) { tabs.add(newTab); @@ -771,9 +621,15 @@ public final class ProjectTopComp extends TopComponent { newTab.open(); newTab.requestActive(); this.project.setSaved(false); + areAllFacesLoadedToProject(); + + } else { + + tabs.stream().filter(t -> (t.equals(newTab))).forEachOrdered(t -> { + t.requestActive(); + }); } } - /** * Creates and opens tab with two faces (1:1 analysis) * @param face1 which will be analyzed @@ -788,17 +644,25 @@ public final class ProjectTopComp extends TopComponent { } }; + face1 = getLoadedOrNewFace(nameOfTab, face1); + face2 = getLoadedOrNewFace(nameOfTab, face2); FaceTab newTab = new FaceTab(face1, face2, nameOfTab, tabCloseListener); if (!tabs.contains(newTab)) { - tabs.add(newTab); + + tabs.add(newTab); if (!loadFromFile) { project.addNewFaceToFaceTabFace(face1.getShortName(), face2.getShortName()); } newTab.open(); newTab.requestActive(); this.project.setSaved(false); + areAllFacesLoadedToProject(); + } else { + tabs.stream().filter(t -> (t.equals(newTab))).forEachOrdered(t -> { + t.requestActive(); + }); } } @@ -825,10 +689,21 @@ public final class ProjectTopComp extends TopComponent { /** * Opens info panel with face state information * @param faceName String name of face + * @param selected Boolean true if some face is selected from list, false otherwise */ - private void checkFaceState(String faceName) { - HumanFace face = project.getFaceByName(faceName); - //FaceStatePanel fsp = new FaceStatePanel(infoPanel, face); + private void checkFaceState(String faceName, boolean selected) { + + if (eventBus != null) { + + if (selected) { + HumanFace face = project.getFaceByName(faceName); + Path path = project.getCfg().getPathToFaceByName(faceName); + eventBus.post(new FaceSelected(face, faceName, path)); + } else { + eventBus.post(new FaceDeselected()); + } + + } } @@ -853,7 +728,9 @@ public final class ProjectTopComp extends TopComponent { Collections.sort(names); names.forEach(name -> { HumanFace face = project.getFaceByName(name); - model.addRowWithName(name, face.hasKdTree()); + String pathString = face.getPath(); + Path preview = Paths.get(pathString.substring(0, pathString.lastIndexOf(".")).concat("_preview.jpg")); + model.addRowWithName(name, preview); }); } @@ -861,19 +738,19 @@ public final class ProjectTopComp extends TopComponent { /** * Removes faces from project (and table of faces) based on filter configuration */ - private void applyFilter() { + public void applyFilter(boolean isFeaturePointsFilter, boolean isKdTreeFilter, boolean isAlphaBeticalFilter) { deselectAllRows(); - + for (int i = 0; i < model.getRowCount(); i++) { HumanFace face = project.getFaceByName(model.getValueAt(i, 1).toString()); - if ((fp.isKdTreeFilter() && !face.hasKdTree()) || (fp.isFeaturePointsFilter() && !face.hasFeaturePoints())) { + if ((isKdTreeFilter && !face.hasKdTree()) || (isFeaturePointsFilter && !face.hasFeaturePoints())) { model.setValueAt(true, i, 0); } } removeSelectedFaces(); - if (fp.isAlphaBeticalFilter()) { + if (isAlphaBeticalFilter) { alphabeticalFilter(); } } @@ -911,6 +788,7 @@ public final class ProjectTopComp extends TopComponent { } project.removeAll(); model.setRowCount(0); + checkFaceState(null, false); selectedRows.clear(); } @@ -941,7 +819,7 @@ public final class ProjectTopComp extends TopComponent { /** * Saves current project */ - private void saveProject() { + public void saveProject() { JFileChooser chooser = new JFileChooser(); //chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); @@ -984,7 +862,7 @@ public final class ProjectTopComp extends TopComponent { try { resetProject(); project.setCfg(mapper.readValue(f, ProjectConfiguration.class)); - loadModel(false); + loadModel(true); loadTabs(); project.setSaved(true); } catch (IOException ex) { @@ -1023,21 +901,71 @@ public final class ProjectTopComp extends TopComponent { } } - this.requestActive(); + //this.requestActive(); } - @Override - public boolean canClose() { - if (!project.isSaved()) { - - int save = JOptionPane.showConfirmDialog(null, - "Project is not saved. Would you like to save project?", "Save project", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE); - - if (save == JOptionPane.YES_OPTION) { - saveProject(); + /** + * Loads currently selected (clicked in table) face to project + */ + public void loadCurrentlySelectedFace() { + String name = table.getValueAt(table.getSelectedRow(), 1).toString(); + project.loadFace(name); + checkFaceState(name, true); + areAllFacesLoadedToProject(); + } + + /** + * Checks whether all faces from list are loaded to project and informs listeners + */ + public void areAllFacesLoadedToProject() { + + for (int i = 0; i < model.getRowCount(); i++) { + HumanFace face = project.getFaceByName(model.getValueAt(i, 1).toString()); + + if (face == null) { + if (eventBus != null) { + eventBus.post(new AllFacesLoaded(false)); + } + return; } } - return super.canClose(); //To change body of generated methods, choose Tools | Templates. + + if (eventBus != null) { + eventBus.post(new AllFacesLoaded(true)); + } } + + /** + * Loads all faces from list to project and informs project listeners about it + */ + public void loadAllFaces() { + + for (int i = 0; i < model.getRowCount(); i++) { + + String name = model.getValueAt(i, 1).toString(); + project.loadFace(name); + } + + if (eventBus != null) { + eventBus.post(new AllFacesLoaded(true)); + } + } + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton addButton; + private javax.swing.JButton analyseButton; + private javax.swing.JPanel buttonsPanel; + private javax.swing.JButton deselectAllButton; + private javax.swing.JScrollPane faceTableScrollPanel; + private javax.swing.JButton inflateButton; + private javax.swing.JButton manyToManyButton; + private javax.swing.JButton newProjectButton; + private javax.swing.JButton oneOnOneButton; + private javax.swing.JButton openProjectButton; + private javax.swing.JButton removeButton; + private javax.swing.JButton saveProjectButton; + private javax.swing.JButton selectAllButton; + private javax.swing.JTable table; + // End of variables declaration//GEN-END:variables } diff --git a/GUI/src/main/java/cz/fidentis/analyst/project/ProjectTopComp.java b/GUI/src/main/java/cz/fidentis/analyst/project/ProjectTopComp.java new file mode 100644 index 00000000..f2b68bd7 --- /dev/null +++ b/GUI/src/main/java/cz/fidentis/analyst/project/ProjectTopComp.java @@ -0,0 +1,184 @@ +package cz.fidentis.analyst.project; + +import cz.fidentis.analyst.core.ControlPanel; +import cz.fidentis.analyst.core.OutputWindowThread; +import cz.fidentis.analyst.core.TopControlPanel; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import javax.swing.AbstractAction; +import javax.swing.GroupLayout; +import javax.swing.JScrollPane; +import javax.swing.LayoutStyle; +import org.netbeans.api.settings.ConvertAsProperties; +import org.openide.awt.ActionID; +import org.openide.awt.ActionReference; +import org.openide.util.NbBundle.Messages; +import org.openide.windows.TopComponent; + +/** + * The main panel enabling analysts to select the primary and secondary faces, + * and to perform basic batch processing. This panel also serves as an entry + * point for detailed face analysis and face-to-face comparison. + * + * @author Matej Kovar + */ +@ConvertAsProperties( + dtd = "-//cz.fidentis.analyst.gui//Dashboard//EN", + autostore = false +) +@TopComponent.Description( + preferredID = "ProjectTopComp", + //iconBase="SET/PATH/TO/ICON/HERE", + persistenceType = TopComponent.PERSISTENCE_ALWAYS +) +@TopComponent.Registration(mode = "editor", openAtStartup = true) +@ActionID(category = "Window", id = "cz.fidentis.analyst.gui.ProjectTopComp") +@ActionReference(path = "Menu/Window" /*, position = 333 */) +@TopComponent.OpenActionRegistration( + displayName = "#CTL_ProjectTopCompAction", + preferredID = "ProjectTopComp" +) +@Messages({ + "CTL_ProjectTopCompAction=Project", + "CTL_ProjectTopCompTopComponent=Project", + "HINT_ProjectTopCompTopComponent=This is a Project window" +}) +public final class ProjectTopComp extends TopComponent { + + private final ProjectPanel projectPanel; + private final TopControlPanel controlPanel; + private final JScrollPane projectPanelScrollPane; + private final JScrollPane controlPanelScrollPane; + + /** + * Project Top Component + */ + public ProjectTopComp() { + + setName(Bundle.CTL_ProjectTopCompTopComponent()); + setToolTipText(Bundle.HINT_ProjectTopCompTopComponent()); + putClientProperty(TopComponent.PROP_CLOSING_DISABLED, Boolean.TRUE); + putClientProperty(TopComponent.PROP_DRAGGING_DISABLED, Boolean.TRUE); + putClientProperty(TopComponent.PROP_UNDOCKING_DISABLED, Boolean.TRUE); + + projectPanel = new ProjectPanel(); + controlPanel = new TopControlPanel(); + projectPanelScrollPane = new JScrollPane(projectPanel); + controlPanelScrollPane = new JScrollPane(controlPanel); + + initComponents(); + + + OutputWindowThread.execute(); + + // Face State Panel + + // Listener for loading currently selected face (to show face state) + ActionListener listenerLoadFace = new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + projectPanel.loadCurrentlySelectedFace(); + } + }; + + FaceStatePanel facePanel = new FaceStatePanel(listenerLoadFace); + this.controlPanel.addTab(facePanel.getName(), facePanel.getIcon(), facePanel); + this.controlPanel.setSelectedComponent(facePanel); + projectPanel.registerListener(facePanel); + + // Filter Panel + + // Listener for loading all faces - to enable filtering + ActionListener listenerLoadAllFaces = new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + projectPanel.loadAllFaces(); + } + }; + + FilterPanel filterPanel = new FilterPanel(listenerLoadAllFaces); + this.controlPanel.addTab(filterPanel.getName(), filterPanel.getIcon(), filterPanel); + + // Listener for applying filter on faces + ActionListener listenerFilter = new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + projectPanel.applyFilter(filterPanel.isFeaturePointsFilter(), filterPanel.isKdTreeFilter(), filterPanel.isAlphabeticalFilter()); + } + }; + + projectPanel.registerListener(filterPanel); + filterPanel.setFilterActionListener(listenerFilter); + + this.openAtTabPosition(0); + this.toFront(); + this.requestActive(); + + } + + private void initComponents() { + GroupLayout layout = new GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addComponent(projectPanelScrollPane, GroupLayout.DEFAULT_SIZE, 651, Short.MAX_VALUE) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) +// .addComponent(renderingToolBar, GroupLayout.PREFERRED_SIZE, RenderingToolBar.WIDTH, GroupLayout.PREFERRED_SIZE) + .addComponent( + controlPanelScrollPane, + ControlPanel.CONTROL_PANEL_WIDTH, + ControlPanel.CONTROL_PANEL_WIDTH, + ControlPanel.CONTROL_PANEL_WIDTH + ) + ) + ); + layout.setVerticalGroup( + layout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addGroup(layout.createBaselineGroup(true, true) + .addComponent(projectPanelScrollPane) +// .addComponent(renderingToolBar) + .addComponent(controlPanelScrollPane) + )) + ); + } + + @Override + public void componentOpened() { + // TODO add custom code on component opening + } + + @Override + public void componentClosed() { + // TODO add custom code on component closing + } + + void writeProperties(java.util.Properties p) { + // better to version settings since initial version as advocated at + // http://wiki.apidesign.org/wiki/PropertyFiles + p.setProperty("version", "1.0"); + // TODO store your settings + } + + void readProperties(java.util.Properties p) { + String version = p.getProperty("version"); + // TODO read your settings according to their version + } + + /* + @Override + public boolean canClose() { + if (!projectPanel.isProjectSaved()) { + + int save = JOptionPane.showConfirmDialog(null, + "Project is not saved. Would you like to save project?", "Save project", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE); + + if (save == JOptionPane.YES_OPTION) { + projectPanel.saveProject(); + } + } + return super.canClose(); //To change body of generated methods, choose Tools | Templates. + }*/ +} diff --git a/GUI/src/main/java/cz/fidentis/analyst/project/events/AllFacesLoaded.java b/GUI/src/main/java/cz/fidentis/analyst/project/events/AllFacesLoaded.java new file mode 100644 index 00000000..437dc46d --- /dev/null +++ b/GUI/src/main/java/cz/fidentis/analyst/project/events/AllFacesLoaded.java @@ -0,0 +1,28 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package cz.fidentis.analyst.project.events; + +/** + * + * @author Matej Kovar + */ +public class AllFacesLoaded extends ProjectEvent { + + private boolean allFacesLoaded; + + /** + * All faces loaded event constructor + * @param allFacesLoaded Boolean + */ + public AllFacesLoaded(boolean allFacesLoaded) { + this.allFacesLoaded = allFacesLoaded; + } + + public boolean isAllFacesLoaded() { + return allFacesLoaded; + } + +} diff --git a/GUI/src/main/java/cz/fidentis/analyst/project/events/FaceDeselected.java b/GUI/src/main/java/cz/fidentis/analyst/project/events/FaceDeselected.java new file mode 100644 index 00000000..89cf01a5 --- /dev/null +++ b/GUI/src/main/java/cz/fidentis/analyst/project/events/FaceDeselected.java @@ -0,0 +1,14 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package cz.fidentis.analyst.project.events; + +/** + * + * @author Matej Kovar + */ +public class FaceDeselected extends ProjectEvent { + +} diff --git a/GUI/src/main/java/cz/fidentis/analyst/project/events/FaceSelected.java b/GUI/src/main/java/cz/fidentis/analyst/project/events/FaceSelected.java new file mode 100644 index 00000000..be9579a7 --- /dev/null +++ b/GUI/src/main/java/cz/fidentis/analyst/project/events/FaceSelected.java @@ -0,0 +1,44 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package cz.fidentis.analyst.project.events; + +import cz.fidentis.analyst.face.HumanFace; +import java.nio.file.Path; + +/** + * + * @author Matej Kovar + */ +public class FaceSelected extends ProjectEvent { + + private HumanFace face; + private String name; + private Path path; + + /** + * Face selected event constructor + * @param face HumanFace + * @param name String + * @param path Path + */ + public FaceSelected(HumanFace face, String name, Path path) { + this.face = face; + this.name = name; + this.path = path; + } + + public HumanFace getFace() { + return face; + } + + public String getName() { + return name; + } + + public Path getPath() { + return path; + } +} diff --git a/GUI/src/main/java/cz/fidentis/analyst/project/events/ProjectEvent.java b/GUI/src/main/java/cz/fidentis/analyst/project/events/ProjectEvent.java new file mode 100644 index 00000000..be8fbabc --- /dev/null +++ b/GUI/src/main/java/cz/fidentis/analyst/project/events/ProjectEvent.java @@ -0,0 +1,14 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package cz.fidentis.analyst.project.events; + +/** + * + * @author Matej Kovar + */ +public class ProjectEvent { + +} diff --git a/GUI/src/main/java/cz/fidentis/analyst/project/events/ProjectListener.java b/GUI/src/main/java/cz/fidentis/analyst/project/events/ProjectListener.java new file mode 100644 index 00000000..24097e6d --- /dev/null +++ b/GUI/src/main/java/cz/fidentis/analyst/project/events/ProjectListener.java @@ -0,0 +1,23 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package cz.fidentis.analyst.project.events; + +import com.google.common.eventbus.Subscribe; + +/** + * + * @author Matej Kovar + */ +public interface ProjectListener { + + /** + * Subscription method, which is invoked when an event appears. + * + * @param event A fired event. + */ + @Subscribe + void acceptEvent(ProjectEvent event); +} diff --git a/GUI/src/main/resources/cz/fidentis/analyst/project/Bundle.properties b/GUI/src/main/resources/cz/fidentis/analyst/project/Bundle.properties new file mode 100644 index 00000000..0b7316a4 --- /dev/null +++ b/GUI/src/main/resources/cz/fidentis/analyst/project/Bundle.properties @@ -0,0 +1,35 @@ +FaceStatePanel.filePanel.AccessibleContext.accessibleName=File info +FaceStatePanel.filePanel.border.title=File info +FaceStatePanel.pathLabel.text=Path : +FaceStatePanel.sizeLabel.text=Size : +FaceStatePanel.pathOutput.text= +FaceStatePanel.sizeOutput.text= +FaceStatePanel.facePanel.border.title=Face info +FaceStatePanel.kdTreeLabel.text=Has KD - tree : +FaceStatePanel.featurePointsLoadedLabel.text=Feature points loaded : +FaceStatePanel.photoPanel.border.title=Photo +FaceStatePanel.photo.text= +FaceStatePanel.hasKDOutput.text= +FaceStatePanel.hasFPOutput.text= +FaceStatePanel.warningLabel.text= +FaceStatePanel.faceNotLoadedLabel.text=Face not loaded +FaceStatePanel.loadFaceButton.text=Load face +FilterPanel.filterPanel.border.title=Filter settings +FilterPanel.hasFP.text=has feature points +FilterPanel.hasKD.text=has kd-tree +FilterPanel.alphabetical.text=alphabetical +FilterPanel.applyFilterButton.text=Apply filter +FilterPanel.warningLabel.text= +FilterPanel.faceNotLoadedLabel.text=All models must be loaded for filtering +FilterPanel.loadAllModelsButton.text=Load all models +ProjectPanel.newProjectButton.text= +ProjectPanel.openProjectButton.text= +ProjectPanel.saveProjectButton.text= +ProjectPanel.analyseButton.text=Analyse +ProjectPanel.manyToManyButton.text=N:N +ProjectPanel.oneOnOneButton.text=Open 1:1 +ProjectPanel.inflateButton.text=Inflate +ProjectPanel.deselectAllButton.text=Deselect all +ProjectPanel.selectAllButton.text=Select all +ProjectPanel.removeButton.text=Remove +ProjectPanel.addButton.text=Add diff --git a/GUI/src/main/resources/face160x160.png b/GUI/src/main/resources/face160x160.png new file mode 100644 index 0000000000000000000000000000000000000000..ce753351ef1d0d43fd85baac2c0e3672b0951f43 GIT binary patch literal 4468 zcmV-)5sU7LP)<h;3K|Lk000e1NJLTq005u>005u}1^@s6i_d2*00001b5ch_0Itp) z=>Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D5eZ2|K~#8N?VSs7 zQ&)O`^?u8ijU>yq;$SRfV^<i1gE297oKSF#0hfmejaxGfV`tN8pxX`8*<|W8Wz$Is zGdt6nbUbX@kg#oW0%>VV$mU_1WHB2IWO<l8v=A&~6F+3h$a-2*|C5~TvPKSUV$1j3 z`+qb4@c&n~k?#5RKh8b(T(JoGEgc;lihcX`8QgBS!DKR7LZMLp*w|QcI2^W5OibjD zj*hA`Gc)ZzpHCDF21Rh}tKU;76e5jABT7q46L~zIPtw!VN0mzDRk>XL8-u}cDUnFH zqS5GZMn;C$>2!{@wzfvU`b9(}cn552Ym;?$b}kqh8CfwrJnR5RA<kxtL?SuhfHL}H z-x;x3EYfPVA#g@_JRWzc)oNExPR_}N3m1Oy(n~M(!H*=q{z*hofYYfO8X6ufDk?ex z5zGZLCXq<u@Dg!|855~g8iVLKqEe}PN=r*$Yierx<L>TmIlP7l0TS_QYisNC^71|g zX9$4P#o%yKXPIds|2H_k-)6J@=TlETRSKyZOCr9~+}v!asi~<dC@44#X>i6P-5)AY zD^A$$_7^KEDwb^8v`G!e5I#U6UR71q1G%}m9nc&E;ZRZs;EKR|9G*LO?p|<08%9LN zAp^L2_3B4qP_II|BQ0yvLFbytWU`RaXgt4V%a+aPgpAVL+pAu+YSmAn`wWAbbfCE` z&^;&My@%in^kZ;BY*JW(M2v?Yez*|$Ul_z$YcQruph*ch9FD(#<dH`*!A7{w`t|D_ zR;%>{q%r25?;C-pDFhA5{+&B_W`m7zl~-PQ#R>&{H<@b#GwEQmDv*w&(7_)+bm)*7 zY=mpP{PN3Mh!Veqw9C0Emgy4m*%mEYbhy2}9cw}^0cqC&1M~W9PAaELluBh_@#4ih zHgDdn02`TY_U_%QE-o(K4K<%1%%p?HH%U)V?}P4mU0Yk51Z<{}(tlZI@uf?b_5_2$ z3~KY9NF<UrK0dxEJ3IT(nKNg|7Y~^&%F4=)kvTI^1tp{&T()f4tDqyZ#m0>rn<4ck z9UvhHbjFD-0A4Mb1?uYRiVX(CH|yyHD@LR7)Z>poo(DRTD#-dd=z0$dq3gY!kgmAA zy!<a%je<-zAtNIrrCnWJJEPI4;4e?bVlg?CA>mV}PIX?ma3MesGXryNd`Cxz^y0;f z8{+Y}l^zm2qoboM;hYqJ%3Ks=E&@XIGhe=Z`EUGwKRMwD0GWW?EETM+t$nwrr-zg! z%)nd(92y$3hQr~-)I<QN|3t&X!w&@l0WCem49q!TT3TA=`1rV<ng|6P&}6gO{)C#$ zz+4K3g8T2F=CM-~xd|vwVjhpDgPO>6)85{$$;ikM%r)OXRN&nBjvP6n0i79`O2N>4 zlzY8i=IWeO;q&>@-hco7Qfe{*Qx16U+&Kp+xRK<<<8jg1vu7RDWCErf(B*R7MO9=9 zpa#sRDibi}fO5HfK2?z^aJ$`1l_*R(px=*6-)_g)*cjE=fGG#m>2y>>rb4S_t4CwX z0hLPS09BDGuv)E5?LEkp1FF^P%Tz_CKq8U2smcUQIiO0Vx<XZC3M>}O2vwPYDF<A! zV#PRBktr}33>X1tivIro^D^1@-ZhuEK>8JJ+O)|>O(tN<0h^nf{bY*@Y9f<>4mjcQ zcs`{jGTo5-9`f??NE*K7LOhBnk(QP=1m}pUpu*IfCHMcv<MFH1L?)4yl@+CX<1hnL z4oHwnrTtVzCJ_pSE>V>km~%kZ=DAXdMx!D3Nizj=4hT&MM!+dB7!22_$_&goph~6s zlB&ogpaF4Fl^K|GK$FQd0);lUkejKgsTrgyGcf0XgM))#;$-x#KxslEAT}X04OtV2 z%kpo9EXRi$khwh)nRCG0+}w%@`j}MYcf?{b(L3+Fvz(gDz?1`$ePR0h`!`S%nM7Y- z-*$42sL2FOIpBvMez*u6a1k|;N%Z#i79T%;yqua$z|^+|>YP7?lf0Um$Rr>QOQ0F~ z-0gP%k{;qbOhrJkSiF>~$P^3=4CGRk37B#~uh)z7FSo(t@h~+>%9I1jzJ3-6@-57n zGlyzyz?1`~r>B2GRb&dF2E--#GevH0?ggqMQ&3!7j1D+c)YjIXRIAlYEx1f2N~JR9 zbUIH_6Pa!jiG(ySFRzEFD7Olnn@hMPe+ChY#W9G0?@|+)gifb>1DE8_Fj-kyUF7yd z<o6-xq`JELO=>a&b0ZlH27BO}&eXlHsla414Y^#d)6`@J<{VJ3*AK{KvR_jZp%{(E zqi|kA)MN(c9MER7c_7{VS}K)dH%yVs<r8MJ`A9`Y1>Uru3Q9^!{#>C@ctB0s4GK-> z%$f7K!{I0dojI7S=IiR}K2WJt%-sPt6F}EXc0}l`tgO6F4<R#6B9Rc^ci(+&kcuP3 z6tXCl%8{i@m#zVwNtld)<Xc}>R`$<#-+i~>FU?u4){pIW`*CU_sbtr#UCSXAlfpY` zbl|(F)#^k`OG_o_$ZP=(Njr&%pbARJXRfZU{u$^@!(<A+8K?(eggVGeO~GI=7(9@A ze?m=WVcr3u1H1-l_;YFshK!7i58i(JZRVdEz`O$%7Z;N!vj}RTDx_bs8TpBA+qN-( zgEaFFSXWmUfMUE)NLNM_3PlV`kJC>-{WMdL=T8Rn4(N0`V|u;*H{gH)dWiREG@9X| zp`iiVd@&944oCn8B+m~K%neHtiR3awL0)`bUN~TRdHFRM6v0G5nN0QtbillLW(qGH z@PP*&_yQt=j}+&82fk>DSS<F5*=%O(v6y_Pu&{7H3=ZiEZ<(~^lgQ=r;JkVBwt>zI zco6{!5D`9r&XD=8@OD6yAG262ym?dwZyd0)vXa~@!uyQ_;WLgp9FEVZiEssoelkc+ zWRvcssf#a?m6i1i*7gAWHh2>OAvI0p<>mb=HF*ns$$mlRKB>t(ym3Inz4zYxA1alK zw{;-d6=Ln$wf{v;glmwM((~ufC$}ahO<$}Fboyt>X9S%$@G1h5OH(G3=>VB4qlb8d zOeP~+Z|vp6<+q#Rl>-uDvDh)4PRF|^YC`kzF}d}Un!JH`4p>@RdKDb-eW_H+n@FKl zDn)j?{a+%H2rn+b@t)PIS8s)aeHhf=)=w;p(P;c=>C&b7pz{viML<G*ef{C=?Cj%E z3o^e(P%f8;;j{ewx#yn4$JDaKh7B9$LD7B|)TB{`6`4DC?%NMN^iUS)2y4K=ErjBo z+_02%aJeqf(R*53TT4Ml7)88%`SNWlm5RAlG8&C0vUTg$wS1fRn+z{&z?&c`?7yLi zKMeICGgn9y3Prf0qT(O)di^oJ&HD+G#>U1f7)&xZcuS<=nh=MxSS*L{zyE$g)O~!9 zfM4<8gAe`+8j?;Hq98=S5Y&Eeu2`{Rh#o@t05l{{a6qzyXwt~T6;UdceRXwp_kb=4 z1Q7uVkkU@b<#NvNAS#tgJ?qx3BkLLwJ^|gNw4k7X^H)bQGBW-T-m72&gJ3==6!)=s zJkI&0?3tOF5qPhH+2uhn4oDaq8{_;owpy*0YQjKJ4#>g^8K_gKCJY4SfGhx=I@N@M z&>|q!xC_*OR1*e*azLRCE(-|C0a-|I;c%F_$8CKdgjH}bKwn><pf14)$^oNM?mtS+ zYPIH2RS*cu0U^Cnjl0BRG2U#uaVH4M0kgBS=Tnul+_-UrYQjJ;4%pe*DGLMwoKJ5) zpHD;HD>ZqKU>xwul`GlTuU}VEle0jbn&EP}=1`OO2&Uf9YPBoRojbQVkw|box`YM> z2Hw1O?HcnBp}7+T5drt^-K*~E>e>j-$N3AbVzJob^?GYtT3Up4QJAl^x3|kHDk^@U zQmL4E!n(m=_+<V1_4RFSZGvhNdC8hJYkmOf_ZnSemvq3nCK8E+IAL!?L&IMSsUhJF z<X+lcyLK%tD=RxDl}gFvU($i*x_~2wZ8jU(8DSw`S4s2Y>O66{rluzSr=NamjKyMq zG(JB5SZ{A{Z738{&>vwMy<Q*A%E~&Lo16Qp&*$qdDJl8#z<~odAgU8bWg4a(kZjg{ z`0(NKlP6DBgVWsu&bP?#_ZLJW5ne_MvY<9CEv;9nRDNVOo6qFu=bvnCZ9P+8Uyl#1 zNfjj8ZQs7#4vod%!XO-n!T3Thmj`Gx5QLB#5k7Yi#BH%yPF7V_J^Adj&)Uhkf!C3l zpu4+UzIN@}y28T3*VStEC=9|kH}51JB%ug72jpBpnjT-UV8MIM&CP!Xjf)OmV*<{8 zV;+0#G2Q9Yr;U(K3j%?Fb9i`oy~pD*<G1|VA*;SkCR0B+<iYgx^rO*e)U|Tu%Ax0< zfBu^+!6`U5nBaIN@4fe4?da%e<;29qB5*!?Fc`$Ci0^<(r6OB>^k}u()8rBV<>lok z_V3^S88{;M*QKSBef#!hl5KV8&71ccq*oW5G}7S-KD|ztK#GpTIrV}=x}b4+-RX2T zlB+}Tny@)~^k~|;b?bhZo106Xcpe0&Bbx^$J&7pOBjg;Da}8hiOLcX1KYHVhH!N^` z)<|gzCYQwy95`Ts)Vc&x>?Ww|HiD?=%g8JMb>a=H)%tUdM)Mk^>Ce`zSu?m}$BvY( z+)arCKKkgR<}+u`RQLAwR)@pk%JK1W2Q(L)Um7JO$d0T~{#<~6yX<!RvBJW_<1f7M zf}g(3CU3p<mbRv*W+!~Jx|B-gAk-q5VmU65o+n_eu0vEjv1-+-AAu8Qz;U+Ny?b{y zINolP$#fl@E{qKYdqT#Hj2(<&A2{M)J@Ld7dN@AqOiKzT%Z4sqylCj}@6Yr5{hQow zcdOUyH6{||vmmSk&PW~==7whRKr|ZtcZb8#%b9D@TeogC78e))rP*x$A4s*MaOn5G zNhtghgTXKYj@Yqm*|KH`JVrP+J9Kt-8XFrMe+XUFuM`T!7^Yd_2w4;Xb)v^;G@e_s zWXU6Y_UuXBo^oUb%9br#Hs|N(les&r?*uF)1<PczP+nf%Tids9UoxYYNq6knVSvVB zSy55ZL6u5HF6AVBQz*g|olZBgc=6&xWo2dMO-)VH7ZJ(iadmZd{att6^{Q5@W%jXG zD5(*>UhgR=DEOJv>0I``?`i4o?$%UPRQv?~=m5^)q1>rJT8@IxT!Fy#j|UGP{BGBr zpLyn)k_8JEoC3#-fSL3^LP7a90pE$*Y_@lweDcXVf7WqJON)j);19anJ}{I1VHA`* z6>!3Y)oSgos;a8F?Y+*Oot-LZtM@>YF#=}NKZt_zUBqB83_xx8<0+Sck?Xe5!TcM! z*8t3<e*^{P`v}yA<3&Y9KP8PV*uNu@NJt<={u7zgAtnmSOo>{p_ClcB0{Yi;hGg;( zYQB1fLeWo56qK2koSdAG8XFt!po^qEJw55?&!2z##*G{I;0-@WDhLLH*&2;zq@khV zgftR~SUn!k6QNKjlfI51GfF%j7el#c@%el&N<c}M%jI`IPlF)SfY<At52c@0Vl*0a zMn^|+8!#lL`2BvFR4TPgqS0spE*wQt4Wwbw)vH(SlEJ}2!R$wja0_UF(<GUhnP0WT z2$E{R_ev!F{r$M@1u`qR-EO4>n7wuVh@jEwbos;qP1Ht^loAL8bP}OG8VcbKV`F0? zG7W>fBq6hcN~Ow{n9XLq3WCfEdcEEv2?ojXKLklV#P=kT2)X40K~hgB6cR~Tc!)E? zPl)eHCMG7Ri6E(kWM6bZWY!?QCno!Q;A$9THV})&qW=d1iU)gGBwL;U0000<MNUMn GLSTaSN@~pj literal 0 HcmV?d00001 diff --git a/GUI/src/main/resources/face16x16.png b/GUI/src/main/resources/face16x16.png new file mode 100644 index 0000000000000000000000000000000000000000..26bee8f05a6d3fa98e2aebeda660e27c76643c8d GIT binary patch literal 365 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCij$3p^r=85sBugD~Uq{1quc4NRUcjv*HQQzv_K9WoGToBbtGKE!)r*e<;t z#g|*vFKEBWJ)&G8A^zyt?2ZRsEaqKYi~cocW_qmn+Whj*8SRq}yt0WBeU{IyZ#d7$ zoMnCf^RX#;Y-gR1-QfKcY<^^&68l{qzvzRWXO{;0HBDZBS#|wl_kB+051iuKCtc<Z z@LT!uH`}({d=D*?r&^zE-X}cv_sDGQxZAyG!@~OH$ZJx5QVtu-Tmns+CbI?jIBs`Q z?t9F9vP<W5pUP~{%Uj-CoMQ^w#VEGJXHp8oTBT`^cfI3ze<vYQzh%j@OD=q-(O1r` zZe?>cILN<Qzx&p#7awcuvmEA>u;%jYO>a9dZNT!ct@z(hrU`#zzuH$$egh0522WQ% Jmvv4FO#qYil|}#n literal 0 HcmV?d00001 diff --git a/GUI/src/main/resources/face200x200.png b/GUI/src/main/resources/face200x200.png new file mode 100644 index 0000000000000000000000000000000000000000..597ba22fc1ded7778d29a02604ada767622102bc GIT binary patch literal 4801 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 BWM}{Y literal 0 HcmV?d00001 diff --git a/GUI/src/main/resources/face32x32.png b/GUI/src/main/resources/face32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..175f3a590d67aefd1dec061e56d471c922824320 GIT binary patch literal 745 zcmV<F0v7#=P)<h;3K|Lk000e1NJLTq001BW001Be1^@s6b9#F800001b5ch_0Itp) z=>Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0)9zEK~z{r#g<Kr z(?A%<H)-0&z9fCwzGzDerL+>ngN3@D3Sz}W53<-VB3{HpuO1Zi6NrKb59)VV@gs;Q zvA!d=1qo}hBwhcbPeJQU)7hQf{lTB-Kf{xGCYebx8#46!{g7?j+tFzBc{m*Y914Ye zCg#!iER)G>vm8oSOS9QLg(5Ft_f`oxJJo8n2(OM>t!CpcU&C^XE(^J@9LGt(t05MP z-9z9O6Dg5M+($e(?RMM3I{$#>77|I<b+_B?#^Db}Hk-YOz%3FaY|2ZBE72(mnayS< zS!t%z=?Stz0w)lOM81)g#<HxhWQ7DyAe~NsAuCO>So}m*NZ<tK^Lb#72wba?6%si3 zWHLERR+`~(c#f=)zzHOi$+u*sNu^S6$nGEZZ8r?#BP{n-6A53#4~T(Fuoid<*Acjd zM8Y*U5Y<qrR8DG|HizXFTNZNtR;#rMuZF>3pko=>>&Pv*EabjNRP*>3n5Ovvfm?7{ z_$5C?R7*ae-(rszmRoco<amWb;XJ&0@Qb~Jz%9HGa_%A?4%mzi0=Mu&<#PE9;@U`k zW<Aey$qFfzN<Yc2h13MFyA85JMxzmX5^Ezh0oQf6$O;*c#}~+|q0{M@IEr7ztMvrO zEDv4(t^40%Zvk?j;xu%v*Xza5Cl87mxm@lt26}|^;CFO!iv<bSx)|dz#=64BMBi!} zjm9QUz&Ekf@6hB9x?i!M6UM%UBYqz3f2r5&Ry-cRjT!Hv$sItIu#CH`7CUXD{rlMD z;EvfppL@Y!2{nh<Ck{Jw?(h<hLf9WKb)4Hyqj4<wzTafufz+Sov0!W16nl6I)IM5t bUElZxm=$pP5U*9w00000NkvXXu0mjfsDn}B literal 0 HcmV?d00001 diff --git a/GUI/src/main/resources/filter28x28.png b/GUI/src/main/resources/filter28x28.png new file mode 100644 index 0000000000000000000000000000000000000000..af4f1891a89a28ea0b74dd7cc528ce08212a0099 GIT binary patch literal 885 zcmV-*1B(2KP)<h;3K|Lk000e1NJLTq000~S000~a1^@s6at+^<00001b5ch_0Itp) z=>Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0}4q*K~zXfwU#@J z6JZpFXL2{2Y%aUGv0=9`g`_axvWk|1g%<?TN)Rn%J3Gb3LToH;#ljz;qSY$?02Nfw zLIhFVYC*-qB&+5&iO)ICj9GP)Np|zX;k=o1=Dgqe=DWnqX0y3kt#-B3=^Qf*Bi8M9 zeSW_`gg1M=o*@<t2E)XZ_j}Vc)eD4EqfM;q^Z5)h%d%SdF3-ME;{jUNj8G`_n0%=) zaSMmTD<<7A5X;91yVxtNC!-VecOY;&bHFU9@9$hJ5C{aRVNzFq`>`@+^30OpN68hN znwq-4xVRXEi_(@&YDJ^b8*r_U)~XSY$IsA7+kR+CLb+TH!MB8BvA6@=hN>7E%|s$` zQeysCEOrIov4d7561in}Iu;6rLX_`y7b<fuVhtKQ2bazjCh8aQnjoIh-5E!8d3iaA z*gdGzSu2@Lo`t(&E)YFW!Vjn>^Wy!PnVGl-Jz#!*KE>=jgzEb&l6AyRYj6`tr>97) z!?jbk&7*~dg``FYfSf#g?J3j|`^sPsYH$e5bUJ;gPqas&CzVQNQ_)hXlp*IORP)(t zUl3c;pjYJc`6XWb40S|b<Z`*J2K&G?7Fh1Dp^n(6+1c4W8XOhO|85GbLY-pIrl+UV z8U%B5b4A47LNyM5lgVUuYH(aophTf}P%WBDrH*I-a8O*pIWzE_&I%gXD%eAZak^z> zQRzd#ioA>y!4^3O^x+WvJ~W4b(OWh(n$4#Bj&qi>mBhI@gWyRJNEZsGQLie2BRC2? z30A9BIcpWIR?BAN!E1*u+HF^R1DJN34TdK{7KhFFP?q)YnK%MQ?vR`1kNQTq-+2&5 z?$B8%9A{znr)~vq^IpAP|NmV71y6!3dw2Bm4LPVIYinya8;!<sc_#NA`*U3rwgYx2 zy7B4u61E~-46&d59(V<f3<~bYsi53(;>8gA&e5lT8@3f3TdtsEh}F5qPQbSx2=2qV zf^=EsCOImxiGbo2oC?Yv$-TH&1CxUM#o#3QfW7A**)IF>7%+@q3P~Lwb_|X;00000 LNkvXXu0mjf;wqEI literal 0 HcmV?d00001 diff --git a/GUI/src/main/resources/warning16x16.png b/GUI/src/main/resources/warning16x16.png new file mode 100644 index 0000000000000000000000000000000000000000..136173d381479e8f3f2c179dbe866dd9c777ca07 GIT binary patch literal 411 zcmV;M0c8G(P)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00001b5ch_0Itp) z=>Px#1ZP1_K>z@;j|==^1poj532;bRa{vGikpKV=kpT{*K287t0We8KK~y+Tjgvhu zLtz+(U&4Sy6Qhqm;47?*tPCU-egeONl~vRx5(AS6gT%)mBw~<|kg#^r#i#~CT=(;w zmeX@u=Sr^hzE7XGZ~NwLQ>afXj(ZH(_~|hl-S~vxk<Zby1kKTFEd|t$J*b5rxQUsV zK<!%j`eF?AY|>f-TJQn)ti{>IN7PJR7O{+d)<RgrRga+;-*CxV3SIb$E7qJly!B`- zqh>UlU>%FtX3e?4bB~7J)69moKlGzcea_l1hq&*tN**;kU@hVludw!F?clb@Dw?^( zGixw~UpQ(l&JYfIjG<YrnO4z3Z7HO1ga;lIXwAKXZrO}N3JW;zF~KZqZMeZ>>{Q7} z4o^^jvM_=r)Nj%!W>MGr1&1rA-hsON?biP19oapUe*k%ELxy^ZXJY^W002ovPDHLk FV1f<Tu_6Ef literal 0 HcmV?d00001 -- GitLab