diff --git a/Comparison/src/main/java/cz/fidentis/analyst/Project.java b/Comparison/src/main/java/cz/fidentis/analyst/Project.java
index 7f9d8810dbc2b9bae8c398a165f91efe8a3997d8..1a006fe9f1f8fca7a7f306f20693e8e0d281d715 100644
--- a/Comparison/src/main/java/cz/fidentis/analyst/Project.java
+++ b/Comparison/src/main/java/cz/fidentis/analyst/Project.java
@@ -1,6 +1,9 @@
 package cz.fidentis.analyst;
 
 import cz.fidentis.analyst.face.HumanFace;
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -14,8 +17,85 @@ import java.util.List;
  */
 public class Project {
     
+    private boolean saved = true;
+
     private List<HumanFace> faces = new ArrayList<>();
     
+    /* Project data (paths to faces, opened tabs..) */
+    private ProjectConfiguration cfg = new ProjectConfiguration();
+    
+    /**
+     * Asks whether project is saved or some change was made
+     * @return true if project is saved, false otherwise
+     */
+    public boolean isSaved() {
+        return saved;
+    }
+
+    public void setSaved(boolean saved) {
+        this.saved = saved;
+    }
+
+    public ProjectConfiguration getCfg() {
+        return cfg;
+    }
+
+    public void setCfg(ProjectConfiguration cfg) {
+        this.cfg = cfg;
+    }
+    
+    /**
+     * Adds new path to project configuration
+     * @param path Path to be added
+     * @return true if path was successfully added
+     */
+    public boolean addNewPath(Path path) {
+        return this.cfg.addPath(path);
+    }
+    
+    /**
+     * Checks whether path is already loaded in project configuration
+     * @param path Path to be checked
+     * @return true if path was loaded, false otherwise
+     */
+    public boolean pathLoaded(Path path) {
+        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);
+    }
+    
     /**
      * Returns list of HumanFace secondary faces
      * 
@@ -73,6 +153,29 @@ public class Project {
         } 
     }
     
+    /**
+     * Removes face by providing its name
+     * 
+     * @param name name of the face to be removed
+     */
+    public void removeFaceByName(String name) {
+        HumanFace face = this.getFaceByName(name);
+        if (face != null) {
+            this.removeFace(face);
+        }
+        
+        this.cfg.removePath(name);
+        //this.cfg.removeFaceTab(name);
+        
+    }
+    
+    /**
+     * Removes all faces from list of faces
+     */
+    public void removeAll() {
+        faces.clear();
+    }
+    
     /**
      * Removes faces which are sent to this function by list of HumanFace
      * from faces
@@ -101,5 +204,32 @@ public class Project {
         }
         return null;
     }
-
+    
+    /**
+     * Loads face from path
+     * @param name String name of face
+     * @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
+                out.printDuration("Loaded model " + face.getShortName() +" with " + face.getMeshModel().getNumVertices() + " vertices");
+            } catch (IOException ex) {
+                //ex.printStackTrace();
+                Logger.print(ex.toString());
+            }    
+        }
+        return face;
+    }
+   
 }
diff --git a/Comparison/src/main/java/cz/fidentis/analyst/ProjectConfiguration.java b/Comparison/src/main/java/cz/fidentis/analyst/ProjectConfiguration.java
new file mode 100644
index 0000000000000000000000000000000000000000..fb66bec4c58efa1ef0908d1300b520ad6259f676
--- /dev/null
+++ b/Comparison/src/main/java/cz/fidentis/analyst/ProjectConfiguration.java
@@ -0,0 +1,147 @@
+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
+ * @author Matej Kovar
+ */
+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;
+    }
+
+    public void setPaths(List<Path> paths) {
+        this.paths = paths;
+    }
+       
+    /**
+     * Adds path to paths
+     * @param path Path to be added
+     * @return true if path was successfully added 
+     */
+    public boolean addPath(Path path) {
+        return paths.add(path);
+    }
+    
+    /**
+     * Removes specific path from paths
+     * @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));
+    }
+    
+    /**
+     * Returns path to face with specified name of file
+     * @param name String name of file
+     * @return Path to face
+     */
+    public Path getPathToFaceByName(String name) {
+        for (Path p : paths) {
+            if (p.toString().substring(p.toString().lastIndexOf(File.separatorChar) + 1, p.toString().lastIndexOf('.')).equals(name)) {
+                return p;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Opens all files in paths
+     * @return List<File> list of files with faces
+     */
+    public List<File> openFiles() {
+        List<File> f = new ArrayList<>();
+            
+        paths.forEach(p -> {
+            f.add(p.toFile());
+        });
+        
+        return f;
+    }
+    
+    /**
+     * Removes all paths
+     */
+    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);
+        }
+    }
+}
diff --git a/GUI/pom.xml b/GUI/pom.xml
index 3cdd34b4a68be166cce25e5b4722e63891ac4ff2..5caa94cf27180acaf7863f00ff2909ebbbf24aac 100644
--- a/GUI/pom.xml
+++ b/GUI/pom.xml
@@ -137,7 +137,18 @@
             <artifactId>AbsoluteLayout</artifactId>
             <version>RELEASE123</version>
         </dependency>
-
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-databind</artifactId>
+            <version>2.13.0</version>
+            <type>jar</type>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-core</artifactId>
+            <version>2.13.0</version>
+            <type>jar</type>
+        </dependency>
     </dependencies>
     <properties>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
diff --git a/GUI/src/main/java/cz/fidentis/analyst/canvas/Canvas.java b/GUI/src/main/java/cz/fidentis/analyst/canvas/Canvas.java
index 2cd001b08fc6afa3c1c976a2f9fb73e864903aa1..c0be1ee3eb568c0548e7e045a43bfef559c5c573 100644
--- a/GUI/src/main/java/cz/fidentis/analyst/canvas/Canvas.java
+++ b/GUI/src/main/java/cz/fidentis/analyst/canvas/Canvas.java
@@ -52,7 +52,7 @@ public class Canvas extends JPanel {
     private final Scene scene = new Scene();
     private final SceneRenderer sceneRenderer;
     private final Camera camera = new Camera();
-    private final List<HumanFace> faces = new ArrayList();
+    private final List<HumanFace> faces = new ArrayList<>();
     
     // Listeners:
     private final CanvasListener listener;
diff --git a/GUI/src/main/java/cz/fidentis/analyst/core/FaceTab.java b/GUI/src/main/java/cz/fidentis/analyst/core/FaceTab.java
new file mode 100644
index 0000000000000000000000000000000000000000..edbfc4a039a86c99708b2e207a4750468da01c8d
--- /dev/null
+++ b/GUI/src/main/java/cz/fidentis/analyst/core/FaceTab.java
@@ -0,0 +1,197 @@
+package cz.fidentis.analyst.core;
+
+import cz.fidentis.analyst.batch.BatchAction;
+import cz.fidentis.analyst.canvas.Canvas;
+import cz.fidentis.analyst.canvas.toolbar.SceneToolboxFaceToFace;
+import cz.fidentis.analyst.canvas.toolbar.SceneToolboxSingleFace;
+import cz.fidentis.analyst.curvature.CurvatureAction;
+import cz.fidentis.analyst.distance.DistanceAction;
+import cz.fidentis.analyst.face.HumanFace;
+import cz.fidentis.analyst.registration.RegistrationAction;
+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.util.Objects;
+import javax.swing.GroupLayout;
+import javax.swing.JScrollPane;
+import javax.swing.LayoutStyle;
+import org.openide.windows.TopComponent;
+
+/**
+ * The non-singleton window/tab for the analysis of one, two or many to many faces
+ *
+ * @author Matej Kovar
+ */
+public class FaceTab extends TopComponent {
+    
+    private final Canvas canvas ;
+    private final TopControlPanel controlPanel;
+    private final JScrollPane scrollPane;
+    
+    private String nameOfFace1 = null;
+    private String nameOfFace2 = null;
+    private ActionListener listener = null;
+    
+    /**
+     * Constructor.
+     * @param primary Primary face
+     * @param secondary Secondary face
+     * @param name Tab name
+     * @param listener action listener
+     */
+    public FaceTab(HumanFace primary, HumanFace secondary, String name, ActionListener listener) {
+        canvas = new Canvas();
+        this.listener = listener;
+        
+        if (primary == null) { // N:N
+            canvas.addToolBox(new SceneToolboxSingleFace(canvas));
+            
+        } else {
+            nameOfFace1 = primary.getShortName();
+            
+            canvas.addPrimaryFace(primary);
+
+            if (secondary == null) { // single face analysis
+                canvas.getScene().setDefaultColors();
+                canvas.addToolBox(new SceneToolboxSingleFace(canvas));
+                nameOfFace2 = null;
+            } else { // 1:1
+                canvas.addSecondaryFace(secondary);
+                canvas.getScene().setDefaultColors();
+                canvas.addToolBox(new SceneToolboxFaceToFace(canvas));    
+                nameOfFace2 = secondary.getShortName();
+            }
+        }
+
+        controlPanel = new TopControlPanel();
+        scrollPane = new JScrollPane(controlPanel);
+        
+        setName(name);
+        initComponents();
+        
+        // change the height so that it corresponds to the height of the OpenGL window
+        canvas.addComponentListener(new ComponentAdapter() {
+            @Override
+            public void componentResized(ComponentEvent e) {
+                scrollPane.setSize(ControlPanel.CONTROL_PANEL_WIDTH, canvas.getHeight());
+            }
+        });
+        
+        controlPanel.addChangeListener(e -> getCanvas().renderScene());
+        
+        if (primary == null) { // N:N
+            new BatchAction(canvas, controlPanel);
+        } else {
+            if (secondary == null) { // single face analysis
+                new CurvatureAction(getCanvas(), controlPanel);
+                new SymmetryAction(getCanvas(), controlPanel);
+                new ProfilesAction(getCanvas(), controlPanel);
+            } else { // 1:1
+                new RegistrationAction(canvas, controlPanel);
+                new DistanceAction(canvas, controlPanel);
+                new SymmetryAction(canvas, controlPanel);
+                new ProfilesAction(canvas, controlPanel);
+            }
+        }
+        
+
+    }
+    
+    @Override
+    public int getPersistenceType() {
+        return TopComponent.PERSISTENCE_NEVER; // TO DO: change to .PERSISTENCE_ONLY_OPENED when we can re-create the ProjectTC
+    }
+    
+    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(canvas, GroupLayout.DEFAULT_SIZE, 651, Short.MAX_VALUE)
+                                .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
+//                                .addComponent(renderingToolBar, GroupLayout.PREFERRED_SIZE, RenderingToolBar.WIDTH, GroupLayout.PREFERRED_SIZE)
+                                .addComponent(
+                                        scrollPane,
+                                        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(canvas)
+//                                        .addComponent(renderingToolBar)
+                                        .addComponent(scrollPane)
+                                ))
+        );
+    }
+
+    public String getNameOfFace1() {
+        return nameOfFace1;
+    }
+
+    public String getNameOfFace2() {
+        return nameOfFace2;
+    }
+    
+    /**
+     * Checks whether this tab contains name of face
+     * @param name String name of face
+     * @return true if face with this name is in this tab
+     */
+    public boolean hasFace(String name) {
+        return (name.equals(nameOfFace1) || name.equals(nameOfFace2));
+    }
+
+    public Canvas getCanvas() {
+        return canvas;
+    }
+    
+    
+    @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"));
+        }
+        return super.canClose(); //To change body of generated methods, choose Tools | Templates.
+    }
+
+    
+    @Override
+    public int hashCode() {
+        int hash = 5;
+        return hash;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        final FaceTab other = (FaceTab) obj;
+        if (!Objects.equals(this.nameOfFace1, other.nameOfFace1)) {
+            return false;
+        }
+        return Objects.equals(this.nameOfFace2, other.nameOfFace2);
+    }
+    
+    
+}
\ No newline at end of file
diff --git a/GUI/src/main/java/cz/fidentis/analyst/core/FaceToFaceTab.java b/GUI/src/main/java/cz/fidentis/analyst/core/FaceToFaceTab.java
deleted file mode 100644
index ee502c41257f936a0f34e3794fd728d3bdc90887..0000000000000000000000000000000000000000
--- a/GUI/src/main/java/cz/fidentis/analyst/core/FaceToFaceTab.java
+++ /dev/null
@@ -1,102 +0,0 @@
-package cz.fidentis.analyst.core;
-
-import cz.fidentis.analyst.canvas.Canvas;
-import cz.fidentis.analyst.canvas.toolbar.SceneToolboxFaceToFace;
-import cz.fidentis.analyst.distance.DistanceAction;
-import cz.fidentis.analyst.face.HumanFace;
-import cz.fidentis.analyst.registration.RegistrationAction;
-import cz.fidentis.analyst.symmetry.ProfilesAction;
-import cz.fidentis.analyst.symmetry.SymmetryAction;
-import java.awt.event.ComponentAdapter;
-import java.awt.event.ComponentEvent;
-import javax.swing.GroupLayout;
-import javax.swing.JScrollPane;
-import javax.swing.LayoutStyle;
-import org.openide.windows.TopComponent;
-
-/**
- * A non-singleton window/tab for the analysis of two faces.
- *
- * @author Radek Oslejsek
- */
-public class FaceToFaceTab extends TopComponent {
-    
-    private final Canvas canvas ;
-    private final TopControlPanel controlPanel;
-    private final JScrollPane scrollPane;
-
-    /**
-     * Constructor.
-     * @param primary Primary face
-     * @param secondary Secondary face
-     * @param name Tab name
-     */
-    public FaceToFaceTab(HumanFace primary, HumanFace secondary, String name) {
-        canvas = new Canvas();
-        canvas.addPrimaryFace(primary);
-        canvas.addSecondaryFace(secondary);
-        canvas.getScene().setDefaultColors();
-        canvas.addToolBox(new SceneToolboxFaceToFace(canvas));
-        controlPanel = new TopControlPanel();
-        
-        scrollPane = new JScrollPane(controlPanel);
-        
-        setName(name);
-        initComponents();
-        
-        // change the height so that it corresponds to the height of the OpenGL window
-        canvas.addComponentListener(new ComponentAdapter() {
-            @Override
-            public void componentResized(ComponentEvent e) {
-                scrollPane.setSize(ControlPanel.CONTROL_PANEL_WIDTH, canvas.getHeight());
-            }
-        });
-        
-        // (Re)render scene after all change listeners have been called
-        // (the first added listener is called last)
-        controlPanel.addChangeListener(e -> getCanvas().renderScene());
-        new RegistrationAction(canvas, controlPanel);
-        new DistanceAction(canvas, controlPanel);
-        new SymmetryAction(canvas, controlPanel);
-        new ProfilesAction(canvas, controlPanel);
-    }
-    
-    @Override
-    public int getPersistenceType() {
-        return TopComponent.PERSISTENCE_NEVER; // TO DO: change to .PERSISTENCE_ONLY_OPENED when we can re-create the ProjectTC
-    }
-    
-    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(canvas, GroupLayout.DEFAULT_SIZE, 651, Short.MAX_VALUE)
-                                .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
-//                                .addComponent(renderingToolBar, GroupLayout.PREFERRED_SIZE, RenderingToolBar.WIDTH, GroupLayout.PREFERRED_SIZE)
-                                .addComponent(
-                                        scrollPane,
-                                        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(canvas)
-//                                        .addComponent(renderingToolBar)
-                                        .addComponent(scrollPane)
-                                ))
-        );
-    }
-
-    public Canvas getCanvas() {
-        return canvas;
-    }
-    
-}
diff --git a/GUI/src/main/java/cz/fidentis/analyst/core/ManyToManyTab.java b/GUI/src/main/java/cz/fidentis/analyst/core/ManyToManyTab.java
deleted file mode 100644
index a92d45664c7640c2149b5874af34cd3f22853410..0000000000000000000000000000000000000000
--- a/GUI/src/main/java/cz/fidentis/analyst/core/ManyToManyTab.java
+++ /dev/null
@@ -1,85 +0,0 @@
-package cz.fidentis.analyst.core;
-
-import cz.fidentis.analyst.canvas.Canvas;
-import cz.fidentis.analyst.canvas.toolbar.SceneToolboxSingleFace;
-import cz.fidentis.analyst.batch.BatchAction;
-import java.awt.event.ComponentAdapter;
-import java.awt.event.ComponentEvent;
-import javax.swing.GroupLayout;
-import javax.swing.JScrollPane;
-import javax.swing.LayoutStyle;
-import org.openide.windows.TopComponent;
-
-/**
- * A non-singleton window/tab for the batch N:N analysis.
- *
- * @author Radek Oslejsek
- */
-public class ManyToManyTab extends TopComponent {
-    
-    private final Canvas canvas ;
-    private final TopControlPanel controlPanel;
-    private final JScrollPane scrollPane;
-    
-    /**
-     * Constructor.
-     * 
-     * @param name Tab name
-     */
-    public ManyToManyTab(String name) {
-        canvas = new Canvas();
-        //canvas.initScene(faces.get(0)); // !!!
-        canvas.addToolBox(new SceneToolboxSingleFace(canvas)); // !!!
-        controlPanel = new TopControlPanel();
-        
-        scrollPane = new JScrollPane(controlPanel);
-        
-        setName(name);
-        initComponents();
-        
-        // change the height so that it corresponds to the height of the OpenGL window
-        canvas.addComponentListener(new ComponentAdapter() {
-            @Override
-            public void componentResized(ComponentEvent e) {
-                scrollPane.setSize(ControlPanel.CONTROL_PANEL_WIDTH, canvas.getHeight());
-            }
-        });
-        
-        // (Re)render scene after all change listeners have been called
-        // (the first added listener is called last)
-        controlPanel.addChangeListener(e -> canvas.renderScene());
-        new BatchAction(canvas, controlPanel);
-        //new DistanceAction(canvas, controlPanel);
-        //new SymmetryAction(canvas, controlPanel);
-        //new ProfilesAction(canvas, controlPanel);
-    }
-    
-    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(canvas, GroupLayout.DEFAULT_SIZE, 651, Short.MAX_VALUE)
-                                .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
-//                                .addComponent(renderingToolBar, GroupLayout.PREFERRED_SIZE, RenderingToolBar.WIDTH, GroupLayout.PREFERRED_SIZE)
-                                .addComponent(
-                                        scrollPane,
-                                        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(canvas)
-//                                        .addComponent(renderingToolBar)
-                                        .addComponent(scrollPane)
-                                ))
-        );
-    }
-}
diff --git a/GUI/src/main/java/cz/fidentis/analyst/core/ProjectTopComp.form b/GUI/src/main/java/cz/fidentis/analyst/core/ProjectTopComp.form
index d2f0b232cc4ef79c99d50804e1202f09bd953f70..8f592816c46a3feb3185523d2311243356308885 100644
--- a/GUI/src/main/java/cz/fidentis/analyst/core/ProjectTopComp.form
+++ b/GUI/src/main/java/cz/fidentis/analyst/core/ProjectTopComp.form
@@ -40,7 +40,7 @@
   <Layout>
     <DimensionLayout dim="0">
       <Group type="103" groupAlignment="0" attributes="0">
-          <Component id="mainScrollPanel" alignment="1" pref="1217" max="32767" attributes="0"/>
+          <Component id="mainScrollPanel" alignment="1" max="32767" attributes="0"/>
       </Group>
     </DimensionLayout>
     <DimensionLayout dim="1">
@@ -65,13 +65,22 @@
                   <Group type="102" attributes="0">
                       <EmptySpace max="-2" attributes="0"/>
                       <Group type="103" groupAlignment="0" max="-2" attributes="0">
-                          <Component id="faceTableScrollPanel" pref="0" max="32767" attributes="0"/>
-                          <Component id="buttonsPanel" pref="792" max="32767" attributes="0"/>
+                          <Component id="buttonsPanel" max="32767" attributes="0"/>
+                          <Component id="faceTableScrollPanel" pref="863" max="32767" attributes="0"/>
                       </Group>
-                      <EmptySpace type="separate" max="32767" attributes="0"/>
-                      <Group type="103" groupAlignment="0" max="-2" attributes="0">
-                          <Component id="filterPanel" pref="363" max="32767" attributes="0"/>
-                          <Component id="infoPanel" pref="363" max="32767" attributes="0"/>
+                      <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>
@@ -81,8 +90,25 @@
               <Group type="103" groupAlignment="0" attributes="0">
                   <Group type="102" attributes="0">
                       <EmptySpace max="-2" attributes="0"/>
-                      <Component id="buttonsPanel" min="-2" max="-2" 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"/>
@@ -111,17 +137,17 @@
 
               <Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
               <SubComponents>
-                <Component class="javax.swing.JButton" name="addButton1">
+                <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.addButton1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+                      <ResourceString bundle="cz/fidentis/analyst/core/Bundle.properties" key="ProjectTopComp.addButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
                     </Property>
                   </Properties>
                   <Events>
-                    <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="addButton1MouseClicked"/>
+                    <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">
@@ -129,17 +155,17 @@
                     </Constraint>
                   </Constraints>
                 </Component>
-                <Component class="javax.swing.JButton" name="removeButton1">
+                <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.removeButton1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+                      <ResourceString bundle="cz/fidentis/analyst/core/Bundle.properties" key="ProjectTopComp.removeButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
                     </Property>
                   </Properties>
                   <Events>
-                    <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="removeButton1MouseClicked"/>
+                    <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">
@@ -147,17 +173,17 @@
                     </Constraint>
                   </Constraints>
                 </Component>
-                <Component class="javax.swing.JButton" name="selectAllButton1">
+                <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.selectAllButton1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+                      <ResourceString bundle="cz/fidentis/analyst/core/Bundle.properties" key="ProjectTopComp.selectAllButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
                     </Property>
                   </Properties>
                   <Events>
-                    <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="selectAllButton1MouseClicked"/>
+                    <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">
@@ -165,17 +191,17 @@
                     </Constraint>
                   </Constraints>
                 </Component>
-                <Component class="javax.swing.JButton" name="deselectAllButton1">
+                <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.deselectAllButton1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+                      <ResourceString bundle="cz/fidentis/analyst/core/Bundle.properties" key="ProjectTopComp.deselectAllButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
                     </Property>
                   </Properties>
                   <Events>
-                    <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="deselectAllButton1MouseClicked"/>
+                    <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">
@@ -183,18 +209,18 @@
                     </Constraint>
                   </Constraints>
                 </Component>
-                <Component class="javax.swing.JButton" name="inflateButton1">
+                <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.inflateButton1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+                      <ResourceString bundle="cz/fidentis/analyst/core/Bundle.properties" key="ProjectTopComp.inflateButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
                     </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="inflateButton1MouseClicked"/>
+                    <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">
@@ -202,58 +228,58 @@
                     </Constraint>
                   </Constraints>
                 </Component>
-                <Component class="javax.swing.JButton" name="oneOnOneButton1">
+                <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.oneOnOneButton1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+                      <ResourceString bundle="cz/fidentis/analyst/core/Bundle.properties" key="ProjectTopComp.oneOnOneButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
                     </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="oneOnOneButton1MouseClicked"/>
+                    <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="5" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="16" insetsLeft="55" insetsBottom="13" insetsRight="4" anchor="18" weightX="0.0" weightY="0.0"/>
+                      <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="analyseButton1">
+                <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.analyseButton1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+                      <ResourceString bundle="cz/fidentis/analyst/core/Bundle.properties" key="ProjectTopComp.manyToManyButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
                     </Property>
                   </Properties>
                   <Events>
-                    <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="analyseButton1MouseClicked"/>
+                    <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="6" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="16" insetsLeft="16" insetsBottom="13" insetsRight="4" anchor="10" weightX="0.0" weightY="0.0"/>
+                      <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="manyToManyButton">
+                <Component class="javax.swing.JButton" name="analyseButton">
                   <Properties>
                     <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
-                      <Font name="Ubuntu" size="14" style="1"/>
+                      <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, &quot;{key}&quot;)"/>
+                      <ResourceString bundle="cz/fidentis/analyst/core/Bundle.properties" key="ProjectTopComp.analyseButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
                     </Property>
                   </Properties>
                   <Events>
-                    <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="manyToManyButtonMouseClicked"/>
+                    <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="-1" gridY="-1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="0.0" weightY="0.0"/>
+                      <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>
@@ -357,6 +383,56 @@
                 </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, &quot;{key}&quot;)"/>
+                </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, &quot;{key}&quot;)"/>
+                </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, &quot;{key}&quot;)"/>
+                </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, &quot;{key}&quot;)"/>
+                </Property>
+              </Properties>
+              <Events>
+                <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="newProjectButtonMouseClicked"/>
+              </Events>
+            </Component>
           </SubComponents>
         </Container>
       </SubComponents>
diff --git a/GUI/src/main/java/cz/fidentis/analyst/core/ProjectTopComp.java b/GUI/src/main/java/cz/fidentis/analyst/core/ProjectTopComp.java
index d60fc747c9004b6be1545168cae3e990c4bbb378..40caf20ed1dd43fed5806c26d9c892cdfe3e8847 100644
--- a/GUI/src/main/java/cz/fidentis/analyst/core/ProjectTopComp.java
+++ b/GUI/src/main/java/cz/fidentis/analyst/core/ProjectTopComp.java
@@ -1,6 +1,7 @@
 package cz.fidentis.analyst.core;
 
-import cz.fidentis.analyst.Logger;
+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;
@@ -9,23 +10,25 @@ import org.openide.util.NbBundle.Messages;
 import cz.fidentis.analyst.Project;
 import cz.fidentis.analyst.face.HumanFace;
 import cz.fidentis.analyst.dashboard.ModelsTableModel;
-import cz.fidentis.analyst.dashboard.FaceStatePanel;
 import cz.fidentis.analyst.dashboard.FilterPanel;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 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.HashMap;
 import java.util.List;
-import java.util.Map;
 import javax.swing.AbstractAction;
+import javax.swing.ImageIcon;
+import javax.swing.JFileChooser;
 import javax.swing.JOptionPane;
 import javax.swing.event.TableModelEvent;
 import javax.swing.event.TableModelListener;
 import javax.swing.filechooser.FileNameExtensionFilter;
 import org.openide.filesystems.FileChooserBuilder;
+import org.openide.util.Exceptions;
 
 /**
  * The main panel enabling analysts to select the primary and secondary faces,
@@ -57,10 +60,9 @@ import org.openide.filesystems.FileChooserBuilder;
 })
 public final class ProjectTopComp extends TopComponent {
 
-    private final Project project;
+    private Project project;
     
-    private Map<HumanFace, SingleFaceTab> singleFaceTabs = new HashMap<>();
-    private Map<HumanFace, FaceToFaceTab> faceToFaceTabs = new HashMap<>();
+    private List<FaceTab> tabs = new ArrayList<>();
     
     private ModelsTableModel model = new ModelsTableModel(new Object[]{"", "Models", "KD-tree"}, 0);
     
@@ -69,11 +71,14 @@ public final class ProjectTopComp extends TopComponent {
     /* List of indexes of selected Rows */
     private List<Integer> selectedRows = new ArrayList<>();
     
+    private ObjectMapper mapper = new ObjectMapper();
+    
     /**
      * Creates new ProjectTopComp, initializes new project
      */
     public ProjectTopComp() {
         project = new Project();
+       
         initComponents();
         setName(Bundle.CTL_ProjectTopCompTopComponent());
         setToolTipText(Bundle.HINT_ProjectTopCompTopComponent());
@@ -88,12 +93,15 @@ public final class ProjectTopComp extends TopComponent {
             }
         };
         
-        fp = new FilterPanel(filterPanel, listener);
+        //fp = new FilterPanel(filterPanel, listener);
+        
                 
         // Execute infinite OutputWindowThread that redirects messages logged
         // via Logger into the standard output window
         OutputWindowThread.execute();
 
+        openExistingOrNewProject();
+        
     }
 
     /**
@@ -108,18 +116,21 @@ public final class ProjectTopComp extends TopComponent {
         mainScrollPanel = new javax.swing.JScrollPane();
         mainPanel = new javax.swing.JPanel();
         buttonsPanel = new javax.swing.JPanel();
-        addButton1 = new javax.swing.JButton();
-        removeButton1 = new javax.swing.JButton();
-        selectAllButton1 = new javax.swing.JButton();
-        deselectAllButton1 = new javax.swing.JButton();
-        inflateButton1 = new javax.swing.JButton();
-        oneOnOneButton1 = new javax.swing.JButton();
-        analyseButton1 = new javax.swing.JButton();
+        addButton = new javax.swing.JButton();
+        removeButton = new javax.swing.JButton();
+        selectAllButton = new javax.swing.JButton();
+        deselectAllButton = new javax.swing.JButton();
+        inflateButton = new javax.swing.JButton();
+        oneOnOneButton = new javax.swing.JButton();
         manyToManyButton = new javax.swing.JButton();
+        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);
 
@@ -127,11 +138,11 @@ public final class ProjectTopComp extends TopComponent {
         buttonsPanel.setMinimumSize(new java.awt.Dimension(0, 0));
         buttonsPanel.setLayout(new java.awt.GridBagLayout());
 
-        addButton1.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
-        org.openide.awt.Mnemonics.setLocalizedText(addButton1, org.openide.util.NbBundle.getMessage(ProjectTopComp.class, "ProjectTopComp.addButton1.text")); // NOI18N
-        addButton1.addMouseListener(new java.awt.event.MouseAdapter() {
+        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
+        addButton.addMouseListener(new java.awt.event.MouseAdapter() {
             public void mouseClicked(java.awt.event.MouseEvent evt) {
-                addButton1MouseClicked(evt);
+                addButtonMouseClicked(evt);
             }
         });
         gridBagConstraints = new java.awt.GridBagConstraints();
@@ -140,13 +151,13 @@ public final class ProjectTopComp extends TopComponent {
         gridBagConstraints.ipadx = 20;
         gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
         gridBagConstraints.insets = new java.awt.Insets(16, 16, 13, 4);
-        buttonsPanel.add(addButton1, gridBagConstraints);
+        buttonsPanel.add(addButton, gridBagConstraints);
 
-        removeButton1.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
-        org.openide.awt.Mnemonics.setLocalizedText(removeButton1, org.openide.util.NbBundle.getMessage(ProjectTopComp.class, "ProjectTopComp.removeButton1.text")); // NOI18N
-        removeButton1.addMouseListener(new java.awt.event.MouseAdapter() {
+        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
+        removeButton.addMouseListener(new java.awt.event.MouseAdapter() {
             public void mouseClicked(java.awt.event.MouseEvent evt) {
-                removeButton1MouseClicked(evt);
+                removeButtonMouseClicked(evt);
             }
         });
         gridBagConstraints = new java.awt.GridBagConstraints();
@@ -154,13 +165,13 @@ public final class ProjectTopComp extends TopComponent {
         gridBagConstraints.gridy = 0;
         gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
         gridBagConstraints.insets = new java.awt.Insets(16, 22, 13, 4);
-        buttonsPanel.add(removeButton1, gridBagConstraints);
+        buttonsPanel.add(removeButton, gridBagConstraints);
 
-        selectAllButton1.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
-        org.openide.awt.Mnemonics.setLocalizedText(selectAllButton1, org.openide.util.NbBundle.getMessage(ProjectTopComp.class, "ProjectTopComp.selectAllButton1.text")); // NOI18N
-        selectAllButton1.addMouseListener(new java.awt.event.MouseAdapter() {
+        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
+        selectAllButton.addMouseListener(new java.awt.event.MouseAdapter() {
             public void mouseClicked(java.awt.event.MouseEvent evt) {
-                selectAllButton1MouseClicked(evt);
+                selectAllButtonMouseClicked(evt);
             }
         });
         gridBagConstraints = new java.awt.GridBagConstraints();
@@ -168,13 +179,13 @@ public final class ProjectTopComp extends TopComponent {
         gridBagConstraints.gridy = 0;
         gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
         gridBagConstraints.insets = new java.awt.Insets(16, 22, 13, 4);
-        buttonsPanel.add(selectAllButton1, gridBagConstraints);
+        buttonsPanel.add(selectAllButton, gridBagConstraints);
 
-        deselectAllButton1.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
-        org.openide.awt.Mnemonics.setLocalizedText(deselectAllButton1, org.openide.util.NbBundle.getMessage(ProjectTopComp.class, "ProjectTopComp.deselectAllButton1.text")); // NOI18N
-        deselectAllButton1.addMouseListener(new java.awt.event.MouseAdapter() {
+        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
+        deselectAllButton.addMouseListener(new java.awt.event.MouseAdapter() {
             public void mouseClicked(java.awt.event.MouseEvent evt) {
-                deselectAllButton1MouseClicked(evt);
+                deselectAllButtonMouseClicked(evt);
             }
         });
         gridBagConstraints = new java.awt.GridBagConstraints();
@@ -182,14 +193,14 @@ public final class ProjectTopComp extends TopComponent {
         gridBagConstraints.gridy = 0;
         gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
         gridBagConstraints.insets = new java.awt.Insets(16, 22, 13, 4);
-        buttonsPanel.add(deselectAllButton1, gridBagConstraints);
+        buttonsPanel.add(deselectAllButton, gridBagConstraints);
 
-        inflateButton1.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
-        org.openide.awt.Mnemonics.setLocalizedText(inflateButton1, org.openide.util.NbBundle.getMessage(ProjectTopComp.class, "ProjectTopComp.inflateButton1.text")); // NOI18N
-        inflateButton1.setAlignmentX(0.5F);
-        inflateButton1.addMouseListener(new java.awt.event.MouseAdapter() {
+        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
+        inflateButton.setAlignmentX(0.5F);
+        inflateButton.addMouseListener(new java.awt.event.MouseAdapter() {
             public void mouseClicked(java.awt.event.MouseEvent evt) {
-                inflateButton1MouseClicked(evt);
+                inflateButtonMouseClicked(evt);
             }
         });
         gridBagConstraints = new java.awt.GridBagConstraints();
@@ -197,44 +208,49 @@ public final class ProjectTopComp extends TopComponent {
         gridBagConstraints.gridy = 0;
         gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
         gridBagConstraints.insets = new java.awt.Insets(16, 22, 13, 4);
-        buttonsPanel.add(inflateButton1, gridBagConstraints);
+        buttonsPanel.add(inflateButton, gridBagConstraints);
 
-        oneOnOneButton1.setFont(new java.awt.Font("Tahoma", 1, 12)); // NOI18N
-        org.openide.awt.Mnemonics.setLocalizedText(oneOnOneButton1, org.openide.util.NbBundle.getMessage(ProjectTopComp.class, "ProjectTopComp.oneOnOneButton1.text")); // NOI18N
-        oneOnOneButton1.setAlignmentX(0.5F);
-        oneOnOneButton1.addMouseListener(new java.awt.event.MouseAdapter() {
+        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
+        oneOnOneButton.setAlignmentX(0.5F);
+        oneOnOneButton.addMouseListener(new java.awt.event.MouseAdapter() {
             public void mouseClicked(java.awt.event.MouseEvent evt) {
-                oneOnOneButton1MouseClicked(evt);
+                oneOnOneButtonMouseClicked(evt);
             }
         });
         gridBagConstraints = new java.awt.GridBagConstraints();
-        gridBagConstraints.gridx = 5;
+        gridBagConstraints.gridx = 6;
         gridBagConstraints.gridy = 0;
         gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
-        gridBagConstraints.insets = new java.awt.Insets(16, 55, 13, 4);
-        buttonsPanel.add(oneOnOneButton1, gridBagConstraints);
+        gridBagConstraints.insets = new java.awt.Insets(16, 11, 13, 4);
+        buttonsPanel.add(oneOnOneButton, gridBagConstraints);
 
-        analyseButton1.setFont(new java.awt.Font("Tahoma", 1, 12)); // NOI18N
-        org.openide.awt.Mnemonics.setLocalizedText(analyseButton1, org.openide.util.NbBundle.getMessage(ProjectTopComp.class, "ProjectTopComp.analyseButton1.text")); // NOI18N
-        analyseButton1.addMouseListener(new java.awt.event.MouseAdapter() {
+        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
+        manyToManyButton.addMouseListener(new java.awt.event.MouseAdapter() {
             public void mouseClicked(java.awt.event.MouseEvent evt) {
-                analyseButton1MouseClicked(evt);
+                manyToManyButtonMouseClicked(evt);
             }
         });
         gridBagConstraints = new java.awt.GridBagConstraints();
-        gridBagConstraints.gridx = 6;
+        gridBagConstraints.gridx = 5;
         gridBagConstraints.gridy = 0;
-        gridBagConstraints.insets = new java.awt.Insets(16, 16, 13, 4);
-        buttonsPanel.add(analyseButton1, gridBagConstraints);
+        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
+        gridBagConstraints.insets = new java.awt.Insets(16, 30, 13, 4);
+        buttonsPanel.add(manyToManyButton, gridBagConstraints);
 
-        manyToManyButton.setFont(new java.awt.Font("Ubuntu", 1, 14)); // NOI18N
-        org.openide.awt.Mnemonics.setLocalizedText(manyToManyButton, org.openide.util.NbBundle.getMessage(ProjectTopComp.class, "ProjectTopComp.manyToManyButton.text")); // NOI18N
-        manyToManyButton.addMouseListener(new java.awt.event.MouseAdapter() {
+        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
+        analyseButton.addMouseListener(new java.awt.event.MouseAdapter() {
             public void mouseClicked(java.awt.event.MouseEvent evt) {
-                manyToManyButtonMouseClicked(evt);
+                analyseButtonMouseClicked(evt);
             }
         });
-        buttonsPanel.add(manyToManyButton, new java.awt.GridBagConstraints());
+        gridBagConstraints = new java.awt.GridBagConstraints();
+        gridBagConstraints.gridx = 7;
+        gridBagConstraints.gridy = 0;
+        gridBagConstraints.insets = new java.awt.Insets(16, 11, 13, 4);
+        buttonsPanel.add(analyseButton, gridBagConstraints);
 
         faceTableScrollPanel.setPreferredSize(new java.awt.Dimension(812, 750));
 
@@ -297,6 +313,32 @@ public final class ProjectTopComp extends TopComponent {
 
         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
+        saveProjectButton.addMouseListener(new java.awt.event.MouseAdapter() {
+            public void mouseClicked(java.awt.event.MouseEvent evt) {
+                saveProjectButtonMouseClicked(evt);
+            }
+        });
+
+        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
+        openProjectButton.addMouseListener(new java.awt.event.MouseAdapter() {
+            public void mouseClicked(java.awt.event.MouseEvent evt) {
+                openProjectButtonMouseClicked(evt);
+            }
+        });
+
+        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
+        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(
@@ -304,20 +346,40 @@ public final class ProjectTopComp extends TopComponent {
             .addGroup(mainPanelLayout.createSequentialGroup()
                 .addContainerGap()
                 .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
-                    .addComponent(faceTableScrollPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
-                    .addComponent(buttonsPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 792, Short.MAX_VALUE))
-                .addGap(18, 18, 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))
+                    .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()
-                .addComponent(buttonsPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
-                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                .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)
@@ -327,6 +389,8 @@ public final class ProjectTopComp extends TopComponent {
                 .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);
@@ -335,7 +399,7 @@ public final class ProjectTopComp extends TopComponent {
         this.setLayout(layout);
         layout.setHorizontalGroup(
             layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addComponent(mainScrollPanel, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 1217, Short.MAX_VALUE)
+            .addComponent(mainScrollPanel, javax.swing.GroupLayout.Alignment.TRAILING)
         );
         layout.setVerticalGroup(
             layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
@@ -344,27 +408,38 @@ public final class ProjectTopComp extends TopComponent {
     }// </editor-fold>//GEN-END:initComponents
 
     /**
-     * Opens analysis of one selected face, otherwise pops message dialog that
-     * you should select just one face
+     * Opens many to many tab
+     * @param evt
+     */
+    private void manyToManyButtonMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_manyToManyButtonMouseClicked
+       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 analyseButton1MouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_analyseButton1MouseClicked
+    private void oneOnOneButton1MouseClicked(java.awt.event.MouseEvent evt) {                                             
+        //loadTwoModels();
 
-        if (selectedRows.size() == 1) {
+        if (selectedRows.size() == 2) {
 
-            String name = model.getValueAt(selectedRows.get(0), 1).toString();
-            HumanFace face = project.getFaceByName(name);
-            createSingleFaceTab(face, name);
+            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);
+            createFaceToFaceTab(face1, face2, name1 + ":" + name2, false);
         } else {
-            JOptionPane.showMessageDialog(this, "Select one model");
+            JOptionPane.showMessageDialog(this, "Select two models");
         }
-    }//GEN-LAST:event_analyseButton1MouseClicked
+    }                                            
 
     /**
      * Inflates models (selected will be deselected and vice versa)
      * @param evt 
      */
-    private void inflateButton1MouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_inflateButton1MouseClicked
+    private void inflateButtonMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_inflateButtonMouseClicked
 
         for (int i = 0; i < model.getRowCount(); i++) {
             if (model.getValueAt(i, 0) == (Object) true) {
@@ -373,16 +448,20 @@ public final class ProjectTopComp extends TopComponent {
                 model.setValueAt(true, i, 0);
             }
         }
-    }//GEN-LAST:event_inflateButton1MouseClicked
+    }//GEN-LAST:event_inflateButtonMouseClicked
 
     /**
      * Deselects all models from list of models
      * @param evt 
      */
-    private void deselectAllButton1MouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_deselectAllButton1MouseClicked
+    private void deselectAllButtonMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_deselectAllButtonMouseClicked
         deselectAllRows();
-    }//GEN-LAST:event_deselectAllButton1MouseClicked
+    }//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);
@@ -393,40 +472,52 @@ public final class ProjectTopComp extends TopComponent {
      * Selects all models from list of models
      * @param evt 
      */
-    private void selectAllButton1MouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_selectAllButton1MouseClicked
+    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_selectAllButton1MouseClicked
+    }//GEN-LAST:event_selectAllButtonMouseClicked
 
 //GEN-FIRST:event_removeButton1MouseClicked
      /**
      * Removes selected models from list and project
      * @param evt Removes selected faces
      */
-    private void removeButton1MouseClicked(java.awt.event.MouseEvent evt) {                                           
-
+    private void removeButtonMouseClicked(java.awt.event.MouseEvent evt) {                                           
         removeSelectedFaces();
     }    
 //GEN-LAST:event_removeButton1MouseClicked
 
+    /**
+     * Removes selected faces (those which are checked in check boxes)
+     */
     private void removeSelectedFaces() {
         Collections.sort(selectedRows, Collections.reverseOrder());
         selectedRows.forEach(row -> {
-            HumanFace face = this.project.getFaceByName(model.getValueAt(row, 1).toString());
-            this.project.removeFace(face);
+            String name = model.getValueAt(row, 1).toString();
+            List<FaceTab> tabsToClose = new ArrayList<>();
+            tabs.stream().filter(t -> (t.hasFace(name))).forEachOrdered(t -> {
+                tabsToClose.add(t);
+            });
+            
+            while(!tabsToClose.isEmpty()) {
+                tabsToClose.remove(0).close();
+            }
+            
+            project.removeFaceByName(name);
             model.removeRow(row);
         });
         selectedRows.clear();        
+        this.requestActive();
     }
     
     /**
      * Adds new model
      * @param evt 
      */
-    private void addButton1MouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_addButton1MouseClicked
-        loadModel();
-    }//GEN-LAST:event_addButton1MouseClicked
+    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
@@ -441,38 +532,95 @@ public final class ProjectTopComp extends TopComponent {
             if (evt.getClickCount() == 2) {
                 deselectAllRows();
                 model.setValueAt(true, table.getSelectedRow(), 0);
-                analyseButton1MouseClicked(evt);
+                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 
      */
-    private void oneOnOneButton1MouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_oneOnOneButton1MouseClicked
-        //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);
-            createFaceToFaceTab(face1, face2, name1 + ":" + name2);
+
+            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");
         }
-    }//GEN-LAST:event_oneOnOneButton1MouseClicked
-
-    private void manyToManyButtonMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_manyToManyButtonMouseClicked
-        createManyToManyTab("N:N");
-    }//GEN-LAST:event_manyToManyButtonMouseClicked
+    }//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
@@ -491,24 +639,29 @@ public final class ProjectTopComp extends TopComponent {
                     selectedRows.remove((Integer)row);
                 }   
             }
+        } else if (e.getType() == javax.swing.event.TableModelEvent.INSERT || e.getType() == javax.swing.event.TableModelEvent.DELETE) {
+            project.setSaved(false);
         }
     } 
    
     // Variables declaration - do not modify//GEN-BEGIN:variables
-    private javax.swing.JButton addButton1;
-    private javax.swing.JButton analyseButton1;
+    private javax.swing.JButton addButton;
+    private javax.swing.JButton analyseButton;
     private javax.swing.JPanel buttonsPanel;
-    private javax.swing.JButton deselectAllButton1;
+    private javax.swing.JButton deselectAllButton;
     private javax.swing.JScrollPane faceTableScrollPanel;
     private javax.swing.JPanel filterPanel;
-    private javax.swing.JButton inflateButton1;
+    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 oneOnOneButton1;
-    private javax.swing.JButton removeButton1;
-    private javax.swing.JButton selectAllButton1;
+    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
@@ -535,34 +688,35 @@ public final class ProjectTopComp extends TopComponent {
 
     /**
      * Loads model selected in file chooser by user
+     * @param loadFromFile true if models are loaded from file, else user chooses
+     * from FileChooserBuilder
      */
-    public void loadModel() {
-        File[] files = new FileChooserBuilder(ProjectTopComp.class)
+    public void loadModel(boolean loadFromFile) {
+        File[] files;
+        
+        // Selects files with faces (by dialog or from JSON file)
+        if (loadFromFile) {
+            files = new FileChooserBuilder(ProjectTopComp.class)
                 .setTitle("Open human face(s)")
                 .setDefaultWorkingDirectory(new File(System.getProperty("user.home")))
                 //.setApproveText("Add")
                 .setFileFilter(new FileNameExtensionFilter("obj files (*.obj)", "obj"))
                 .setAcceptAllFileFilterUsed(true)
-                .showMultiOpenDialog();
-        
+                .showMultiOpenDialog();           
+        } else {
+            files = new File[project.getCfg().getPaths().size()];
+            files = project.getCfg().openFiles().toArray(files);
+            project.getCfg().clearPaths();
+        }
         
         if (files == null) {
             System.out.print("No file chosen.");
         } else {
-            Logger out = Logger.measureTime();
             for (File file : files) {
-                HumanFace face = null;
-                try {
-                    face = new HumanFace(file, true);
-                    out.printDuration("Loaded model " + face.getShortName() +" with " + face.getMeshModel().getNumVertices() + " vertices");
-                } catch (IOException ex) {
-                    Logger.print(ex.toString());
-                }
-
-                String name = face.getShortName();
-                if (this.project.getFaceByName(name) == null) {
-                    this.project.addFace(face);
-                    face.registerListener(model);
+                
+                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);
                 } else {
                     JOptionPane.showMessageDialog(this, String.format("Model with name %s is already loaded", name));
@@ -570,17 +724,54 @@ public final class ProjectTopComp extends TopComponent {
             }
         }
     }
+    
+    /**
+     * Loads tabs from project file
+     */
+    private void loadTabs() {
+        
+        project.getCfg().getSingleTabFaces().forEach(name -> {
+            HumanFace face1 = project.loadFace(name);
+            createSingleFaceTab(face1, name, true);
+        });
+        
+        project.getCfg().getFaceToFaceTabFaces().keySet().forEach(name -> {
+            HumanFace face1 = project.loadFace(name);
+            project.getCfg().getFaceToFaceTabFaces().get(name).forEach(otherName -> {
+                HumanFace face2 = project.loadFace(otherName);
+                createFaceToFaceTab(face1, face2, name + ":" + otherName, true);
+            });
+        });
+        
+        this.toFront();
+        this.openAtTabPosition(0);
+        this.requestActive();
+        
+    }
 
    /**
     * Creates and opens tab with one face
     * @param face which will be analyzed
     * @param name name of the tab (name of the model)
     */
-    private void createSingleFaceTab(HumanFace face, String name) {
-        SingleFaceTab newTab = new SingleFaceTab(face, name);
-        this.singleFaceTabs.put(face, newTab);
-        newTab.open();
-        newTab.requestActive();
+    private void createSingleFaceTab(HumanFace face, String name, boolean loadFromFile) {
+        ActionListener tabCloseListener = new AbstractAction() {
+            @Override
+            public void actionPerformed(ActionEvent e) {
+                closeTab(e);
+            }
+        };
+        FaceTab newTab = new FaceTab(face, null, name, tabCloseListener);
+        
+        if (!tabs.contains(newTab)) {
+            tabs.add(newTab);
+            if (!loadFromFile) {
+                project.addNewSingleFaceTabFace(name);
+            }
+            newTab.open();
+            newTab.requestActive();
+            this.project.setSaved(false);    
+        }
     }
 
     /**
@@ -589,12 +780,26 @@ public final class ProjectTopComp extends TopComponent {
      * @param face2 which will be analyzed
      * @param name name of the tab
      */
-    private void createFaceToFaceTab(HumanFace face1, HumanFace face2, String name) {
-        FaceToFaceTab newTab = new FaceToFaceTab(face1, face2, name);
-        this.faceToFaceTabs.put(face1, newTab);
-        this.faceToFaceTabs.put(face2, newTab);
-        newTab.open();
-        newTab.requestActive();
+    private void createFaceToFaceTab(HumanFace face1, HumanFace face2, String nameOfTab, boolean loadFromFile) {
+        ActionListener tabCloseListener = new AbstractAction() {
+            @Override
+            public void actionPerformed(ActionEvent e) {
+                closeTab(e);
+            }
+        };
+        
+        FaceTab newTab = new FaceTab(face1, face2, nameOfTab, tabCloseListener);
+        
+        if (!tabs.contains(newTab)) {
+            tabs.add(newTab);
+
+            if (!loadFromFile) {
+                project.addNewFaceToFaceTabFace(face1.getShortName(), face2.getShortName());
+            }
+            newTab.open();
+            newTab.requestActive();
+            this.project.setSaved(false);
+        }
     }
     
     /**
@@ -603,7 +808,16 @@ public final class ProjectTopComp extends TopComponent {
      * @param name name of the tab
      */
     private void createManyToManyTab(String name) {
-        ManyToManyTab newTab = new ManyToManyTab(name);
+        ActionListener tabCloseListener = new AbstractAction() {
+            @Override
+            public void actionPerformed(ActionEvent e) {
+                closeTab(e);
+            }
+        };
+        FaceTab newTab = new FaceTab(null, null, name, tabCloseListener);
+        if (!tabs.contains(newTab)) {
+            tabs.add(newTab);
+        }
         newTab.open();
         newTab.requestActive();
     }
@@ -614,9 +828,13 @@ public final class ProjectTopComp extends TopComponent {
      */
     private void checkFaceState(String faceName) {
         HumanFace face = project.getFaceByName(faceName);
-        FaceStatePanel fsp = new FaceStatePanel(infoPanel, face);
+        //FaceStatePanel fsp = new FaceStatePanel(infoPanel, face);
+        
     }
     
+    /**
+     * Sorts faces by alphabet
+     */
     private void alphabeticalFilter() {
         this.deselectAllRows();
         /*
@@ -642,21 +860,17 @@ public final class ProjectTopComp extends TopComponent {
     
     /**
      * Removes faces from project (and table of faces) based on filter configuration
-     * 
      */
     private void applyFilter() {
-        
         deselectAllRows();
                 
-        for (int i = 0; i < model.getRowCount(); i++) {
-            
+        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())) {
                 model.setValueAt(true, i, 0);
             }
-        }
-        
+        } 
         removeSelectedFaces();
         
         if (fp.isAlphaBeticalFilter()) {
@@ -664,4 +878,166 @@ public final class ProjectTopComp extends TopComponent {
         }
     }
     
+    /**
+     * Asks user whether he wants to create new empty project, or open existing
+     * project
+     */
+    private void openExistingOrNewProject() {
+        ImageIcon newProjectImage = new ImageIcon(ProjectTopComp.class.getClassLoader().getResource("/" + "new.png"));
+        ImageIcon existingProjectImage = new ImageIcon(ProjectTopComp.class.getClassLoader().getResource("/" + "open.png"));
+        Object[] options = {newProjectImage, existingProjectImage};
+        
+        
+        int choice = JOptionPane.showOptionDialog(this, 
+                "Would you like to create a new project or open an existing project?", 
+                "Select project", 
+                JOptionPane.DEFAULT_OPTION, JOptionPane.QUESTION_MESSAGE, 
+                null, 
+                options, 
+                options[0]);
+        
+        if (choice == 1) {
+            openProject();
+        }
+    }
+    
+    /**
+     * Resets all project attributes
+     */
+    private void resetProject() {
+        
+        while (!tabs.isEmpty()) {
+            tabs.get(0).close();
+        }
+        project.removeAll();
+        model.setRowCount(0);
+        selectedRows.clear();        
+    }
+    
+    /**
+     * Checks whether current project is saved, if not then asks user if he wants
+     * to save it
+     * @return 
+     */
+    private boolean loadNewProject() {
+        if (!project.isSaved()) {
+            int showConfirmDialog = JOptionPane.showConfirmDialog(this, "Project is not saved. Would you like to save project?", "Save project", JOptionPane.YES_NO_CANCEL_OPTION);
+            
+            switch (showConfirmDialog) {
+                
+                case JOptionPane.YES_OPTION:
+                    saveProject();
+                    break;
+                case JOptionPane.CANCEL_OPTION:
+                case JOptionPane.CLOSED_OPTION:
+                    return false;
+                default:
+                    break;
+            }
+        }
+        return true;
+    }
+    
+    /**
+     * Saves current project
+     */
+    private void saveProject() {
+        
+        JFileChooser chooser = new JFileChooser();
+        //chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
+        chooser.setFileFilter(new FileNameExtensionFilter("json files (*.json)", "json"));
+        chooser.setAcceptAllFileFilterUsed(true);
+        chooser.showSaveDialog(null);
+        
+        File file = chooser.getSelectedFile();
+        
+        if (file != null) {
+            String filePath = file.getAbsolutePath();
+            if (!filePath.endsWith(".json")) {
+                file = new File(filePath.concat(".json"));
+            }
+
+            try {
+                mapper.writeValue(file, project.getCfg());
+                project.setSaved(true);
+            } catch (IOException ex) {
+                Exceptions.printStackTrace(ex);
+            }
+        }
+        
+   
+    }
+    /**
+     * Opens project, which user selects in File Chooser
+     */
+    private void openProject() {
+        
+        File f;
+        f = new FileChooserBuilder(ProjectTopComp.class)
+                .setTitle("Choose existing project")
+                .setDefaultWorkingDirectory(new File(System.getProperty("user.home")))
+                .setFileFilter(new FileNameExtensionFilter("json files (*.json)", "json"))
+                .setAcceptAllFileFilterUsed(true)
+                .showOpenDialog();
+
+        if (f != null) {
+            try {
+                resetProject();
+                project.setCfg(mapper.readValue(f, ProjectConfiguration.class));
+                loadModel(false);    
+                loadTabs();
+                project.setSaved(true);
+            } catch (IOException ex) {
+                Exceptions.printStackTrace(ex);
+            }
+
+        }  
+    }
+    
+    /**
+     * Creates new project
+     */
+    private void newProject() {    
+        resetProject();
+        project.setCfg(new ProjectConfiguration());
+        project.setSaved(true);
+    }
+
+    /**
+     * Closes tab
+     * @param e ActionEvent
+     */
+    private void closeTab(ActionEvent e) {
+        FaceTab tab = (FaceTab)e.getSource();
+        
+        for (FaceTab t : tabs) {
+            if (t.equals(tab)) {
+                          
+                if (e.getActionCommand().equals("FaceTab")) {
+                    this.project.removeFaceTab(t.getNameOfFace1());
+                } else if (e.getActionCommand().equals("FaceToFaceTab")){
+                    this.project.removeFaceToFaceTab(t.getNameOfFace1(), t.getNameOfFace2());
+                }
+                tabs.remove(t);
+                break;
+            }
+        }
+        
+        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();
+            }
+        }
+        return super.canClose(); //To change body of generated methods, choose Tools | Templates.
+    }
+
 }
diff --git a/GUI/src/main/java/cz/fidentis/analyst/core/SingleFaceTab.java b/GUI/src/main/java/cz/fidentis/analyst/core/SingleFaceTab.java
deleted file mode 100644
index 8733b245f8ef355834a0728fcd6c19f1e7aa90c8..0000000000000000000000000000000000000000
--- a/GUI/src/main/java/cz/fidentis/analyst/core/SingleFaceTab.java
+++ /dev/null
@@ -1,100 +0,0 @@
-package cz.fidentis.analyst.core;
-
-import cz.fidentis.analyst.canvas.Canvas;
-import cz.fidentis.analyst.canvas.toolbar.SceneToolboxSingleFace;
-import cz.fidentis.analyst.curvature.CurvatureAction;
-import cz.fidentis.analyst.face.HumanFace;
-import cz.fidentis.analyst.symmetry.ProfilesAction;
-import cz.fidentis.analyst.symmetry.SymmetryAction;
-import java.awt.event.ComponentAdapter;
-import java.awt.event.ComponentEvent;
-import javax.swing.GroupLayout;
-import javax.swing.JScrollPane;
-import javax.swing.LayoutStyle;
-import org.openide.windows.TopComponent;
-
-/**
- * The non-singleton window/tab for detail inspection of a single face.
- *
- * @author Radek Oslejsek
- */
-public final class SingleFaceTab extends TopComponent {
-    
-    private final Canvas canvas;
-    private final TopControlPanel controlPanel;
-    private final JScrollPane scrollPane;
-    
-    /**
-     * Constructor.
-     * @param face Face
-     * @param name Tab name
-     */
-    public SingleFaceTab(HumanFace face, String name) {
-        canvas = new Canvas();
-        canvas.addPrimaryFace(face);
-        canvas.getScene().setDefaultColors();
-        canvas.addToolBox(new SceneToolboxSingleFace(canvas));
-        controlPanel = new TopControlPanel();
-        
-        scrollPane = new JScrollPane(controlPanel);
-        
-        setName(name);
-        initComponents();
-        
-        // change the height so that it corresponds to the height of the OpenGL window
-        canvas.addComponentListener(new ComponentAdapter() {
-            @Override
-            public void componentResized(ComponentEvent e) {
-                scrollPane.setSize(ControlPanel.CONTROL_PANEL_WIDTH, canvas.getHeight());
-            }
-        });
-
-        /*
-         * Add and open controll panels: 
-         */
-        // (Re)render scene after all change listeners have been called
-        // (the first added listener is called last)
-        controlPanel.addChangeListener(e -> getCanvas().renderScene());
-        new CurvatureAction(getCanvas(), controlPanel);
-        new SymmetryAction(getCanvas(), controlPanel);
-        new ProfilesAction(getCanvas(), controlPanel);
-    }
-    
-    @Override
-    public int getPersistenceType() {
-        return TopComponent.PERSISTENCE_NEVER; // TO DO: change to .PERSISTENCE_ONLY_OPENED when we can re-create the ProjectTC
-    }
-    
-    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(canvas, GroupLayout.DEFAULT_SIZE, 651, Short.MAX_VALUE)
-                                .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
-//                                .addComponent(renderingToolBar, GroupLayout.PREFERRED_SIZE, RenderingToolBar.WIDTH, GroupLayout.PREFERRED_SIZE)
-                                .addComponent(
-                                        scrollPane,
-                                        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(canvas)
-//                                        .addComponent(renderingToolBar)
-                                        .addComponent(scrollPane)
-                                ))
-        );
-    }
-
-    public Canvas getCanvas() {
-        return canvas;
-    }
-}
diff --git a/GUI/src/main/java/cz/fidentis/analyst/dashboard/FaceStatePanel.java b/GUI/src/main/java/cz/fidentis/analyst/dashboard/FaceStatePanel.java
index 70890deeeb22e9cb8e35f11c4744b2de6a028bdc..173f96e0d50094c377364f999bf1e75b57e28baf 100644
--- a/GUI/src/main/java/cz/fidentis/analyst/dashboard/FaceStatePanel.java
+++ b/GUI/src/main/java/cz/fidentis/analyst/dashboard/FaceStatePanel.java
@@ -44,7 +44,7 @@ public final class FaceStatePanel extends JPanel {
             hasKDtree.setIcon(notCheck);
         }
         builder.addLine();
-        
+
         hasFeaturePoints = builder.addLabelLine("Has Feature points");
         if (face.hasFeaturePoints()) {
             hasFeaturePoints.setIcon(check);
@@ -52,15 +52,15 @@ public final class FaceStatePanel extends JPanel {
             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/ModelsTableModel.java b/GUI/src/main/java/cz/fidentis/analyst/dashboard/ModelsTableModel.java
index 7367bb56a2cbac2710769106e1b7063af74c3c5e..e7e979ed7629b21e3d69f82138be891282d22cba 100644
--- a/GUI/src/main/java/cz/fidentis/analyst/dashboard/ModelsTableModel.java
+++ b/GUI/src/main/java/cz/fidentis/analyst/dashboard/ModelsTableModel.java
@@ -58,7 +58,7 @@ public class ModelsTableModel extends DefaultTableModel implements HumanFaceList
     /**
      * Adds new row to model
      * @param name String name of the face
-     * @param hasKD boolean if face has KD tree calculated
+     * @param hasKD Boolean if face has KD tree calculated
      */
     public void addRowWithName(String name, boolean hasKD) {
         if (hasKD) {
diff --git a/GUI/src/main/resources/cz/fidentis/analyst/core/Bundle.properties b/GUI/src/main/resources/cz/fidentis/analyst/core/Bundle.properties
index 4b6044b01a8afb683eb7f3ab1cbb202ccc168e78..fb98808fdf280afd4593d85f9b9ffe4464aa6b4f 100644
--- a/GUI/src/main/resources/cz/fidentis/analyst/core/Bundle.properties
+++ b/GUI/src/main/resources/cz/fidentis/analyst/core/Bundle.properties
@@ -14,12 +14,6 @@ ProjectTopComp.jTable1.columnModel.title3=Title 4
 ProjectTopComp.jTable1.columnModel.title1=Title 2
 ProjectTopComp.jTable1.columnModel.title0_1=Models
 ProjectTopComp.jTable1.columnModel.title1_1=
-ProjectTopComp.analyseButton1.text=Analyse
-ProjectTopComp.inflateButton1.text=Inflate
-ProjectTopComp.deselectAllButton1.text=Deselect all
-ProjectTopComp.selectAllButton1.text=Select all
-ProjectTopComp.removeButton1.text=Remove
-ProjectTopComp.addButton1.text=Add
 ProjectTopComp.jTable2.columnModel.title3=Title 4
 ProjectTopComp.jTable2.columnModel.title2=Title 3
 ProjectTopComp.jTable2.columnModel.title1=Title 2
@@ -29,5 +23,21 @@ MeasurementsPanel.jLabel3.text=Feature points distance:
 MeasurementsPanel.jTextField1.text=
 MeasurementsPanel.jTextField2.text=
 MeasurementsPanel.jTextField3.text=
-ProjectTopComp.oneOnOneButton1.text=Open 1:1
+StartFrame.jButton1.text=jButton1
+StartFrame.jButton2.text=jButton2
+StartFrame.jButton3.text=jButton3
+StartPanel.jButton1.text=
+StartPanel.jButton2.text=
+StartPanel.jButton3.text=Cancel
+ProjectTopComp.saveProjectButton.AccessibleContext.accessibleName=SaveProject
+ProjectTopComp.saveProjectButton.text=
+ProjectTopComp.openProjectButton.text=
+ProjectTopComp.newProjectButton.text=
 ProjectTopComp.manyToManyButton.text=N:N
+ProjectTopComp.analyseButton.text=Analyse
+ProjectTopComp.addButton.text=Add
+ProjectTopComp.removeButton.text=Remove
+ProjectTopComp.selectAllButton.text=Select all
+ProjectTopComp.deselectAllButton.text=Deselect all
+ProjectTopComp.inflateButton.text=Inflate
+ProjectTopComp.oneOnOneButton.text=Open 1:1
diff --git a/GUI/src/main/resources/new.png b/GUI/src/main/resources/new.png
new file mode 100644
index 0000000000000000000000000000000000000000..3b7bc90aedd63fb996407cb0ebb8ab2543385f9b
Binary files /dev/null and b/GUI/src/main/resources/new.png differ
diff --git a/GUI/src/main/resources/new100x24.png b/GUI/src/main/resources/new100x24.png
new file mode 100644
index 0000000000000000000000000000000000000000..8bef62ef23ae0aec69a1614b16bf2993ff692102
Binary files /dev/null and b/GUI/src/main/resources/new100x24.png differ
diff --git a/GUI/src/main/resources/open.png b/GUI/src/main/resources/open.png
new file mode 100644
index 0000000000000000000000000000000000000000..b13c5d7b0152df6b11dd21505414718ce9c34d37
Binary files /dev/null and b/GUI/src/main/resources/open.png differ
diff --git a/GUI/src/main/resources/open100x24.png b/GUI/src/main/resources/open100x24.png
new file mode 100644
index 0000000000000000000000000000000000000000..0e8ad33d6b8af6869176aa13660230ff6bf0d839
Binary files /dev/null and b/GUI/src/main/resources/open100x24.png differ
diff --git a/GUI/src/main/resources/save100x24.png b/GUI/src/main/resources/save100x24.png
new file mode 100644
index 0000000000000000000000000000000000000000..defc919847ac755bbfb5677d7cd733c904ecafaa
Binary files /dev/null and b/GUI/src/main/resources/save100x24.png differ