Commit 6ce765c9 authored by Piotr Gawron's avatar Piotr Gawron
Browse files

Merge branch '806-set-border-color-for-textareas' into 'master'

Resolve "Set border color for TextAreas"

Closes #999 and #806

See merge request minerva/core!981
parents 946dbe37 1d77f3dd
......@@ -3,6 +3,8 @@ minerva (15.0.0~alpha.0) stable; urgency=medium
the content is compressed and returned as a zip file (#348)
* Small improvement: confirmation dialog when removing "general view"
overlays contain proper warning (#809)
* Small improvement: CellDesigner text area object can have "BorderColor"
property defined (#806)
* Bug fix: position of structural state is preserved on upload CellDesigner
file (#671)
......
package lcsb.mapviewer.converter.model.celldesigner;
import java.awt.*;
import java.awt.Color;
import java.awt.geom.Point2D;
import java.util.*;
import java.util.List;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
......@@ -502,6 +501,11 @@ public class LayerXmlParser {
result.setBackgroundColor(backgroundColor);
notes = removeBackgroundColor(notes);
}
Color borderColor = extractBorderColor(notes);
if (borderColor != null) {
result.setBorderColor(borderColor);
notes = removeBorderColor(notes);
}
result.setNotes(notes);
} else if (node.getNodeName().equalsIgnoreCase("celldesigner:paint")) {
result.setColor(commonParser.getColor(node));
......@@ -523,10 +527,18 @@ public class LayerXmlParser {
}
String removeBackgroundColor(String notes) {
return removeColor(notes, "BackgroundColor");
}
String removeBorderColor(String notes) {
return removeColor(notes, "BorderColor");
}
private String removeColor(String notes, String string) {
String lines[] = notes.split("[\n\r]+");
StringBuilder result = new StringBuilder("");
for (String line : lines) {
if (!line.startsWith("BackgroundColor=") && !line.startsWith("BackgroundColor:")) {
if (!line.startsWith(string + "=") && !line.startsWith(string + ":")) {
result.append(line + "\n");
}
}
......@@ -534,10 +546,18 @@ public class LayerXmlParser {
}
Color extractBackgroundColor(String notes) {
return extractColor(notes, "BackgroundColor");
}
Color extractBorderColor(String notes) {
return extractColor(notes, "BorderColor");
}
private Color extractColor(String notes, String string) {
String lines[] = notes.split("[\n\r]+");
for (String line : lines) {
if (line.startsWith("BackgroundColor=") ||line.startsWith("BackgroundColor:")) {
String colorString = line.replace("BackgroundColor=", "").replace("BackgroundColor:", "");
if (line.startsWith(string + "=") || line.startsWith(string + ":")) {
String colorString = line.replace(string + "=", "").replace(string + ":", "");
return new ColorParser().parse(colorString);
}
}
......@@ -562,6 +582,9 @@ public class LayerXmlParser {
if (!layer.getBackgroundColor().equals(Color.LIGHT_GRAY)) {
notes += "\nBackgroundColor:" + new ColorParser().colorToHtml(layer.getBackgroundColor());
}
if (!layer.getBorderColor().equals(Color.LIGHT_GRAY)) {
notes += "\nBorderColor:" + new ColorParser().colorToHtml(layer.getBorderColor());
}
result.append(notes);
result.append("\n</celldesigner:layerNotes>");
result.append("<celldesigner:paint color=\"" + XmlParser.colorToString(layer.getColor()) + "\"/>");
......
package lcsb.mapviewer.converter.model.celldesigner.alias;
import java.awt.Color;
import java.util.Objects;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.w3c.dom.Node;
......@@ -96,7 +99,13 @@ public class CompartmentAliasXmlParser extends AbstractAliasXmlParser<Compartmen
result.setLineOuterWidth(XmlParser.getNodeAttr("outerWidth", node));
result.setLineInnerWidth(XmlParser.getNodeAttr("innerWidth", node));
} else if (node.getNodeName().equalsIgnoreCase("celldesigner:paint")) {
result.setColor(getCommonParser().getColor(node));
Color color = getCommonParser().getColor(node);
result.setFillColor(color);
if (Objects.equals(color, Color.WHITE)) {
result.setBorderColor(Color.BLACK);
} else {
result.setBorderColor(color);
}
} else if (node.getNodeName().equalsIgnoreCase("celldesigner:info")) {
// not handled
continue;
......@@ -104,12 +113,14 @@ public class CompartmentAliasXmlParser extends AbstractAliasXmlParser<Compartmen
if (result instanceof BottomSquareCompartment) {
result.setY(XmlParser.getNodeAttr("y", node));
} else if (result instanceof LeftSquareCompartment) {
result.setX(XmlParser.getNodeAttr("x", node));
result.setWidth(XmlParser.getNodeAttr("x", node));
result.setX(0.0);
} else if (result instanceof RightSquareCompartment) {
result.setX(XmlParser.getNodeAttr("x", node));
result.setWidth(result.getWidth() - result.getX());
} else if (result instanceof TopSquareCompartment) {
result.setY(XmlParser.getNodeAttr("y", node));
result.setHeight(XmlParser.getNodeAttr("y", node));
result.setY(0.0);
} else {
throw new InvalidXmlSchemaException(
"Don't know what to do with celldesigner:point for class: " + result.getClass());
......@@ -176,7 +187,7 @@ public class CompartmentAliasXmlParser extends AbstractAliasXmlParser<Compartmen
sb.append("innerWidth=\"" + compartment.getInnerWidth() + "\"/>\n");
sb.append("<celldesigner:paint ");
sb.append("color=\"" + XmlParser.colorToString(compartment.getColor()) + "\" scheme=\"Color\"/>\n");
sb.append("color=\"" + XmlParser.colorToString(compartment.getFillColor()) + "\" scheme=\"Color\"/>\n");
sb.append("</celldesigner:compartmentAlias>\n");
......
......@@ -142,7 +142,7 @@ public class ComplexAliasXmlParser extends AbstractAliasXmlParser<Complex> {
result.setWidth(view.getBoxSize().width);
result.setHeight(view.getBoxSize().height);
result.setLineWidth(view.getSingleLine().getWidth());
result.setColor(view.getColor());
result.setFillColor(view.getColor());
} else if (!state.equalsIgnoreCase("complexnoborder")) {
throw new InvalidXmlSchemaException("No view (" + state + ") in ComplexAlias for " + result.getElementId());
}
......@@ -228,13 +228,13 @@ public class ComplexAliasXmlParser extends AbstractAliasXmlParser<Complex> {
sb.append("<celldesigner:innerPosition x=\"" + complex.getX() + "\" y=\"" + complex.getY() + "\"/>");
sb.append("<celldesigner:boxSize width=\"" + complex.getWidth() + "\" height=\"" + complex.getHeight() + "\"/>");
sb.append("<celldesigner:singleLine width=\"" + complex.getLineWidth() + "\"/>");
sb.append("<celldesigner:paint color=\"" + XmlParser.colorToString(complex.getColor()) + "\" scheme=\"Color\"/>");
sb.append("<celldesigner:paint color=\"" + XmlParser.colorToString(complex.getFillColor()) + "\" scheme=\"Color\"/>");
sb.append("</celldesigner:usualView>\n");
sb.append("<celldesigner:briefView>");
sb.append("<celldesigner:innerPosition x=\"" + complex.getX() + "\" y=\"" + complex.getY() + "\"/>");
sb.append("<celldesigner:boxSize width=\"" + complex.getWidth() + "\" height=\"" + complex.getHeight() + "\"/>");
sb.append("<celldesigner:singleLine width=\"" + complex.getWidth() + "\"/>");
sb.append("<celldesigner:paint color=\"" + XmlParser.colorToString(complex.getColor()) + "\" scheme=\"Color\"/>");
sb.append("<celldesigner:paint color=\"" + XmlParser.colorToString(complex.getFillColor()) + "\" scheme=\"Color\"/>");
sb.append("</celldesigner:briefView>\n");
sb.append(createStructuralStateTag(complex));
......
......@@ -121,7 +121,7 @@ public class SpeciesAliasXmlParser extends AbstractAliasXmlParser<Species> {
result.setWidth(view.getBoxSize().width);
result.setHeight(view.getBoxSize().height);
result.setLineWidth(view.getSingleLine().getWidth());
result.setColor(view.getColor());
result.setFillColor(view.getColor());
} else {
throw new InvalidXmlSchemaException(errorPrefix + "No view in Alias");
}
......@@ -220,13 +220,13 @@ public class SpeciesAliasXmlParser extends AbstractAliasXmlParser<Species> {
sb.append("<celldesigner:innerPosition x=\"" + species.getX() + "\" y=\"" + species.getY() + "\"/>");
sb.append("<celldesigner:boxSize width=\"" + species.getWidth() + "\" height=\"" + species.getHeight() + "\"/>");
sb.append("<celldesigner:singleLine width=\"" + species.getLineWidth() + "\"/>");
sb.append("<celldesigner:paint color=\"" + XmlParser.colorToString(species.getColor()) + "\" scheme=\"Color\"/>");
sb.append("<celldesigner:paint color=\"" + XmlParser.colorToString(species.getFillColor()) + "\" scheme=\"Color\"/>");
sb.append("</celldesigner:usualView>\n");
sb.append("<celldesigner:briefView>");
sb.append("<celldesigner:innerPosition x=\"" + species.getX() + "\" y=\"" + species.getY() + "\"/>");
sb.append("<celldesigner:boxSize width=\"" + species.getWidth() + "\" height=\"" + species.getHeight() + "\"/>");
sb.append("<celldesigner:singleLine width=\"" + species.getLineWidth() + "\"/>");
sb.append("<celldesigner:paint color=\"" + XmlParser.colorToString(species.getColor()) + "\" scheme=\"Color\"/>");
sb.append("<celldesigner:paint color=\"" + XmlParser.colorToString(species.getFillColor()) + "\" scheme=\"Color\"/>");
sb.append("</celldesigner:briefView>\n");
if (species.getStateLabel() != null || species.getStatePrefix() != null) {
sb.append("<celldesigner:info state=\"open\" prefix=\"" + species.getStatePrefix() + "\" label=\""
......
......@@ -326,8 +326,10 @@ public class LayerXmlParserTest extends CellDesignerTestFunctions {
public void testLayerTextToXmlWithCustomDefaultBackgroundColor() throws Exception {
LayerText text = new LayerText();
text.setBackgroundColor(Color.BLUE);
text.setBorderColor(Color.YELLOW);
String xml = parser.layerTextToXml(text);
assertTrue(xml.contains("BackgroundColor"));
assertTrue(xml.contains("BorderColor"));
}
}
......@@ -127,7 +127,7 @@ public class CompartmentAliasXmlParserTest extends CellDesignerTestFunctions {
assertEquals(522.0, alias.getWidth(), 1e-6);
assertEquals(392.5, alias.getNamePoint().getX(), 1e-6);
assertEquals(196.5, alias.getNamePoint().getY(), 1e-6);
assertEquals(0xffcccc00, alias.getColor().getRGB());
assertEquals(0xffcccc00, alias.getFillColor().getRGB());
}
@Test
......
package lcsb.mapviewer.converter.model.celldesigner.compartment;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.junit.*;
import lcsb.mapviewer.common.Configuration;
import lcsb.mapviewer.converter.model.celldesigner.CellDesignerTestFunctions;
import lcsb.mapviewer.model.map.compartment.Compartment;
import lcsb.mapviewer.model.map.model.Model;
public class CompartmentParserTests extends CellDesignerTestFunctions {
......@@ -23,6 +26,11 @@ public class CompartmentParserTests extends CellDesignerTestFunctions {
@Test
public void testParseCompartmensBottom() throws Exception {
Model model = getModelForFile("testFiles/compartment/bottom_compartment.xml");
Compartment c = model.getElementByElementId("ca4");
assertTrue(c.getY() > 0);
assertTrue(c.getWidth() > 0);
assertTrue(c.getHeight() > 0);
assertEquals(0, c.getX(), Configuration.EPSILON);
assertEquals(1, model.getElements().size());
}
......@@ -31,19 +39,33 @@ public class CompartmentParserTests extends CellDesignerTestFunctions {
public void testParseCompartmensTop() throws Exception {
Model model = getModelForFile("testFiles/compartment/top_compartment.xml");
Compartment c = model.getElementByElementId("ca3");
assertEquals(0, c.getX(), Configuration.EPSILON);
assertEquals(0, c.getY(), Configuration.EPSILON);
assertTrue(c.getWidth() > 0);
assertTrue(c.getHeight() < model.getHeight());
assertEquals(1, model.getElements().size());
}
@Test
public void testParseCompartmensRight() throws Exception {
Model model = getModelForFile("testFiles/compartment/right_compartment.xml");
Compartment c = model.getElementByElementId("ca2");
assertTrue(c.getX() > 0);
assertTrue(c.getWidth() > 0);
assertTrue(c.getHeight() > 0);
assertEquals(0, c.getY(), Configuration.EPSILON);
assertEquals(1, model.getElements().size());
}
@Test
public void testParseCompartmensLeft() throws Exception {
Model model = getModelForFile("testFiles/compartment/left_compartment.xml");
Compartment c = model.getElementByElementId("ca1");
assertEquals(0, c.getX(), Configuration.EPSILON);
assertEquals(0, c.getY(), Configuration.EPSILON);
assertTrue(c.getWidth() < model.getWidth());
assertTrue(c.getHeight() > 0);
assertEquals(1, model.getElements().size());
}
......
......@@ -1513,7 +1513,8 @@ public class SbgnmlXmlParser {
compartment.setX(new Double(glyph.getBbox().getX()));
compartment.setY(new Double(glyph.getBbox().getY()));
compartment.setThickness(1.0);
compartment.setColor(COMPARTMENT_COLOR);
compartment.setFillColor(COMPARTMENT_COLOR);
compartment.setBorderColor(COMPARTMENT_COLOR);
if (glyph.getLabel() != null && glyph.getLabel().getBbox() != null) {
compartment.setNamePoint(glyph.getLabel().getBbox().getX(), glyph.getLabel().getBbox().getY());
......
......@@ -9,7 +9,7 @@ package lcsb.mapviewer.converter.graphics;
public class ConverterParams {
/**
* At which level the object is visualized. It helps to deterimine font size.
* At which level the object is visualized. It helps to determine font size.
* However it's possible that this value is not required.
*/
private int level = 0;
......
package lcsb.mapviewer.converter.graphics.bioEntity.element.compartment;
import java.awt.*;
import java.awt.Shape;
import java.awt.geom.*;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import lcsb.mapviewer.commands.ColorExtractor;
import lcsb.mapviewer.converter.graphics.ConverterParams;
import lcsb.mapviewer.converter.graphics.DrawingException;
import lcsb.mapviewer.model.graphics.LineType;
import lcsb.mapviewer.model.map.compartment.BottomSquareCompartment;
import lcsb.mapviewer.model.map.layout.ColorSchema;
import lcsb.mapviewer.model.map.species.Species;
......@@ -40,55 +37,19 @@ public class BottomSquareCompartmentConverter extends CompartmentConverter<Botto
}
@Override
protected void drawImpl(final BottomSquareCompartment compartment, final Graphics2D graphics,
final ConverterParams params) throws DrawingException {
// keep the old values of colors and line
Color oldColor = graphics.getColor();
Stroke oldStroke = graphics.getStroke();
protected Shape getOuterShape(BottomSquareCompartment compartment) {
return new Line2D.Double(0, compartment.getY(), compartment.getWidth(), compartment.getY());
}
// create shape of the compartment
Shape s1 = new Line2D.Double(0, compartment.getY(), compartment.getWidth(), compartment.getY());
Shape s3 = new Line2D.Double(0, compartment.getY() + compartment.getThickness(), compartment.getWidth(),
@Override
protected Shape getInnerShape(BottomSquareCompartment compartment) {
return new Line2D.Double(0, compartment.getY() + compartment.getThickness(), compartment.getWidth(),
compartment.getY() + compartment.getThickness());
Area a1 = new Area(
new Rectangle2D.Double(0.0, compartment.getY(), compartment.getWidth(), compartment.getHeight()));
Color c1 = compartment.getColor();
Color c2 = new Color(c1.getRed(), c1.getGreen(), c1.getBlue(), HIGH_ALPHA_LEVEL);
if (c1.equals(Color.WHITE)) {
c1 = Color.BLACK;
}
// fill the background
boolean fill = !isTransparent(compartment, params);
if (fill) {
graphics.setColor(c1);
} else {
Color bgAlphaColor = new Color(c1.getRed(), c1.getGreen(), c1.getBlue(), getAlphaLevel());
graphics.setColor(bgAlphaColor);
}
graphics.fill(s1);
// create borders
graphics.setColor(c1);
graphics.setStroke(LineType.SOLID_BOLD.getStroke());
graphics.draw(s1);
graphics.setStroke(LineType.SOLID.getStroke());
graphics.draw(s3);
graphics.setColor(c2);
if (fill) {
graphics.fill(a1);
}
// restore color and line type
graphics.setColor(oldColor);
graphics.setStroke(oldStroke);
}
// draw description
if (fill) {
Point2D tmpPoint = compartment.getNamePoint();
compartment.setNamePoint(compartment.getCenter());
drawText(compartment, graphics, params);
compartment.setNamePoint(tmpPoint);
}
@Override
protected Shape getBorderShape(BottomSquareCompartment compartment) {
return new Area(new Rectangle2D.Double(0.0, compartment.getY(), compartment.getWidth(), compartment.getHeight()));
}
}
package lcsb.mapviewer.converter.graphics.bioEntity.element.compartment;
import java.awt.*;
import java.awt.geom.Rectangle2D;
import java.awt.geom.*;
import java.util.List;
import org.apache.logging.log4j.LogManager;
......@@ -9,6 +9,7 @@ import org.apache.logging.log4j.Logger;
import lcsb.mapviewer.commands.ColorExtractor;
import lcsb.mapviewer.common.Configuration;
import lcsb.mapviewer.common.exception.NotImplementedException;
import lcsb.mapviewer.common.geometry.LineTransformation;
import lcsb.mapviewer.converter.graphics.ConverterParams;
import lcsb.mapviewer.converter.graphics.DrawingException;
......@@ -16,6 +17,7 @@ import lcsb.mapviewer.converter.graphics.bioEntity.element.ElementConverter;
import lcsb.mapviewer.converter.graphics.geometry.FontFinder;
import lcsb.mapviewer.converter.graphics.geometry.RectangleTooSmallException;
import lcsb.mapviewer.converter.graphics.placefinder.PlaceFinder;
import lcsb.mapviewer.model.graphics.LineType;
import lcsb.mapviewer.model.map.compartment.Compartment;
import lcsb.mapviewer.model.map.layout.ColorSchema;
import lcsb.mapviewer.modelutils.map.ElementUtils;
......@@ -40,10 +42,7 @@ public abstract class CompartmentConverter<T extends Compartment> extends Elemen
* Default alpha level for semi-transparent borders.
*/
protected static final int HIGH_ALPHA_LEVEL = 127;
/**
* Default font size.
*/
private static final int DEFAULT_FONT_SIZE = 10;
/**
* Default class logger.
*/
......@@ -58,7 +57,7 @@ public abstract class CompartmentConverter<T extends Compartment> extends Elemen
*/
private LineTransformation lineTransformation = new LineTransformation();
/**
* Class used for finding place to draw desciption of the compartment.
* Class used for finding place to draw description of the compartment.
*/
private PlaceFinder placeFinder;
......@@ -114,6 +113,68 @@ public abstract class CompartmentConverter<T extends Compartment> extends Elemen
this.lineTransformation = lineTransformation;
}
@Override
protected void drawImpl(T compartment, Graphics2D graphics, ConverterParams params) throws DrawingException {
// keep the old values of color and line type
Color oldColor = graphics.getColor();
Stroke oldStroke = graphics.getStroke();
Shape s1 = getOuterShape(compartment);
Shape s3 = getInnerShape(compartment);
Shape a1 = getBorderShape(compartment);
Color borderColor = compartment.getBorderColor();
Color fillColor = compartment.getFillColor();
// fill the background
boolean fill = !isTransparent(compartment, params);
if (fill) {
graphics.setColor(fillColor);
} else {
Color bgAlphaColor = new Color(fillColor.getRed(), fillColor.getGreen(), fillColor.getBlue(), getAlphaLevel());
graphics.setColor(bgAlphaColor);
}
graphics.fill(s1);
// create borders
graphics.setColor(borderColor);
graphics.setStroke(LineType.SOLID_BOLD.getStroke());
graphics.draw(s1);
graphics.setStroke(LineType.SOLID.getStroke());
graphics.draw(s3);
fillColor = new Color(fillColor.getRed(), fillColor.getGreen(), fillColor.getBlue(), HIGH_ALPHA_LEVEL);
graphics.setColor(fillColor);
graphics.fill(a1);
// restore color and line type
graphics.setColor(oldColor);
graphics.setStroke(oldStroke);
// draw description
if (fill) {
Point2D tmpPoint = compartment.getNamePoint();
compartment.setNamePoint(compartment.getCenter());
drawText(compartment, graphics, params);
compartment.setNamePoint(tmpPoint);
}
}
protected Shape getOuterShape(T compartment) {
throw new NotImplementedException();
}
protected Shape getInnerShape(T compartment) {
throw new NotImplementedException();
}
protected Shape getBorderShape(T compartment) {
Area result = new Area(getOuterShape(compartment));
result.subtract(new Area(getInnerShape(compartment)));
return result;
}
@Override
public void draw(T alias, Graphics2D graphics, ConverterParams params,
List<ColorSchema> visualizedLayoutsColorSchemas) throws DrawingException {
......@@ -167,18 +228,19 @@ public abstract class CompartmentConverter<T extends Compartment> extends Elemen
compartment.getHeight() - (compartment.getNamePoint().getY() - compartment.getY()));
}
double fontSize = DEFAULT_FONT_SIZE * params.getScale();
if (compartment.getFontSize() != null) {
fontSize = compartment.getFontSize() * params.getScale();
}
double fontSize = compartment.getFontSize() * params.getScale();
String fontName = Font.SANS_SERIF;
Color tmpColor = graphics.getColor();
try {
graphics.setColor(compartment.getFontColor());
fontSize = FontFinder.findMaxFontSize((int) Math.round(fontSize), fontName, graphics, border,
compartment.getName());
FontFinder.drawText((int) fontSize, fontName, graphics, border, compartment.getName(), textCentered);
} catch (RectangleTooSmallException e) {
// if it's too small then don't draw
return;
} finally {
graphics.setColor(tmpColor);
}
}
......
package lcsb.mapviewer.converter.graphics.bioEntity.element.compartment;
import java.awt.*;
import java.awt.Shape;
import java.awt.geom.*;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import lcsb.mapviewer.commands.ColorExtractor;
import lcsb.mapviewer.converter.graphics.ConverterParams;
import lcsb.mapviewer.converter.graphics.DrawingException;
import lcsb.mapviewer.model.graphics.LineType;
import lcsb.mapviewer.model.map.compartment.LeftSquareCompartment;
import lcsb.mapviewer.model.map.layout.ColorSchema;
......@@ -40,56 +37,20 @@ public class LeftSquareCompartmentConverter extends CompartmentConverter<LeftSqu
}
@Override
protected void drawImpl(final LeftSquareCompartment compartment, final Graphics2D graphics,
final ConverterParams params) throws DrawingException {
// keep the old values of color and line type
Color oldColor = graphics.getColor();
Stroke oldStroke = graphics.getStroke();