From 647c8cd5cefefcfa39b2579ec926529978de27f8 Mon Sep 17 00:00:00 2001
From: Piotr Gawron <p.gawron@atcomp.pl>
Date: Mon, 17 Mar 2025 16:49:43 +0100
Subject: [PATCH] export of layer images added

---
 .../model/celldesigner/LayerXmlParser.java    | 34 +++++++++++--
 .../CellDesignerTestFunctions.java            | 19 ++++++-
 .../model/celldesigner/ProjectExportTest.java | 38 ++++++++++++++
 .../converter/ComplexZipConverter.java        |  2 +-
 .../mapviewer/converter/ProjectFactory.java   | 12 +++++
 .../commands/CreateHierarchyCommand.java      | 32 +++++++++++-
 .../commands/CommandTestFunctions.java        | 40 +++++++++++++++
 .../commands/CreateHierarchyCommandTest.java  | 50 +++++++++++++++----
 .../model/map/layout/graphics/Layer.java      |  1 +
 .../layout/graphics/LayerImageComparator.java | 10 +++-
 .../model/map/layout/graphics/LayerText.java  |  2 +-
 .../lcsb/mapviewer/model/map/model/Model.java |  2 +
 .../mapviewer/model/map/model/ModelData.java  |  4 ++
 .../model/map/model/ModelFullIndexed.java     |  5 ++
 14 files changed, 229 insertions(+), 22 deletions(-)

diff --git a/converter-CellDesigner/src/main/java/lcsb/mapviewer/converter/model/celldesigner/LayerXmlParser.java b/converter-CellDesigner/src/main/java/lcsb/mapviewer/converter/model/celldesigner/LayerXmlParser.java
index 4195ae9f81..592a89b005 100644
--- a/converter-CellDesigner/src/main/java/lcsb/mapviewer/converter/model/celldesigner/LayerXmlParser.java
+++ b/converter-CellDesigner/src/main/java/lcsb/mapviewer/converter/model/celldesigner/LayerXmlParser.java
@@ -3,12 +3,14 @@ package lcsb.mapviewer.converter.model.celldesigner;
 import lcsb.mapviewer.common.XmlParser;
 import lcsb.mapviewer.common.exception.InvalidXmlSchemaException;
 import lcsb.mapviewer.common.geometry.ColorParser;
+import lcsb.mapviewer.converter.ComplexZipConverter;
 import lcsb.mapviewer.model.graphics.ArrowType;
 import lcsb.mapviewer.model.graphics.LineType;
 import lcsb.mapviewer.model.graphics.PolylineData;
 import lcsb.mapviewer.model.map.layout.BlockDiagram;
 import lcsb.mapviewer.model.map.layout.ElementGroup;
 import lcsb.mapviewer.model.map.layout.graphics.Layer;
+import lcsb.mapviewer.model.map.layout.graphics.LayerImage;
 import lcsb.mapviewer.model.map.layout.graphics.LayerOval;
 import lcsb.mapviewer.model.map.layout.graphics.LayerRect;
 import lcsb.mapviewer.model.map.layout.graphics.LayerText;
@@ -23,6 +25,7 @@ import org.w3c.dom.NodeList;
 
 import java.awt.Color;
 import java.awt.geom.Point2D;
+import java.io.File;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
@@ -278,15 +281,18 @@ public class LayerXmlParser {
     if (!NumberUtils.isParsable(id)) {
       id = (problematicIdCounter++) + "";
     }
-    result.append("<celldesigner:layer id =\"" + id + "\" ");
-    result.append(" name =\"" + XmlParser.escapeXml(layer.getName()) + "\" ");
-    result.append(" locked =\"" + layer.isLocked() + "\" ");
-    result.append(" visible =\"" + layer.isVisible() + "\">\n");
+    result.append("<celldesigner:layer id =\"").append(id).append("\" ");
+    result.append(" name =\"").append(XmlParser.escapeXml(layer.getName())).append("\" ");
+    result.append(" locked =\"").append(layer.isLocked()).append("\" ");
+    result.append(" visible =\"").append(layer.isVisible()).append("\">\n");
 
     result.append("<celldesigner:listOfTexts>\n");
     for (final LayerText layerText : layer.getTexts()) {
       result.append(layerTextToXml(layerText));
     }
+    for (final LayerImage layerImage : layer.getImages()) {
+      result.append(layerImageToXml(layerImage));
+    }
     result.append("</celldesigner:listOfTexts>\n");
 
     result.append("<celldesigner:listOfSquares>\n");
@@ -553,4 +559,24 @@ public class LayerXmlParser {
     return result.toString();
   }
 
+  String layerImageToXml(final LayerImage layer) {
+    StringBuilder result = new StringBuilder();
+    result.append("<celldesigner:layerSpeciesAlias>");
+    result.append("<celldesigner:layerNotes>\n");
+    String notes = "";
+    if (layer.getGlyph() != null) {
+      notes += "\n" + ComplexZipConverter.GLYPH_PREFIX + "glyphs/" + new File(layer.getGlyph().getFile().getOriginalFileName()).getName();
+    }
+    result.append(notes);
+    result.append("\n</celldesigner:layerNotes>");
+    result.append("<celldesigner:paint color=\"" + XmlParser.colorToString(Color.BLACK) + "\"/>");
+    result.append("<celldesigner:bounds x=\"" + layer.getX() + "\" ");
+    result.append(" y=\"" + layer.getY() + "\" ");
+    result.append(" w=\"" + layer.getWidth() + "\" ");
+    result.append(" h=\"" + layer.getHeight() + "\"/>");
+    result.append("<celldesigner:font size=\"" + ((int) LayerText.DEFAULT_LAYER_FONT_SIZE) + "\"/>");
+    result.append("</celldesigner:layerSpeciesAlias>\n");
+    return result.toString();
+  }
+
 }
diff --git a/converter-CellDesigner/src/test/java/lcsb/mapviewer/converter/model/celldesigner/CellDesignerTestFunctions.java b/converter-CellDesigner/src/test/java/lcsb/mapviewer/converter/model/celldesigner/CellDesignerTestFunctions.java
index c6f6b59e96..379d507b56 100644
--- a/converter-CellDesigner/src/test/java/lcsb/mapviewer/converter/model/celldesigner/CellDesignerTestFunctions.java
+++ b/converter-CellDesigner/src/test/java/lcsb/mapviewer/converter/model/celldesigner/CellDesignerTestFunctions.java
@@ -24,6 +24,7 @@ import lcsb.mapviewer.model.map.kinetics.SbmlParameter;
 import lcsb.mapviewer.model.map.kinetics.SbmlUnit;
 import lcsb.mapviewer.model.map.layout.graphics.Glyph;
 import lcsb.mapviewer.model.map.layout.graphics.Layer;
+import lcsb.mapviewer.model.map.layout.graphics.LayerImage;
 import lcsb.mapviewer.model.map.layout.graphics.LayerText;
 import lcsb.mapviewer.model.map.model.Model;
 import lcsb.mapviewer.model.map.model.ModelComparator;
@@ -111,6 +112,9 @@ public abstract class CellDesignerTestFunctions extends TestUtils {
   protected void clearModelFromZ(final Model model) {
     for (final Drawable bioEntity : model.getDrawables()) {
       bioEntity.setZ(null);
+      if (bioEntity instanceof Element) {
+        ((Element) bioEntity).setVisibilityLevel(0);
+      }
     }
   }
 
@@ -172,11 +176,22 @@ public abstract class CellDesignerTestFunctions extends TestUtils {
     layerText.setWidth(233.0);
     layerText.setHeight(188.0);
     layerText.setZ(0);
-    layerText.setNotes("asd as");
-    layerText.setColor(Color.BLACK);
+    layerText.setNotes(faker.lorem().paragraph());
+    layerText.setColor(new ColorParser().parse(faker.color().hex()));
     return layerText;
   }
 
+  protected LayerImage createImage() throws IOException {
+    final LayerImage image = new LayerImage();
+    image.setX(256.0);
+    image.setY(79.0);
+    image.setWidth(233.0);
+    image.setHeight(188.0);
+    image.setZ(0);
+    image.setGlyph(createGlyph());
+    return image;
+  }
+
   protected static SbmlFunction createFunction() throws InvalidXmlSchemaException {
     SbmlFunction fun = new SbmlFunction("fun_id" + (idCounter++));
     fun.setDefinition("<math xmlns=\"http://www.w3.org/1998/Math/MathML\">\n"
diff --git a/converter-CellDesigner/src/test/java/lcsb/mapviewer/converter/model/celldesigner/ProjectExportTest.java b/converter-CellDesigner/src/test/java/lcsb/mapviewer/converter/model/celldesigner/ProjectExportTest.java
index 4f29ab512c..fb3eb9eaab 100644
--- a/converter-CellDesigner/src/test/java/lcsb/mapviewer/converter/model/celldesigner/ProjectExportTest.java
+++ b/converter-CellDesigner/src/test/java/lcsb/mapviewer/converter/model/celldesigner/ProjectExportTest.java
@@ -1,5 +1,6 @@
 package lcsb.mapviewer.converter.model.celldesigner;
 
+import lcsb.mapviewer.commands.CreateHierarchyCommand;
 import lcsb.mapviewer.converter.ComplexZipConverter;
 import lcsb.mapviewer.converter.ComplexZipConverterParams;
 import lcsb.mapviewer.converter.ProjectFactory;
@@ -8,6 +9,9 @@ import lcsb.mapviewer.converter.zip.ZipEntryFileFactory;
 import lcsb.mapviewer.model.Project;
 import lcsb.mapviewer.model.ProjectComparator;
 import lcsb.mapviewer.model.map.layout.graphics.Glyph;
+import lcsb.mapviewer.model.map.layout.graphics.Layer;
+import lcsb.mapviewer.model.map.layout.graphics.LayerImage;
+import lcsb.mapviewer.model.map.layout.graphics.LayerText;
 import lcsb.mapviewer.model.map.model.ElementSubmodelConnection;
 import lcsb.mapviewer.model.map.model.Model;
 import lcsb.mapviewer.model.map.model.ModelData;
@@ -175,6 +179,7 @@ public class ProjectExportTest extends CellDesignerTestFunctions {
       clearModelFromZ(model);
     }
     for (ModelData model : project2.getModels()) {
+      new CreateHierarchyCommand(model.getModel(), 10, 1000).execute();
       clearModelFromZ(model);
     }
 
@@ -201,4 +206,37 @@ public class ProjectExportTest extends CellDesignerTestFunctions {
     return complexParams;
   }
 
+  @Test
+  public void testLayerWithText() throws Exception {
+    Project project = createProject();
+    Model model = createEmptyModel();
+    model.setWidth(745);
+    model.setHeight(346);
+    Layer layer = createLayer();
+    LayerText layerText = createText();
+    layer.addLayerText(layerText);
+    model.addLayer(layer);
+
+    project.addModel(model);
+
+    testSerializationOverZip(project);
+  }
+
+  @Test
+  public void testLayerWithImage() throws Exception {
+    Project project = createProject();
+    Model model = createEmptyModel();
+    model.setWidth(745);
+    model.setHeight(346);
+    Layer layer = createLayer();
+    LayerImage image = createImage();
+    layer.addLayerImage(image);
+    model.addLayer(layer);
+
+    project.addModel(model);
+    project.addGlyph(image.getGlyph());
+
+    testSerializationOverZip(project);
+  }
+
 }
diff --git a/converter/src/main/java/lcsb/mapviewer/converter/ComplexZipConverter.java b/converter/src/main/java/lcsb/mapviewer/converter/ComplexZipConverter.java
index c00117499d..cf641959f4 100644
--- a/converter/src/main/java/lcsb/mapviewer/converter/ComplexZipConverter.java
+++ b/converter/src/main/java/lcsb/mapviewer/converter/ComplexZipConverter.java
@@ -68,7 +68,7 @@ public class ComplexZipConverter {
    */
   private static final Logger logger = LogManager.getLogger();
   protected static final String IMMEDIATE_LINK_PREFIX = "IMMEDIATE_LINK:";
-  protected static final String GLYPH_PREFIX = "Glyph:";
+  public static final String GLYPH_PREFIX = "Glyph:";
 
   /**
    * Class used to create single submap from a file.
diff --git a/converter/src/main/java/lcsb/mapviewer/converter/ProjectFactory.java b/converter/src/main/java/lcsb/mapviewer/converter/ProjectFactory.java
index ea388b84d9..6a4939e969 100644
--- a/converter/src/main/java/lcsb/mapviewer/converter/ProjectFactory.java
+++ b/converter/src/main/java/lcsb/mapviewer/converter/ProjectFactory.java
@@ -14,6 +14,7 @@ import lcsb.mapviewer.model.map.compartment.Compartment;
 import lcsb.mapviewer.model.map.compartment.SquareCompartment;
 import lcsb.mapviewer.model.map.layout.graphics.Glyph;
 import lcsb.mapviewer.model.map.layout.graphics.Layer;
+import lcsb.mapviewer.model.map.layout.graphics.LayerImage;
 import lcsb.mapviewer.model.map.layout.graphics.LayerText;
 import lcsb.mapviewer.model.map.model.ElementSubmodelConnection;
 import lcsb.mapviewer.model.map.model.Model;
@@ -218,6 +219,17 @@ public class ProjectFactory {
         zos.closeEntry();
       }
     }
+    for (Layer layer : model.getLayers()) {
+      for (LayerImage image : layer.getImages()) {
+        if (image.getGlyph() != null) {
+          UploadedFileEntry uploadedFileEntry = image.getGlyph().getFile();
+          ZipEntry entry = new ZipEntry(ZipEntryFileFactory.GLYPHS_DIRECTORY + new File(uploadedFileEntry.getOriginalFileName()).getName());
+          zos.putNextEntry(entry);
+          zos.write(uploadedFileEntry.getFileContent());
+          zos.closeEntry();
+        }
+      }
+    }
   }
 
   private int idCounter = 0;
diff --git a/model-command/src/main/java/lcsb/mapviewer/commands/CreateHierarchyCommand.java b/model-command/src/main/java/lcsb/mapviewer/commands/CreateHierarchyCommand.java
index 9a6046aa98..30baa1a223 100644
--- a/model-command/src/main/java/lcsb/mapviewer/commands/CreateHierarchyCommand.java
+++ b/model-command/src/main/java/lcsb/mapviewer/commands/CreateHierarchyCommand.java
@@ -8,6 +8,7 @@ import lcsb.mapviewer.model.graphics.VerticalAlign;
 import lcsb.mapviewer.model.map.compartment.Compartment;
 import lcsb.mapviewer.model.map.compartment.PathwayCompartment;
 import lcsb.mapviewer.model.map.layout.graphics.Layer;
+import lcsb.mapviewer.model.map.layout.graphics.LayerImage;
 import lcsb.mapviewer.model.map.layout.graphics.LayerRect;
 import lcsb.mapviewer.model.map.layout.graphics.LayerText;
 import lcsb.mapviewer.model.map.model.Model;
@@ -33,7 +34,7 @@ import java.util.Set;
  */
 public class CreateHierarchyCommand extends ModelCommand {
 
-  public static final String TEXT_LAYER_NAME = "text";
+  public static final String PATHWAY_LAYER_NAME = "pathways";
 
   /**
    * Natural logarithm of four.
@@ -154,8 +155,10 @@ public class CreateHierarchyCommand extends ModelCommand {
     RestAnnotationParser rap = new RestAnnotationParser();
     Model model = getModel();
     int id = 0;
+    Layer pathwayLayer = null;
     for (final Layer layer : model.getLayers()) {
-      if (!Objects.equals(layer.getName(), TEXT_LAYER_NAME)) {
+      if (Objects.equals(layer.getName(), PATHWAY_LAYER_NAME)) {
+        pathwayLayer = layer;
         for (final LayerRect rect : layer.getRectangles()) {
           int nextId = getNextArtId(model, id);
           id = nextId + 1;
@@ -207,8 +210,33 @@ public class CreateHierarchyCommand extends ModelCommand {
           model.addElement(compartment);
 
         }
+      } else {
+        Set<LayerText> objectsToRemove = new HashSet<>();
+        for (final LayerText text : layer.getTexts()) {
+          int nextId = getNextArtId(model, id);
+          id = nextId + 1;
+
+          if (text.getGlyph() != null) {
+            objectsToRemove.add(text);
+
+            LayerImage image = new LayerImage();
+            image.setX(text.getX());
+            image.setY(text.getY());
+            image.setZ(text.getZ());
+            image.setWidth(text.getWidth());
+            image.setHeight(text.getHeight());
+            image.setGlyph(text.getGlyph());
+            layer.addLayerImage(image);
+          }
+        }
+        for (LayerText image : objectsToRemove) {
+          layer.removeLayerText(image);
+        }
       }
     }
+    if (pathwayLayer != null) {
+      model.removeLayer(pathwayLayer);
+    }
   }
 
   private int getNextArtId(final Model model, final int id) {
diff --git a/model-command/src/test/java/lcsb/mapviewer/commands/CommandTestFunctions.java b/model-command/src/test/java/lcsb/mapviewer/commands/CommandTestFunctions.java
index 3b9ab3f51b..a9f361fbdf 100644
--- a/model-command/src/test/java/lcsb/mapviewer/commands/CommandTestFunctions.java
+++ b/model-command/src/test/java/lcsb/mapviewer/commands/CommandTestFunctions.java
@@ -3,9 +3,14 @@ package lcsb.mapviewer.commands;
 import lcsb.mapviewer.common.Configuration;
 import lcsb.mapviewer.common.tests.TestUtils;
 import lcsb.mapviewer.common.tests.UnitTestFailedWatcher;
+import lcsb.mapviewer.model.cache.UploadedFileEntry;
 import lcsb.mapviewer.model.graphics.HorizontalAlign;
 import lcsb.mapviewer.model.graphics.PolylineData;
 import lcsb.mapviewer.model.graphics.VerticalAlign;
+import lcsb.mapviewer.model.map.layout.graphics.Glyph;
+import lcsb.mapviewer.model.map.layout.graphics.LayerImage;
+import lcsb.mapviewer.model.map.layout.graphics.LayerRect;
+import lcsb.mapviewer.model.map.layout.graphics.LayerText;
 import lcsb.mapviewer.model.map.model.Model;
 import lcsb.mapviewer.model.map.model.ModelFullIndexed;
 import lcsb.mapviewer.model.map.reaction.Product;
@@ -21,6 +26,7 @@ import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 import org.junit.Rule;
 
+import java.awt.Color;
 import java.awt.geom.Point2D;
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -137,4 +143,38 @@ public abstract class CommandTestFunctions extends TestUtils {
     element.setNameHorizontalAlign(HorizontalAlign.CENTER);
   }
 
+  protected LayerRect createLayerRect() {
+    LayerRect layerRect = new LayerRect();
+    layerRect.setBorderColor(Color.BLUE);
+    layerRect.setFillColor(Color.YELLOW);
+    return layerRect;
+  }
+
+  protected LayerImage createLayerImage() {
+    LayerImage layerImage = new LayerImage();
+    layerImage.setGlyph(createGlyph());
+    return layerImage;
+  }
+
+  protected LayerText createLayerText() {
+    LayerText layerText = new LayerText();
+    layerText.setGlyph(createGlyph());
+    layerText.setFillColor(Color.YELLOW);
+    layerText.setNotes(faker.lorem().sentence());
+    return layerText;
+  }
+
+  protected Glyph createGlyph() {
+    Glyph glyph = new Glyph();
+    glyph.setFile(createFile());
+    return glyph;
+  }
+
+  private UploadedFileEntry createFile() {
+    UploadedFileEntry file = new UploadedFileEntry();
+    file.setOriginalFileName(faker.file().fileName());
+    return file;
+  }
+
+
 }
diff --git a/model-command/src/test/java/lcsb/mapviewer/commands/CreateHierarchyCommandTest.java b/model-command/src/test/java/lcsb/mapviewer/commands/CreateHierarchyCommandTest.java
index 246adc24a1..32dc9dbba3 100644
--- a/model-command/src/test/java/lcsb/mapviewer/commands/CreateHierarchyCommandTest.java
+++ b/model-command/src/test/java/lcsb/mapviewer/commands/CreateHierarchyCommandTest.java
@@ -11,8 +11,6 @@ import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 
-import java.awt.Color;
-
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
@@ -32,6 +30,7 @@ public class CreateHierarchyCommandTest extends CommandTestFunctions {
     Model model = new ModelFullIndexed(null);
 
     Layer layer = new Layer();
+    layer.setName(CreateHierarchyCommand.PATHWAY_LAYER_NAME);
     LayerRect layerRect = createLayerRect();
     layer.addLayerRect(layerRect);
     model.addLayer(layer);
@@ -44,18 +43,12 @@ public class CreateHierarchyCommandTest extends CommandTestFunctions {
     assertEquals(pathway.getBorderColor(), pathway.getFontColor());
   }
 
-  private LayerRect createLayerRect() {
-    LayerRect layerRect = new LayerRect();
-    layerRect.setBorderColor(Color.BLUE);
-    layerRect.setFillColor(Color.YELLOW);
-    return layerRect;
-  }
-
   @Test
   public void testCreatePathwayWhenIdIsTaken() throws Exception {
     Model model = new ModelFullIndexed(null);
 
     Layer layer = new Layer();
+    layer.setName(CreateHierarchyCommand.PATHWAY_LAYER_NAME);
     LayerRect layerRect = createLayerRect();
     layer.addLayerRect(layerRect);
     LayerRect layerRect2 = createLayerRect();
@@ -84,6 +77,7 @@ public class CreateHierarchyCommandTest extends CommandTestFunctions {
     Model model = new ModelFullIndexed(null);
 
     Layer layer = new Layer();
+    layer.setName(CreateHierarchyCommand.PATHWAY_LAYER_NAME);
     LayerText layerText = new LayerText();
     layerText.setNotes("colors check\n"
         + "SemanticZoomLevelVisibility: 3\n"
@@ -116,7 +110,7 @@ public class CreateHierarchyCommandTest extends CommandTestFunctions {
     Model model = new ModelFullIndexed(null);
 
     Layer layer = new Layer();
-    layer.setName(CreateHierarchyCommand.TEXT_LAYER_NAME);
+    layer.setName(CreateHierarchyCommand.PATHWAY_LAYER_NAME + "blah");
     LayerRect layerRect = createLayerRect();
     layer.addLayerRect(layerRect);
     model.addLayer(layer);
@@ -127,4 +121,40 @@ public class CreateHierarchyCommandTest extends CommandTestFunctions {
     assertEquals(0, model.getCompartments().size());
   }
 
+  @Test
+  public void deletePathwayLayer() {
+    Model model = new ModelFullIndexed(null);
+
+    Layer layer = new Layer();
+    layer.setName(CreateHierarchyCommand.PATHWAY_LAYER_NAME);
+    LayerRect layerRect = createLayerRect();
+    layer.addLayerRect(layerRect);
+    model.addLayer(layer);
+
+    CreateHierarchyCommand command = new CreateHierarchyCommand(model, 4, 80);
+    command.createArtificials();
+
+    PathwayCompartment pathway = (PathwayCompartment) model.getCompartments().get(0);
+
+    assertEquals(0, model.getLayers().size());
+  }
+
+  @Test
+  public void testCreateImageFromText() {
+    Model model = new ModelFullIndexed(null);
+
+    Layer layer = new Layer();
+    layer.setName(CreateHierarchyCommand.PATHWAY_LAYER_NAME + "blah");
+    LayerText layerText = createLayerText();
+    layer.addLayerText(layerText);
+    model.addLayer(layer);
+
+    CreateHierarchyCommand command = new CreateHierarchyCommand(model, 4, 80);
+    command.createArtificials();
+
+    assertEquals(0, model.getCompartments().size());
+    assertEquals(1, layer.getImages().size());
+    assertEquals(0, layer.getTexts().size());
+  }
+
 }
diff --git a/model/src/main/java/lcsb/mapviewer/model/map/layout/graphics/Layer.java b/model/src/main/java/lcsb/mapviewer/model/map/layout/graphics/Layer.java
index 7ccf3708f6..fd635e43da 100644
--- a/model/src/main/java/lcsb/mapviewer/model/map/layout/graphics/Layer.java
+++ b/model/src/main/java/lcsb/mapviewer/model/map/layout/graphics/Layer.java
@@ -434,6 +434,7 @@ public class Layer implements MinervaEntity {
     result.addAll(ovals);
     result.addAll(rectangles);
     result.addAll(texts);
+    result.addAll(images);
     return result;
   }
 
diff --git a/model/src/main/java/lcsb/mapviewer/model/map/layout/graphics/LayerImageComparator.java b/model/src/main/java/lcsb/mapviewer/model/map/layout/graphics/LayerImageComparator.java
index 1849718e21..9c45516173 100644
--- a/model/src/main/java/lcsb/mapviewer/model/map/layout/graphics/LayerImageComparator.java
+++ b/model/src/main/java/lcsb/mapviewer/model/map/layout/graphics/LayerImageComparator.java
@@ -23,23 +23,29 @@ public class LayerImageComparator extends Comparator<LayerImage> {
     DoubleComparator doubleComparator = new DoubleComparator(epsilon);
     IntegerComparator integerComparator = new IntegerComparator();
 
-    if (doubleComparator.compare(arg0.getWidth(), arg1.getWidth()) != 0) {
-      return doubleComparator.compare(arg0.getWidth(), arg1.getWidth());
+    int status = doubleComparator.compare(arg0.getWidth(), arg1.getWidth());
+    if (status != 0) {
+      logger.debug("Image width different: {} != {}", arg0.getWidth(), arg1.getWidth());
+      return status;
     }
 
     if (doubleComparator.compare(arg0.getHeight(), arg1.getHeight()) != 0) {
+      logger.debug("Image Height different: {} != {}", arg0.getHeight(), arg1.getHeight());
       return doubleComparator.compare(arg0.getHeight(), arg1.getHeight());
     }
 
     if (doubleComparator.compare(arg0.getX(), arg1.getX()) != 0) {
+      logger.debug("Image X different: {} != {}", arg0.getX(), arg1.getX());
       return doubleComparator.compare(arg0.getX(), arg1.getX());
     }
 
     if (doubleComparator.compare(arg0.getY(), arg1.getY()) != 0) {
+      logger.debug("Image Y different: {} != {}", arg0.getY(), arg1.getY());
       return doubleComparator.compare(arg0.getY(), arg1.getY());
     }
 
     if (integerComparator.compare(arg0.getZ(), arg1.getZ()) != 0) {
+      logger.debug("Image Z different: {} != {}", arg0.getZ(), arg1.getZ());
       return integerComparator.compare(arg0.getZ(), arg1.getZ());
     }
 
diff --git a/model/src/main/java/lcsb/mapviewer/model/map/layout/graphics/LayerText.java b/model/src/main/java/lcsb/mapviewer/model/map/layout/graphics/LayerText.java
index e6e6be49e6..3cb94de592 100644
--- a/model/src/main/java/lcsb/mapviewer/model/map/layout/graphics/LayerText.java
+++ b/model/src/main/java/lcsb/mapviewer/model/map/layout/graphics/LayerText.java
@@ -43,7 +43,7 @@ public class LayerText implements MinervaEntity, Drawable {
   /**
    * Default font size of the text.
    */
-  private static final double DEFAULT_LAYER_FONT_SIZE = 11.0;
+  public static final double DEFAULT_LAYER_FONT_SIZE = 11.0;
 
   /**
    * Default class logger.
diff --git a/model/src/main/java/lcsb/mapviewer/model/map/model/Model.java b/model/src/main/java/lcsb/mapviewer/model/map/model/Model.java
index b9c683193f..d3525bfdb0 100644
--- a/model/src/main/java/lcsb/mapviewer/model/map/model/Model.java
+++ b/model/src/main/java/lcsb/mapviewer/model/map/model/Model.java
@@ -507,4 +507,6 @@ public interface Model {
   Set<Drawable> getDrawables(boolean onlyVisible);
 
   Collection<Element> getSortedElements();
+
+  void removeLayer(Layer pathwayLayer);
 }
diff --git a/model/src/main/java/lcsb/mapviewer/model/map/model/ModelData.java b/model/src/main/java/lcsb/mapviewer/model/map/model/ModelData.java
index 9258dcedb5..996edbb725 100644
--- a/model/src/main/java/lcsb/mapviewer/model/map/model/ModelData.java
+++ b/model/src/main/java/lcsb/mapviewer/model/map/model/ModelData.java
@@ -793,4 +793,8 @@ public class ModelData implements MinervaEntity {
   public EntityType getEntityType() {
     throw new NotImplementedException();
   }
+
+  public void removeLayer(final Layer pathwayLayer) {
+    this.layers.remove(pathwayLayer);
+  }
 }
\ No newline at end of file
diff --git a/model/src/main/java/lcsb/mapviewer/model/map/model/ModelFullIndexed.java b/model/src/main/java/lcsb/mapviewer/model/map/model/ModelFullIndexed.java
index ffa13ff083..3a672046de 100644
--- a/model/src/main/java/lcsb/mapviewer/model/map/model/ModelFullIndexed.java
+++ b/model/src/main/java/lcsb/mapviewer/model/map/model/ModelFullIndexed.java
@@ -739,4 +739,9 @@ public class ModelFullIndexed implements Model {
     result.sort(new ElementByIdComparator());
     return result;
   }
+
+  @Override
+  public void removeLayer(final Layer pathwayLayer) {
+    modelData.removeLayer(pathwayLayer);
+  }
 }
-- 
GitLab