/* VARNA is a tool for the automated drawing, visualization and annotation of the secondary structure of RNA, designed as a companion software for web servers and databases. Copyright (C) 2008 Kevin Darty, Alain Denise and Yann Ponty. electronic mail : Yann.Ponty@lri.fr paper mail : LRI, bat 490 Universit� Paris-Sud 91405 Orsay Cedex France This file is part of VARNA version 3.1. VARNA version 3.1 is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. VARNA version 3.1 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with VARNA version 3.1. If not, see http://www.gnu.org/licenses. */ package fr.orsay.lri.varna.models.annotations; import java.awt.Color; import java.awt.Font; import java.awt.geom.Point2D; import java.io.Serializable; import java.text.DecimalFormat; import java.text.NumberFormat; import java.util.ArrayList; import java.util.Collections; import fr.orsay.lri.varna.models.rna.ModeleBase; import fr.orsay.lri.varna.models.rna.VARNAPoint; /** * The annotated text model * * @author Darty@lri.fr * */ public class TextAnnotation implements Serializable { /** * */ private static final long serialVersionUID = 465236085501860747L; /** * if the annoted text is located by a static position */ public final static int POSITION = 0; /** * if the annoted text is fixed to a base; */ public final static int BASE = 1; /** * if the annoted text is fixed to a helix; */ public final static int HELIX = 2; /** * if the annoted text is fixed to a loop; */ public final static int LOOP = 3; /** * default text color */ public static final Color DEFAULTCOLOR = Color.black; /** * default text font */ public static final Font DEFAULTFONT = new Font("Arial", Font.PLAIN, 12); private String _texte; private Font _font; private Object _ancrage; private int _typeAncrage; private Color _color; private double _angle; /** * creates an annoted text on a VARNAPanel with the specified text * * @param texte Textual content of the annotation */ public TextAnnotation(String texte) { _texte = texte; _color = DEFAULTCOLOR; _font = DEFAULTFONT; _angle = 0; } /** * /** creates an annoted text on a VARNAPanel with the specified text and * is static position * * @param texte * @param x * @param y */ public TextAnnotation(String texte, double x, double y) { this(texte); _ancrage = new VARNAPoint(x, y); _typeAncrage = POSITION; } /** * creates an annoted text on a VARNAPanel with the specified text fixed to * a base * * @param texte * @param mb */ public TextAnnotation(String texte, ModeleBase mb) { this(texte); _ancrage = mb; _typeAncrage = BASE; } /** * creates an annoted text on a VARNAPanel with the specified text fixed to * a helix (if type is HELIX) or to a loop (if type is LOOP) * * @param texte * @param listeBase * @param type * @throws Exception */ public TextAnnotation(String texte, ArrayList<ModeleBase> listeBase, int type) throws Exception { this(texte); _ancrage = listeBase; if (type == HELIX) _typeAncrage = HELIX; else if (type == LOOP) _typeAncrage = LOOP; else throw new Exception("Bad argument"); } /** * creates an annoted text from another one * * @param textAnnotation */ public TextAnnotation(TextAnnotation textAnnotation) { _ancrage = textAnnotation.getAncrage(); _font = textAnnotation.getFont(); _texte = textAnnotation.getTexte(); _typeAncrage = textAnnotation.getType(); } /** * * @return the text */ public String getTexte() { return _texte; } public void setTexte(String _texte) { this._texte = _texte; } /** * * @return the font */ public Font getFont() { return _font; } public void setFont(Font _font) { this._font = _font; } public Object getAncrage() { return _ancrage; } public void setAncrage(ModeleBase mb) { _ancrage = mb; _typeAncrage = BASE; } public void setAncrage(double x, double y) { _ancrage = new VARNAPoint(x, y); _typeAncrage = POSITION; } public void setAncrage(ArrayList<ModeleBase> list, int type) throws Exception { _ancrage = list; if (type == HELIX) _typeAncrage = HELIX; else if (type == LOOP) _typeAncrage = LOOP; else throw new Exception("Bad argument"); } public int getType() { return _typeAncrage; } public Color getColor() { return _color; } public void setColor(Color color) { this._color = color; } public String getHelixDescription() { ArrayList<ModeleBase> listeBase = ((ArrayList<ModeleBase>)_ancrage); int minA = Integer.MAX_VALUE,maxA = Integer.MIN_VALUE; int minB = Integer.MAX_VALUE,maxB = Integer.MIN_VALUE; for(ModeleBase mb : listeBase) { int i = mb.getBaseNumber(); if (mb.getElementStructure()>i) { minA = Math.min(minA, i); maxA = Math.max(maxA, i); } else { minB = Math.min(minB, i); maxB = Math.max(maxB, i); } } return "["+minA+","+maxA+"] ["+minB+","+maxB+"]"; } public String getLoopDescription() { ArrayList<ModeleBase> listeBase = ((ArrayList<ModeleBase>)_ancrage); int min = Integer.MAX_VALUE,max = Integer.MIN_VALUE; for(ModeleBase mb : listeBase) { int i = mb.getBaseNumber(); min = Math.min(min, i); max = Math.max(max, i); } return "["+min+","+max+"]"; } public String toString() { String tmp = "["+_texte+"] "; switch (_typeAncrage) { case POSITION: NumberFormat formatter = new DecimalFormat(".00"); return tmp+" at ("+formatter.format(getCenterPosition().x)+","+formatter.format(getCenterPosition().y)+")"; case BASE: return tmp+" on base "+((ModeleBase) _ancrage).getBaseNumber(); case HELIX: return tmp+" on helix "+getHelixDescription(); case LOOP: return tmp+" on loop "+getLoopDescription(); default: return tmp; } } /** * * @return the text position center */ public Point2D.Double getCenterPosition() { switch (_typeAncrage) { case POSITION: return ((VARNAPoint) _ancrage).toPoint2D(); case BASE: return ((ModeleBase) _ancrage).getCoords(); case HELIX: return calculLoopHelix(); case LOOP: return calculLoop(); default: return new Point2D.Double(0., 0.); } } private Point2D.Double calculLoop() { ArrayList<ModeleBase> liste = extractedArrayListModeleBaseFromAncrage(); double totalX = 0., totalY = 0.; for (ModeleBase base : liste) { totalX += base.getCoords().x; totalY += base.getCoords().y; } return new Point2D.Double(totalX / liste.size(), totalY / liste.size()); } private Point2D.Double calculLoopHelix() { ArrayList<ModeleBase> liste = extractedArrayListModeleBaseFromAncrage(); Collections.sort(liste); double totalX = 0., totalY = 0.; double num=0.0; for (int i=0;i<liste.size(); i++) { ModeleBase base =liste.get(i); if ((i>0 && (i<liste.size()-1)) || (liste.size()<=2)) { totalX += base.getCoords().x; totalY += base.getCoords().y; num += 1; } } return new Point2D.Double(totalX / num, totalY / num); } private ArrayList<ModeleBase> extractedArrayListModeleBaseFromAncrage() { return (ArrayList<ModeleBase>) _ancrage; } /** * clone a TextAnnotation */ public TextAnnotation clone() { TextAnnotation textAnnot = null; try { switch (_typeAncrage) { case BASE: textAnnot = new TextAnnotation(_texte, (ModeleBase) _ancrage); break; case POSITION: textAnnot = new TextAnnotation(_texte, ((VARNAPoint) _ancrage).x, ((VARNAPoint) _ancrage).y); break; case LOOP: textAnnot = new TextAnnotation(_texte, extractedArrayListModeleBaseFromAncrage(), LOOP); break; case HELIX: textAnnot = new TextAnnotation(_texte, extractedArrayListModeleBaseFromAncrage(), HELIX); break; default: break; } } catch (Exception e) { e.printStackTrace(); } textAnnot.setFont(_font); textAnnot.setColor(_color); return textAnnot; } /** * copy a textAnnotation * * @param textAnnotation */ public void copy(TextAnnotation textAnnotation) { _ancrage = textAnnotation.getAncrage(); _font = textAnnotation.getFont(); _texte = textAnnotation.getTexte(); _typeAncrage = textAnnotation.getType(); _color = textAnnotation.getColor(); _angle = textAnnotation.getAngleInDegres(); } /** * * @return the angle in degrees */ public double getAngleInDegres() { // if (_typeAncrage == TextAnnotation.HELIX) // _angle = calculAngleDegres(); return _angle; } /** * * @return the angle in radians */ public double getAngleInRadians() { return (getAngleInDegres() * Math.PI) / 180.; } public void setAngleInDegres(double _angle) { this._angle = _angle; } public void setAngleInRadians(double _angle) { this._angle = _angle * 180 / Math.PI; } }