Skip to content
Snippets Groups Projects
Commit a53cbdf4 authored by Matej Kovár's avatar Matej Kovár Committed by Radek Ošlejšek
Browse files

Resolve "Indicate faces analyzed in multiple tasks"

parent 988dfb20
No related branches found
No related tags found
No related merge requests found
Showing
with 458 additions and 240 deletions
......@@ -110,7 +110,18 @@
<artifactId>ejml-all</artifactId>
<version>0.41</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.13.0</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.13.0</version>
<type>jar</type>
</dependency>
</dependencies>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
......
......@@ -4,6 +4,9 @@ import cz.fidentis.analyst.face.HumanFace;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.util.prefs.Preferences;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.nio.file.Paths;
/**
......@@ -15,8 +18,13 @@ import java.nio.file.Path;
public class Project {
private boolean saved = true;
private String projectName = "";
/* Project data (paths to faces, opened tabs..) */
private ObjectMapper mapper = new ObjectMapper();
private Preferences userPreferences = Preferences.userNodeForPackage(Project.class);
/* Project data (paths to faces) */
private ProjectConfiguration cfg = new ProjectConfiguration();
/**
......@@ -39,6 +47,10 @@ public class Project {
this.cfg = cfg;
}
public String getProjectName() {
return projectName;
}
/**
* Adds new path to project configuration
* @param path Path to be added
......@@ -57,40 +69,6 @@ public class Project {
return this.cfg.getPaths().contains(path);
}
/**
* Adds new FaceToFace tab to project configuration
* @param name1 String name of first face
* @param name2 String name of second face
*/
public void addNewFaceToFaceTabFace(String name1, String name2) {
this.cfg.addFaceToFaceTabFace(name1, name2);
}
/**
* Adds new face to FaceTab
* @param name String name of face
*/
public void addNewSingleFaceTabFace(String name) {
this.cfg.addSingleFaceTabFace(name);
}
/**
* Removes FaceTab
* @param name String name of face
*/
public void removeFaceTab(String name) {
this.cfg.removeFaceTab(name);
}
/**
* Removes FaceToFace tab
* @param name1 String name of first face
* @param name2 String name of second face
*/
public void removeFaceToFaceTab(String name1, String name2) {
this.cfg.removeFaceToFaceTab(name1, name2);
}
/**
* Loads face from path
* @param name String name of face
......@@ -140,5 +118,81 @@ public class Project {
}
return false;
}
/**
* Close currently loaded project
*/
public void closeProject() {
userPreferences.remove("pathToMostRecentProject");
}
/**
* Save currently loaded project
* @param file file where to store project
* @return true if project was successfully saved
*/
public boolean saveProject(File file) {
try {
mapper.writeValue(file, cfg);
userPreferences.put("pathToMostRecentProject", file.getAbsolutePath());
setSaved(true);
projectName = file.getName().split(".json")[0];
return true;
} catch (IOException ex) {
//Exceptions.printStackTrace(ex);
}
return false;
}
/**
* Create new project
*/
public void newProject() {
setCfg(new ProjectConfiguration());
projectName = "";
setSaved(true);
}
/**
* Gets path to project file
* @return String path to project file
*/
public String getPathToProjectFile() {
return userPreferences.get("pathToMostRecentProject", "");
}
/**
* Loads most recent project from user preferences
* @return File where project is saved, null if no project was found
*/
public File getRecentProject() {
String path = getPathToProjectFile();
if (path.equals("")) {
return null;
}
Path p = Paths.get(path);
return p.toFile();
}
/**
* Loads project from file
* @param projectFile file with project
* @return true if project was successfully loaded, false otherwise
*/
public boolean openProjectFromFile(File projectFile) {
if (projectFile != null) {
try {
closeProject();
cfg = mapper.readValue(projectFile, ProjectConfiguration.class);
userPreferences.put("pathToMostRecentProject", projectFile.getAbsolutePath());
setSaved(true);
projectName = projectFile.getName().split(".json")[0];
} catch (IOException ex) {
return false;
}
}
return true;
}
}
......@@ -3,13 +3,11 @@ package cz.fidentis.analyst;
import java.io.File;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* This class encapsulates data important for project (re)storing such as paths
* to faces or which tabs were opened
* to faces
*
* @author Matej Kovar
*/
......@@ -17,15 +15,6 @@ public class ProjectConfiguration {
/* Paths to loaded models */
private List<Path> paths = new ArrayList<>();
private List<String> singleTabFaces = new ArrayList<>();
// f.e. [face1 : [face2, face3], face2 : [face4, face5, face6], face3 : [face4]...]
private Map<String, List<String>> faceToFaceTabFaces = new HashMap<>();
//private Map<HumanFace, SingleFaceTab> singleFaceTabs = new HashMap<>();
//private Map<HumanFace, FaceToFaceTab> faceToFaceTabs = new HashMap<>();
public List<Path> getPaths() {
return paths;
......@@ -95,63 +84,4 @@ public class ProjectConfiguration {
public void clearPaths() {
paths.clear();
}
public List<String> getSingleTabFaces() {
return singleTabFaces;
}
public void setSingleTabFaces(List<String> singleTabFaces) {
this.singleTabFaces = singleTabFaces;
}
public Map<String, List<String>> getFaceToFaceTabFaces() {
return faceToFaceTabFaces;
}
public void setFaceToFaceTabFaces(Map<String, List<String>> faceToFaceTabFaces) {
this.faceToFaceTabFaces = faceToFaceTabFaces;
}
/**
* Adds SingleFace tab
* @param name String name of face
*/
public void addSingleFaceTabFace(String name) {
singleTabFaces.add(name);
}
/**
* Adds FaceToFace tab
* @param name1 String name of first face
* @param name2 String name of second face
*/
public void addFaceToFaceTabFace(String name1, String name2) {
if (faceToFaceTabFaces.containsKey(name1)) {
faceToFaceTabFaces.get(name1).add(name2);
} else {
List<String> faces = new ArrayList<>();
faces.add(name2);
faceToFaceTabFaces.put(name1, faces);
}
}
/**
* Removes SingleFace tab
* @param name String name of face
*/
public void removeFaceTab(String name) {
singleTabFaces.remove(name);
}
/**
* Removes FaceToFace tab
* @param name1 String name of first face
* @param name2 String name of second face
*/
public void removeFaceToFaceTab(String name1, String name2) {
faceToFaceTabFaces.get(name1).remove(name2);
if (faceToFaceTabFaces.get(name1).isEmpty()) {
faceToFaceTabFaces.remove(name1);
}
}
}
......@@ -15,7 +15,6 @@ import cz.fidentis.analyst.visitors.face.HumanFaceVisitor;
import cz.fidentis.analyst.visitors.mesh.BoundingBox;
import cz.fidentis.analyst.visitors.mesh.BoundingBox.BBox;
import cz.fidentis.analyst.visitors.mesh.CurvatureCalculator;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
......@@ -61,9 +60,7 @@ public class HumanFace implements Serializable {
private final transient EventBus eventBus;
private final String id;
private transient BufferedImage preview;
private boolean hasCurvature = false;
/**
......@@ -73,7 +70,6 @@ public class HumanFace implements Serializable {
/**
* Reads a 3D human face from the given OBJ file.
* Use {@link restoreFromFile} to restore the human face from a dump file.
*
* @param file OBJ file
* @param loadLandmarks If {@code true}, then the constructor aims to load
......@@ -108,7 +104,6 @@ public class HumanFace implements Serializable {
/**
* Reads a 3D human face from the given OBJ file.
* Also loads landmarks (feature points) if appropriate file is found.
* Use {@link restoreFromFile} to restore the human face from a dump file.
*
* @param file OBJ file
* @throws IOException on I/O failure
......
......@@ -118,7 +118,7 @@ public class IcpTransformer extends MeshVisitor {
* Mean distance of vertices is computed for each ICP iteration.
* If the difference between the previous and current mean distances is less than the error,
* then the ICP computation stops. Reasonable number seems to be 0.05.
* @param strategy One of the reduction strategies. If {@code null}, then {@link NoUndersampling} is used.
* @param strategy One of the reduction strategies. If {@code null}, then {@code NoUndersampling} is used.
* @throws IllegalArgumentException if some parameter is wrong
*/
public IcpTransformer(MeshFacet mainFacet, int maxIteration, boolean scale, double error, PointSampling strategy) {
......@@ -141,7 +141,7 @@ public class IcpTransformer extends MeshVisitor {
* Mean distance of vertices is computed for each ICP iteration.
* If the difference between the previous and current mean distances is less than the error,
* then the ICP computation stops. Reasonable number seems to be 0.05.
* @param strategy One of the reduction strategies. If {@code null}, then {@link NoUndersampling} is used.
* @param strategy One of the reduction strategies. If {@code null}, then {@code NoUndersampling} is used.
* @throws IllegalArgumentException if some parameter is wrong
*/
public IcpTransformer(Set<MeshFacet> mainFacets, int maxIteration, boolean scale, double error, PointSampling strategy) {
......@@ -174,7 +174,7 @@ public class IcpTransformer extends MeshVisitor {
* Mean distance of vertices is computed for each ICP iteration.
* If the difference between the previous and current mean distances is less than the error,
* then the ICP computation stops. Reasonable number seems to be 0.05.
* @param strategy One of the reduction strategies. If {@code null}, then {@link NoUndersampling} is used.
* @param strategy One of the reduction strategies. If {@code null}, then {@code NoUndersampling} is used.
* @throws IllegalArgumentException if some parameter is wrong
*/
public IcpTransformer(MeshModel mainModel, int maxIteration, boolean scale, double error, PointSampling strategy) {
......@@ -197,7 +197,7 @@ public class IcpTransformer extends MeshVisitor {
* Mean distance of vertices is computed for each ICP iteration.
* If the difference between the previous and current mean distances is less than the error,
* then the ICP computation stops. Reasonable number seems to be 0.05.
* @param strategy One of the reduction strategies. If {@code null}, then {@link NoUndersampling} is used.
* @param strategy One of the reduction strategies. If {@code null}, then {@code NoUndersampling} is used.
* @throws IllegalArgumentException if some parameter is wrong
*/
public IcpTransformer(KdTree primaryKdTree, int maxIteration, boolean scale, double error, PointSampling strategy) {
......
......@@ -9,7 +9,7 @@ import java.util.stream.Collectors;
/**
* A relevance-based point sampling using highest curvature.
* {@see https://graphics.stanford.edu/papers/zipper/zipper.pdf}
* {@link https://graphics.stanford.edu/papers/zipper/zipper.pdf}
* If curvature is not set in inspected facets, then it is computed and set automatically.
* This visitor is tread-safe.
*
......
......@@ -142,6 +142,7 @@
<artifactId>AbsoluteLayout</artifactId>
<version>RELEASE123</version>
</dependency>
<!--
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
......@@ -154,6 +155,7 @@
<version>2.13.0</version>
<type>jar</type>
</dependency>
-->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
......
......@@ -43,7 +43,7 @@ public class ApproxHausdorffDistTask extends SimilarityTask {
*
* @param progressDialog A window that show the progress of the computation. Must not be {@code null}
* @param controlPanel A control panel with computation parameters. Must not be {@code null}
* @param avgFace average face
* @param templateFaceIndex Index of the template face
*/
public ApproxHausdorffDistTask(ProgressDialog progressDialog, BatchPanel controlPanel, int templateFaceIndex) {
super(progressDialog, controlPanel);
......
......@@ -32,7 +32,7 @@ import org.jocl.cl_queue_properties;
* A GPU accelerated variant of {@link ApproxHausdorffDistTask}.
* The computation is accelerated by using both the CPU and GPU parallelism.
* The OpenCL code is based on
* {@see https://github.com/gpu/JOCLSamples/blob/master/src/main/java/org/jocl/samples/JOCLSample.java}.
* {@link https://github.com/gpu/JOCLSamples/blob/master/src/main/java/org/jocl/samples/JOCLSample.java}.
* However, the computation is slower than using CPU-based multitasking only
* (For 500 faces, 40 seconds of the HD finalization phase on GPU compared to 18 second on 8-core CPU)
* This class is marked as deprecated for this reason.
......@@ -97,7 +97,7 @@ public class ApproxHausdorffDistTaskGPU extends SimilarityTask {
*
* @param progressDialog A window that show the progress of the computation. Must not be {@code null}
* @param controlPanel A control panel with computation parameters. Must not be {@code null}
* @param avgFace average face
* @param templateFaceIndex Index of the template face
*/
public ApproxHausdorffDistTaskGPU(ProgressDialog progressDialog, BatchPanel controlPanel, int templateFaceIndex) {
super(progressDialog, controlPanel);
......
......@@ -56,7 +56,7 @@ public class Canvas extends JPanel implements HumanFaceListener {
// Scene components:
private final Scene scene = new Scene();
private final SceneRenderer sceneRenderer;
private final Camera camera = new Camera();
private Camera camera = new Camera();
private final List<HumanFace> faces = new ArrayList<>();
// Listeners:
......@@ -199,6 +199,10 @@ public class Canvas extends JPanel implements HumanFaceListener {
return camera;
}
public void setCamera(Camera camera) {
this.camera = camera;
}
/**
* Returns the underlying OpenGL canvas.
*
......
......@@ -9,9 +9,13 @@ import cz.fidentis.analyst.scene.DrawableFace;
import cz.fidentis.analyst.scene.DrawablePlane;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.AbstractAction;
import javax.swing.Box;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.JToggleButton;
......@@ -46,15 +50,18 @@ public class SceneToolboxFaceToFace extends JPanel implements HumanFaceListener
private JSlider slider;
private JToggleButton secDistButton;
private JButton endTaskButton;
private final Canvas canvas;
/**
* Constructor.
* @param canvas Rendering canvas
* @param endTaskListener action listener
*/
public SceneToolboxFaceToFace(Canvas canvas) {
public SceneToolboxFaceToFace(Canvas canvas, ActionListener endTaskListener) {
this.canvas = canvas;
initComponents(); // buttons are turned on by default
initComponents(endTaskListener); // buttons are turned on by default
// be informed if something changes in the faces -- see acceptEvent()
canvas.getPrimaryFace().registerListener(this);
......@@ -135,7 +142,7 @@ public class SceneToolboxFaceToFace extends JPanel implements HumanFaceListener
return button;
}
private void initComponents() {
private void initComponents(ActionListener endTaskListener) {
JPanel panel = new JPanel();
panel.setLayout(new FlowLayout());
add(panel);
......@@ -242,5 +249,12 @@ public class SceneToolboxFaceToFace extends JPanel implements HumanFaceListener
canvas.renderScene();
}
});
/////////////////////////
endTaskButton = new JButton("End Task");
endTaskButton.setFont(new Font("Tahoma", Font.BOLD, 12));
endTaskButton.addActionListener(endTaskListener);
panel.add(Box.createHorizontalStrut(40));
panel.add(endTaskButton);
}
}
......@@ -8,9 +8,13 @@ import cz.fidentis.analyst.scene.DrawableFace;
import cz.fidentis.analyst.scene.DrawablePlane;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.AbstractAction;
import javax.swing.Box;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.JToggleButton;
......@@ -39,15 +43,18 @@ public class SceneToolboxSingleFace extends JPanel implements HumanFaceListener
private JToggleButton priSymmetryButton;
private JSlider slider;
private JButton endTaskButton;
private final Canvas canvas;
/**
* Constructor.
* @param canvas Rendering canvas
* @param endTaskListener action listener
*/
public SceneToolboxSingleFace(Canvas canvas) {
public SceneToolboxSingleFace(Canvas canvas, ActionListener endTaskListener) {
this.canvas = canvas;
initComponents();
initComponents(endTaskListener);
// show the symmetry planes automatically, but only after they are computed
priSymmetryButton.setSelected(true);
......@@ -100,7 +107,7 @@ public class SceneToolboxSingleFace extends JPanel implements HumanFaceListener
return button;
}
private void initComponents() {
private void initComponents(ActionListener endTaskListener) {
JPanel panel = new JPanel();
panel.setLayout(new FlowLayout());
add(panel);
......@@ -156,5 +163,13 @@ public class SceneToolboxSingleFace extends JPanel implements HumanFaceListener
canvas.renderScene();
});
/////////////////////////
endTaskButton = new JButton("End Task");
endTaskButton.setFont(new Font("Tahoma", Font.BOLD, 12));
endTaskButton.addActionListener(endTaskListener);
panel.add(Box.createHorizontalStrut(40));
panel.add(endTaskButton);
}
}
......@@ -9,15 +9,20 @@ import cz.fidentis.analyst.curvature.CurvatureAction;
import cz.fidentis.analyst.distance.DistanceAction;
import cz.fidentis.analyst.face.HumanFace;
import cz.fidentis.analyst.faceState.FaceStatePanel;
import cz.fidentis.analyst.project.Task;
import cz.fidentis.analyst.registration.RegistrationAction;
import cz.fidentis.analyst.scene.Camera;
import cz.fidentis.analyst.symmetry.ProfilesAction;
import cz.fidentis.analyst.symmetry.SymmetryAction;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
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.List;
import java.util.Objects;
import javax.swing.GroupLayout;
......@@ -36,9 +41,11 @@ public class FaceTab extends TopComponent {
private final TopControlPanel controlPanel;
private final JScrollPane scrollPane;
private String nameOfFace1 = null;
private String nameOfFace2 = null;
private ActionListener listener = null;
private HumanFace face1 = null;
private HumanFace face2 = null;
private List<Path> faces = new ArrayList<>();
private Project project;
/**
* Constructor for single face analysis and 1:1.
......@@ -46,25 +53,40 @@ public class FaceTab extends TopComponent {
* @param primary Primary face
* @param secondary Secondary face
* @param name Tab name
* @param listener action listener
* @param endTaskListener action endTaskListener
* @param project Project
*/
public FaceTab(HumanFace primary, HumanFace secondary, String name, ActionListener listener, Project project) {
public FaceTab(HumanFace primary, HumanFace secondary, String name,
ActionListener endTaskListener, Project project) {
canvas = new Canvas();
this.listener = listener;
this.project = project;
nameOfFace1 = primary.getShortName();
face1 = primary;
canvas.addPrimaryFace(primary);
if (secondary == null) { // single face analysis
canvas.getScene().setDefaultColors();
canvas.addToolBox(new SceneToolboxSingleFace(canvas));
nameOfFace2 = null;
canvas.addToolBox(new SceneToolboxSingleFace(canvas,
(ActionEvent e) -> {
endTaskListener.actionPerformed(
new ActionEvent(this,
ActionEvent.ACTION_PERFORMED,
"FaceTab"));
}));
} else { // 1:1
canvas.addSecondaryFace(secondary);
canvas.getScene().setDefaultColors();
canvas.addToolBox(new SceneToolboxFaceToFace(canvas));
nameOfFace2 = secondary.getShortName();
canvas.addToolBox(new SceneToolboxFaceToFace(canvas,
(ActionEvent e) -> {
endTaskListener.actionPerformed(
new ActionEvent(this,
ActionEvent.ACTION_PERFORMED,
"FaceToFaceTab"));
}));
face2 = secondary;
}
controlPanel = new TopControlPanel();
......@@ -115,13 +137,18 @@ public class FaceTab extends TopComponent {
*
* @param faces Paths to faces
* @param name Tab name
* @param listener action listener
* @param endTaskListener action endTaskListener
*/
public FaceTab(List<Path> faces, String name, ActionListener listener) {
public FaceTab(List<Path> faces, String name, ActionListener endTaskListener) {
canvas = new Canvas();
this.listener = listener;
canvas.addToolBox(new SceneToolboxSingleFace(canvas));
canvas.addToolBox(new SceneToolboxSingleFace(canvas,
(ActionEvent e) -> {
endTaskListener.actionPerformed(
new ActionEvent(this,
ActionEvent.ACTION_PERFORMED,
"FaceToFaceTab"));
}));
controlPanel = new TopControlPanel();
scrollPane = new JScrollPane(controlPanel);
......@@ -139,8 +166,13 @@ public class FaceTab extends TopComponent {
controlPanel.addChangeListener(e -> getCanvas().renderScene());
this.faces = faces;
new BatchAction(canvas, controlPanel, faces);
}
/*
public FaceTab() {
this(null, null, null, null, null);
}*/
@Override
public int getPersistenceType() {
......@@ -176,12 +208,39 @@ public class FaceTab extends TopComponent {
);
}
/**
* Gets name of primary face
* @return name of primary face, or null
*/
public String getNameOfFace1() {
return nameOfFace1;
if (face1 != null) {
return face1.getShortName();
}
return null;
}
/**
* Gets name of secondary face
* @return name of secondary face, or null
*/
public String getNameOfFace2() {
return nameOfFace2;
if (face2 != null) {
return face2.getShortName();
}
return null;
}
public HumanFace getFace1() {
return face1;
}
public HumanFace getFace2() {
return face2;
}
public List<Path> getFaces() {
return faces;
}
/**
......@@ -190,13 +249,21 @@ public class FaceTab extends TopComponent {
* @return true if face with this name is in this tab
*/
public boolean hasFace(String name) {
return (name.equals(nameOfFace1) || name.equals(nameOfFace2));
return (name.equals(getNameOfFace1()) || name.equals(getNameOfFace2()));
}
public Canvas getCanvas() {
return canvas;
}
/**
* Sets camera to canvas
* @param camera
*/
public void setCamera(Camera camera) {
this.canvas.setCamera(camera);
}
/**
* Create FaceStatePanel for face
* @param face which will be shown on panel
......@@ -213,20 +280,20 @@ public class FaceTab extends TopComponent {
return facePanel;
}
@Override
public boolean canClose() {
if (nameOfFace1 != null && nameOfFace2 == null) {
listener.actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "FaceTab"));
} else if (nameOfFace1 != null && nameOfFace2 != null) {
listener.actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "FaceToFaceTab"));
} else {
listener.actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "ManyToManyTab"));
/**
* Create task for this tab and serialize data
* @throws IOException
*/
public void serializeTask() throws IOException {
if (face1 != null) {
Task task = new Task(face1, face2, canvas.getCamera());
task.dumpToFile(project.getPathToProjectFile()
.substring(0, project.getPathToProjectFile().lastIndexOf(File.separatorChar)));
}
return super.canClose(); //To change body of generated methods, choose Tools | Templates.
}
@Override
public int hashCode() {
int hash = 5;
......@@ -245,11 +312,14 @@ public class FaceTab extends TopComponent {
return false;
}
final FaceTab other = (FaceTab) obj;
if (!Objects.equals(this.nameOfFace1, other.nameOfFace1)) {
if (!Objects.equals(this.getNameOfFace1(), other.getNameOfFace1())) {
return false;
}
return Objects.equals(this.nameOfFace2, other.nameOfFace2);
if (!Objects.equals(this.getNameOfFace2(), other.getNameOfFace2())) {
return false;
}
return Objects.equals(faces, other.getFaces());
}
}
\ No newline at end of file
......@@ -15,7 +15,7 @@ import javax.swing.SwingWorker;
* Before using this dialog, a {@code SwingWorker} task class has to be implemented
* that stores the reference to this {@code ProgressDialog}, e.g.,
* <pre>
* public class Task extends SwingWorker<Void, Voide> {
* public class Task extends SwingWorker&lt;Void, Voide&gt; {
* private final ProgressDialog progressDialog;
*
* public Task(ProgressDialog progressDialog) {
......@@ -35,8 +35,8 @@ import javax.swing.SwingWorker;
* ProgressDialog progressDialog = new ProgressDialog(null);
* Task task = new Task(progressDialog);
*
* task.addPropertyChangeListener((PropertyChangeEvent evt) -> {
* if ("state".equals(evt.getPropertyName()) && (SwingWorker.StateValue.DONE.equals(evt.getNewValue()))) {
* task.addPropertyChangeListener((PropertyChangeEvent evt) -&gt; {
* if ("state".equals(evt.getPropertyName()) &amp;&amp; (SwingWorker.StateValue.DONE.equals(evt.getNewValue()))) {
* // code invoked when the task is done
* }
* });
......
......@@ -136,8 +136,8 @@ public class SpinSlider extends JPanel {
* <b>Removed all listeners!</b>
*
* @param value Initial value
* @param minimum Minimum value
* @param maximum Maximum value
* @param min Minimum value
* @param max Maximum value
* @param stepSize Spin step size
*/
public void initInteger(int value, int min, int max, int stepSize) {
......@@ -163,8 +163,8 @@ public class SpinSlider extends JPanel {
* <b>Removed all listeners!</b>
*
* @param value Initial value
* @param minimum Minimum value
* @param maximum Maximum value
* @param min Minimum value
* @param max Maximum value
* @param fractionDigits precision of flouting numbers, i.e.,
* the number of digits allowed after the floating dot
*/
......
......@@ -336,7 +336,7 @@ public class FaceStatePanel extends ControlPanel {
/**
* Shows face information on panel
* @param name String
* @param faceName String
* @param path Path
*/
public void showFaceState(String faceName, Path path) {
......@@ -630,7 +630,7 @@ public class FaceStatePanel extends ControlPanel {
/**
* Face from list is (de)selected
* @param selected true if face is selected, false if deselected
* @param name String name of face
* @param faceNames String name of face
* @param path Path to face
*/
public void newSelection(boolean selected, String faceName, Path path) {
......
package cz.fidentis.analyst.gui;
import cz.fidentis.analyst.project.ProjectTopComp;
import cz.fidentis.analyst.project.ProjectPanel;
import javax.swing.JOptionPane;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
......@@ -13,23 +13,6 @@ import org.openide.modules.ModuleInstall;
*/
public class Installer extends ModuleInstall {
private ProjectTopComp projectTopComp;
/**
* Constructor with projectTopComp
* @param projectTopComp ProjectTopComp
*/
public Installer(ProjectTopComp projectTopComp) {
this.projectTopComp = projectTopComp;
}
/**
* Default constructor
*/
public Installer() {
//super();
}
@Override
public void restored() {
/*
......@@ -62,12 +45,13 @@ public class Installer extends ModuleInstall {
@Override
public boolean closing() {
if (projectTopComp != null) {
projectTopComp.saveProjectOnClose();
}
int answer = JOptionPane.showConfirmDialog(null,
"Do you really want to close the application?", "", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
if (answer == JOptionPane.YES_OPTION) {
ProjectPanel.serializeTasks();
}
return answer == JOptionPane.YES_OPTION;
}
......
package cz.fidentis.analyst.project;
import cz.fidentis.analyst.core.ProgressDialog;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import javax.swing.SwingWorker;
/**
* A task which opens all tasks from files
*
* @author Matej Kovar
*/
class LoadTasksTask extends SwingWorker<Boolean, Integer> {
private List<File> tasksToOpen;
private ProgressDialog progressDialog;
private List<Task> tasksRestored = new ArrayList<>();
/**
* Constructor for task
* @param tasksToOpen files with tasks
* @param progressDialog dialog
*/
LoadTasksTask(List<File> tasksToOpen, ProgressDialog progressDialog) {
this.tasksToOpen = tasksToOpen;
this.progressDialog = progressDialog;
}
@Override
protected Boolean doInBackground() throws Exception {
int iter = 0;
for (var file : tasksToOpen) {
if (isCancelled()) {
return false;
}
Task task = Task.restoreFromFile(file);
tasksRestored.add(task);
int progress = (int)Math.round(100.0 * (iter + 1) / tasksToOpen.size());
progressDialog.setValue(progress);
iter++;
}
return true;
}
@Override
protected void done() {
progressDialog.dispose();
if (isCancelled()) {
this.tasksRestored.clear();
}
}
public List<Task> getTasksRestored() {
return this.tasksRestored;
}
}
......@@ -4,6 +4,7 @@ import cz.fidentis.analyst.faceState.FaceStatePanel;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.awt.Image;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
......@@ -12,6 +13,7 @@ import java.util.ArrayList;
import java.util.List;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JComboBox;
import javax.swing.table.DefaultTableModel;
import org.openide.util.Exceptions;
import org.imgscalr.Scalr;
......@@ -27,7 +29,7 @@ public class ModelsTableModel extends DefaultTableModel {
private final ImageIcon previewBasic = new ImageIcon(FaceStatePanel.class.getClassLoader().getResource("/" + "face32x32.png"));
private final ImageIcon previewBasicGray = new ImageIcon(FaceStatePanel.class.getClassLoader().getResource("/" + "face_gray32x32.png"));
// List of previews of faces which are currently filtered
// List of paths faces which are currently filtered
private List<Path> pathsToFilteredFaces = new ArrayList<>();
private Integer filteredRows = 0;
......@@ -36,15 +38,16 @@ public class ModelsTableModel extends DefaultTableModel {
* Constructor
*/
public ModelsTableModel() {
super(new Object[]{"", "Models", "Preview"}, 0);
super(new Object[]{"", "Models", "Tasks", "Preview"}, 0);
}
private Class[] types = new Class [] {
java.lang.Boolean.class, java.lang.String.class, ImageIcon.class
java.lang.Boolean.class, java.lang.String.class, JComboBox.class, ImageIcon.class
};
private boolean[] canEdit = new boolean [] {
true, false, false
true, false, true, false
};
@Override
......@@ -62,16 +65,17 @@ public class ModelsTableModel extends DefaultTableModel {
@Override
public void setRowCount(int rowCount) {
super.setRowCount(rowCount);
if (rowCount == 0) {
pathsToFilteredFaces.clear();
filteredRows = 0;
}
super.setRowCount(rowCount);
}
@Override
public void removeRow(int row) {
super.removeRow(row);
String faceName = this.getValueAt(row, 1).toString();
......@@ -80,6 +84,8 @@ public class ModelsTableModel extends DefaultTableModel {
.lastIndexOf(File.separatorChar) + 1,
path.toString().lastIndexOf('.')).equals(faceName);
});
super.removeRow(row);
}
/**
......@@ -102,8 +108,6 @@ public class ModelsTableModel extends DefaultTableModel {
for (int row = 0; row < this.getRowCount() - filteredRows; row++) {
if (this.getValueAt(row, 0) == (Object) true) {
this.setValueAt(false, row, 0);
} else {
......@@ -161,12 +165,12 @@ public class ModelsTableModel extends DefaultTableModel {
public void disableRow(int row, Path path) {
if (path != null && !pathsToFilteredFaces.contains(path)) {
Image iconImage = ((ImageIcon)this.getValueAt(row, 2)).getImage();
Image iconImage = ((ImageIcon)this.getValueAt(row, 3)).getImage();
Path previewPath = this.getPreviewPath(path);
if (previewPath == null || !previewPath.toFile().exists()) {
this.setValueAt(previewBasicGray, row, 2);
this.setValueAt(previewBasicGray, row, 3);
} else {
......@@ -175,7 +179,7 @@ public class ModelsTableModel extends DefaultTableModel {
// Scalr.OP_DARKER passed 5 times to grey preview by 50%
image = Scalr.apply(image, Scalr.OP_DARKER, Scalr.OP_DARKER,
Scalr.OP_DARKER, Scalr.OP_DARKER, Scalr.OP_DARKER);
this.setValueAt(new ImageIcon(image), row, 2);
this.setValueAt(new ImageIcon(image), row, 3);
}
pathsToFilteredFaces.add(path);
......@@ -208,7 +212,7 @@ public class ModelsTableModel extends DefaultTableModel {
}
this.setValueAt(preview, row, 2);
this.setValueAt(preview, row, 3);
pathsToFilteredFaces.remove(path);
}
}
......@@ -245,25 +249,68 @@ public class ModelsTableModel extends DefaultTableModel {
return preview;
}
/**
* Adds new task to combo-box
* @param faceName name of the face
* @param nameOfTask name of task
*/
public void addNewTask(String faceName, String nameOfTask) {
for (int row = 0; row < this.getRowCount(); row++) {
if (this.getValueAt(row, 1).toString() == null ? faceName == null : this.getValueAt(row, 1).toString().equals(faceName)) {
JComboBox comboBox = ((JComboBox)this.getValueAt(row, 2));
comboBox.addItem(nameOfTask);
return;
}
}
}
/**
* Removes task from combo-box
* @param faceName name of face
* @param nameOfTask name of task
*/
public void removeTask(String faceName, String nameOfTask) {
for (int row = 0; row < this.getRowCount(); row++) {
if (this.getValueAt(row, 1).toString() == null ? faceName == null : this.getValueAt(row, 1).toString().equals(faceName)) {
JComboBox comboBox = ((JComboBox)this.getValueAt(row, 2));
comboBox.removeItem(nameOfTask);
return;
}
}
}
/**
* Adds new row to model
* @param name String name of the face
* @param Path path to face
* @param path path to face
* @param taskSelected task
*/
public void addRowWithName(String name, Path path) {
public void addRowWithName(String name, Path path, ActionListener taskSelected) {
Path preview = this.getPreviewPath(path);
int index = this.getRowCount() - filteredRows;
JComboBox comboBox = new JComboBox();
comboBox.addActionListener(taskSelected);
comboBox.setFont(new java.awt.Font("Tahoma", 0, 14));
if (preview == null || !preview.toFile().exists()) {
insertRow(index, new Object[]{false, name, previewBasic});
insertRow(index, new Object[]{false, name, comboBox, previewBasic});
} else {
try {
BufferedImage image = ImageIO.read(preview.toFile());
// Scale image to fit into column
BufferedImage scaledImage = Scalr.resize(image, 70, 55);
insertRow(index, new Object[]{false, name, new ImageIcon(scaledImage)});
insertRow(index, new Object[]{false, name, comboBox, new ImageIcon(scaledImage)});
} catch (IOException ex) {
Exceptions.printStackTrace(ex);
......
......@@ -19,26 +19,21 @@
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" pref="41" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="buttonsPanel" pref="1025" max="32767" attributes="0"/>
<Component id="buttonsPanel" pref="968" max="32767" attributes="0"/>
<Component id="tableScrollPane" max="32767" attributes="0"/>
</Group>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace min="-2" pref="50" 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="saveProjectButton" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
<Group type="102" alignment="1" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="openProjectButton" min="-2" max="-2" attributes="0"/>
<Component id="newProjectButton" min="-2" max="-2" attributes="0"/>
<Component id="saveProjectButton" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="openProjectButton" min="-2" max="-2" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Component id="projectNameLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="projectNameOutput" min="-2" pref="122" max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
......@@ -46,20 +41,26 @@
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="buttonsPanel" alignment="0" min="-2" pref="56" max="-2" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Component id="buttonsPanel" min="-2" pref="56" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="tableScrollPane" pref="768" max="32767" attributes="0"/>
<EmptySpace min="-2" pref="29" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="projectNameOutput" alignment="0" min="-2" pref="15" max="-2" attributes="0"/>
<Component id="projectNameLabel" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" pref="61" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<Component id="newProjectButton" min="-2" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="19" 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"/>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
<Component id="tableScrollPane" pref="768" max="32767" attributes="0"/>
</Group>
<EmptySpace pref="12" max="32767" attributes="0"/>
</Group>
......@@ -94,7 +95,7 @@
</Property>
</Properties>
<Events>
<EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="addButtonMouseClicked"/>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="addButtonActionPerformed"/>
</Events>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
......@@ -115,7 +116,7 @@
</Property>
</Properties>
<Events>
<EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="removeButtonMouseClicked"/>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="removeButtonActionPerformed"/>
</Events>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
......@@ -136,7 +137,7 @@
</Property>
</Properties>
<Events>
<EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="selectAllButtonMouseClicked"/>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="selectAllButtonActionPerformed"/>
</Events>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
......@@ -157,7 +158,7 @@
</Property>
</Properties>
<Events>
<EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="deselectAllButtonMouseClicked"/>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="deselectAllButtonActionPerformed"/>
</Events>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
......@@ -179,7 +180,7 @@
</Property>
</Properties>
<Events>
<EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="inflateButtonMouseClicked"/>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="inflateButtonActionPerformed"/>
</Events>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
......@@ -195,12 +196,19 @@
<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, &quot;{key}&quot;)"/>
</Property>
<Property name="enabled" type="boolean" value="false"/>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[150, 23]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[150, 23]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[100, 30]"/>
<Dimension value="[150, 30]"/>
</Property>
</Properties>
<Events>
<EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="analyseFaces"/>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="analyseButtonActionPerformed"/>
</Events>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
......@@ -223,7 +231,7 @@
</Property>
</Properties>
<Events>
<EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="saveProjectButtonMouseClicked"/>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="saveProjectButtonActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="openProjectButton">
......@@ -239,7 +247,7 @@
</Property>
</Properties>
<Events>
<EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="openProjectButtonMouseClicked"/>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="openProjectButtonActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="newProjectButton">
......@@ -252,7 +260,7 @@
</Property>
</Properties>
<Events>
<EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="newProjectButtonMouseClicked"/>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="newProjectButtonActionPerformed"/>
</Events>
</Component>
<Container class="javax.swing.JScrollPane" name="tableScrollPane">
......@@ -264,7 +272,7 @@
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor" postCode="table.getTableHeader().setOpaque(false);&#xa;table.getTableHeader().setBackground(new java.awt.Color(204,204,204));&#xa;table.getTableHeader().setFont(new java.awt.Font(&quot;Tahoma&quot;, 0, 18));&#xa;model.addTableModelListener(new TableModelListener() {&#xa; public void tableChanged(TableModelEvent e) {&#xa; jTable1TableChanged(e);&#xa; }&#xa;});">
<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);&#xa;table.getColumnModel().getColumn(2).setMaxWidth(75);&#xa;table.getTableHeader().getColumnModel().getColumn(0).setMaxWidth(50);&#xa;table.getTableHeader().getColumnModel().getColumn(2).setMaxWidth(85);">
<Property name="model" type="javax.swing.table.TableModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor" postCode="table.getColumnModel().getColumn(0).setMaxWidth(50);&#xa;table.getColumnModel().getColumn(1).setPreferredWidth(400);&#xa;table.getColumnModel().getColumn(2).setMaxWidth(250);&#xa;table.getColumnModel().getColumn(2).setPreferredWidth(250);&#xa;table.getColumnModel().getColumn(3).setMaxWidth(125);&#xa;table.getColumnModel().getColumn(3).setPreferredWidth(125);&#xa;table.getTableHeader().getColumnModel().getColumn(0).setMaxWidth(50);&#xa;table.getTableHeader().getColumnModel().getColumn(1).setPreferredWidth(400);&#xa;table.getTableHeader().getColumnModel().getColumn(2).setMaxWidth(250);&#xa;table.getTableHeader().getColumnModel().getColumn(2).setPreferredWidth(250);&#xa;table.getTableHeader().getColumnModel().getColumn(3).setMaxWidth(125);&#xa;table.getTableHeader().getColumnModel().getColumn(3).setPreferredWidth(125);">
<Connection code="model" type="code"/>
</Property>
<Property name="columnModel" type="javax.swing.table.TableColumnModel" editor="org.netbeans.modules.form.editors2.TableColumnModelEditor">
......@@ -289,5 +297,25 @@
</Component>
</SubComponents>
</Container>
<Component class="javax.swing.JLabel" name="projectNameLabel">
<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.projectNameLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="projectNameOutput">
<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.projectNameOutput.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
</SubComponents>
</Form>
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment