X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=srcjar%2Ffr%2Forsay%2Flri%2Fvarna%2FVARNAPanel.java;h=5be74db3f618920afe1ea3f133f8669020a2dbea;hb=66ae8046375bbef690753727308a48f6bc71b162;hp=e60ceb2ccd2737de83393f0a9ab6311ee9aa4904;hpb=9577372b31a3c39a0690d3060503a76a2364a1d9;p=jalview.git diff --git a/srcjar/fr/orsay/lri/varna/VARNAPanel.java b/srcjar/fr/orsay/lri/varna/VARNAPanel.java index e60ceb2..5be74db 100644 --- a/srcjar/fr/orsay/lri/varna/VARNAPanel.java +++ b/srcjar/fr/orsay/lri/varna/VARNAPanel.java @@ -735,10 +735,14 @@ import fr.orsay.lri.varna.views.VueUI; /** * - * BH j2s SwingJS Added PropertyChangeListener for returns from VueUI. + * BH (early) j2s SwingJS Added PropertyChangeListener for returns from VueUI. + * + * BH 2019.05.15 flashes white background solution: replaced during-paint + * setBackground() with g.setColor();g.fill(); + * + * BH 2019.05.15 initialization shows popup menu raw creation objects solution: + * moved menu creation out of paintComponent() * - * - * * * The RNA 2D Panel is a lightweight component that allows for an automatic * basic drawing of an RNA secondary structures. The drawing algorithms do not @@ -755,3774 +759,4364 @@ import fr.orsay.lri.varna.views.VueUI; * */ -public class VARNAPanel extends JPanel implements PropertyChangeListener { - - /** - * SwingJS uses a PropertyChangeEvent to signal that a pseudo-modal dialog has been closed. - * - * @param event - */ - @Override - public void propertyChange(PropertyChangeEvent event) { - Object val = event.getNewValue(); - switch (event.getPropertyName()) { - case "value": - _UI.onDialogReturn(val == null ? JOptionPane.CLOSED_OPTION : ((Integer) val).intValue()); - return; - case "SelectedFile": - case "SelectedColor": - case "inputValue": - _UI.onDialogReturn(val); - break; - } - } - - - - private static final long serialVersionUID = 8194421570308956001L; - - private RNA _RNA = new RNA(); - - private boolean _debug = false; - - private VARNAConfig _conf = new VARNAConfig(); - - private ArrayList _VARNAListeners = new ArrayList(); - private ArrayList _selectionListeners = new ArrayList(); - private ArrayList _RNAListeners = new ArrayList(); - private ArrayList _basesListeners = new ArrayList(); - - UndoManager _manager; - - // private boolean _foldMode = true; - - private Point2D.Double[] _realCoords = new Point2D.Double[0]; - private Point2D.Double[] _realCenters = new Point2D.Double[0]; - private double _scaleFactor = 1.0; - private Point2D.Double _offsetPanel = new Point2D.Double(); - private Point2D.Double _offsetRNA = new Point2D.Double(); - - private double _offX; - private double _offY; - - private ControleurBlinkingThread _blink; - private BaseList _selectedBases = new BaseList("selection"); - private ArrayList _backupSelection = new ArrayList(); - private Integer _nearestBase = null; - private Point2D.Double _lastSelectedCoord = new Point2D.Double(0.0, 0.0); - - private Point2D.Double _linkOrigin = null; - private Point2D.Double _linkDestination = null; - - private Rectangle _selectionRectangle = null; - - private boolean _highlightAnnotation = false; - - private int _titleHeight; - private Dimension _border = new Dimension(0, 0); - - private boolean _drawBBox = false; - private boolean _drawBorder = false; - - // private Point _positionRelativeSouris; - private Point _translation; - private boolean _horsCadre; - private boolean _premierAffichage; - - private ControleurInterpolator _interpolator; - /** - * If comparison mode is TRUE (ON), then the application will be used to - * display a super-structure resulting on an RNA secondary structure - * comparison. Else, the application is used by default. - */ - - private VueMenu _popup = new VueMenu(this); - - private VueUI _UI = new VueUI(this); - - private TextAnnotation _selectedAnnotation; - - /** - * Creates an RNA 2D panel with initially displays the empty structure. - * - * @throws ExceptionNonEqualLength - * - */ - public VARNAPanel() { - init(); - drawRNA(); - } - - /** - * Creates an RNA 2D panel, and creates and displays an RNA coupled with its - * secondary structure formatted as a well-balanced parenthesis with dots - * word (DBN format). - * - * @param seq - * The raw nucleotide sequence - * @param str - * The secondary structure in DBN format - * @throws ExceptionNonEqualLength - */ - - public VARNAPanel(String seq, String str) throws ExceptionNonEqualLength { - this(seq, str, RNA.DRAW_MODE_RADIATE); - } - - /** - * Creates a VARNAPanel instance, and creates and displays an RNA coupled - * with its secondary structure formatted as a well-balanced parenthesis - * with dots word (DBN format). Allows the user to choose the drawing - * algorithm to be used. - * - * @param seq - * The raw nucleotide sequence - * @param str - * The secondary structure in DBN format - * @param drawMode - * The drawing mode - * @throws ExceptionNonEqualLength - * @see RNA#DRAW_MODE_RADIATE - * @see RNA#DRAW_MODE_CIRCULAR - * @see RNA#DRAW_MODE_NAVIEW - */ - public VARNAPanel(String seq, String str, int drawMode) - throws ExceptionNonEqualLength { - this(seq, str, drawMode, ""); - } - - public VARNAPanel(Reader r) throws ExceptionNonEqualLength, - ExceptionFileFormatOrSyntax { - this(r, RNA.DRAW_MODE_RADIATE); - } - - public VARNAPanel(Reader r, int drawMode) throws ExceptionNonEqualLength, - ExceptionFileFormatOrSyntax { - this(r, drawMode, ""); - } - - public VARNAPanel(Reader r, int drawMode, String title) - throws ExceptionNonEqualLength, ExceptionFileFormatOrSyntax { - init(); - drawRNA(r, drawMode); - setTitle(title); - } - - public void setOriginLink(Point2D.Double p) { - _linkOrigin = (p); - } - - public void setDestinationLink(Point2D.Double p) { - _linkDestination = (p); - } - - public void removeLink() { - _linkOrigin = null; - _linkDestination = null; - } - - /** - * Creates a VARNAPanel instance, and displays an RNA. - * - * @param r - * The RNA to be displayed within this panel - */ - - public VARNAPanel(RNA r) { - showRNA(r); - init(); - } - - /** - * Creates a VARNAPanel instance, and creates and displays an RNA coupled - * with its secondary structure formatted as a well-balanced parenthesis - * with dots word (DBN format). Allows the user to choose the drawing - * algorithm to be used. Additionally, sets the panel's title. - * - * @param seq - * The raw nucleotide sequence - * @param str - * The secondary structure in DBN format - * @param drawMode - * The drawing mode - * @param title - * The panel title - * @throws ExceptionNonEqualLength - * @see RNA#DRAW_MODE_CIRCULAR - * @see RNA#DRAW_MODE_RADIATE - * @see RNA#DRAW_MODE_NAVIEW - */ - - public VARNAPanel(String seq, String str, int drawMode, String title) - throws ExceptionNonEqualLength { - drawRNA(seq, str, drawMode); - init(); - setTitle(title); - // VARNASecDraw._vp = this; - } - - public VARNAPanel(String seq1, String struct1, String seq2, String struct2, - int drawMode, String title) { - _conf._comparisonMode = true; - drawRNA(seq1, struct1, seq2, struct2, drawMode); - init(); - setTitle(title); - } - - private void init() { - setBackground(VARNAConfig.DEFAULT_BACKGROUND_COLOR); - _manager = new UndoManager(); - _manager.setLimit(10000); - _UI.addUndoableEditListener(_manager); - - _blink = new ControleurBlinkingThread(this, - ControleurBlinkingThread.DEFAULT_FREQUENCY, 0, 1.0, 0.0, 0.2); - _blink.start(); - - _premierAffichage = true; - _translation = new Point(0, 0); - - _horsCadre = false; - this.setFont(_conf._fontBasesGeneral); - - // ajout des controleurs au VARNAPanel - ControleurClicMovement controleurClicMovement = new ControleurClicMovement( - this); - this.addMouseListener(controleurClicMovement); - this.addMouseMotionListener(controleurClicMovement); - this.addMouseWheelListener(new ControleurMolette(this)); - - ControleurDraggedMolette ctrlDraggedMolette = new ControleurDraggedMolette( - this); - this.addMouseMotionListener(ctrlDraggedMolette); - this.addMouseListener(ctrlDraggedMolette); - - ControleurVARNAPanelKeys ctrlKey = new ControleurVARNAPanelKeys(this); - this.addKeyListener(ctrlKey); - this.addFocusListener(ctrlKey); - - _interpolator = new ControleurInterpolator(this); - /** - * - * BH SwingJS do not start this thread - * - * @j2sNative - */ - { - _interpolator.start(); - } - - } - - public void undo() { - if (_manager.canUndo()) - _manager.undo(); - } - - public void redo() { - if (_manager.canRedo()) - _manager.redo(); - } - - /** - * Sets the new style of the title font. - * - * @param newStyle - * An int that describes the new font style ("PLAIN","BOLD", - * "BOLDITALIC", or "ITALIC") - */ - public void setTitleFontStyle(int newStyle) { - _conf._titleFont = _conf._titleFont.deriveFont(newStyle); - updateTitleHeight(); - } - - /** - * Sets the new size of the title font. - * - * @param newSize - * The new size of the title font - */ - public void setTitleFontSize(float newSize) { - //System.err.println("Applying title size "+newSize); - _conf._titleFont = _conf._titleFont.deriveFont(newSize); - updateTitleHeight(); - } - - /** - * Sets the new font family to be used for the title. Available fonts are - * system-specific, yet it seems that "Arial", "Dialog", and "MonoSpaced" - * are almost always available. - * - * @param newFamily - * New font family used for the title - */ - public void setTitleFontFamily(String newFamily) { - _conf._titleFont = new Font(newFamily, _conf._titleFont.getStyle(), - _conf._titleFont.getSize()); - updateTitleHeight(); - } - - /** - * Sets the color to be used for the title. - * - * @param newColor - * A color used to draw the title - */ - public void setTitleFontColor(Color newColor) { - _conf._titleColor = newColor; - updateTitleHeight(); - } - - /** - * Sets the font size for displaying bases - * - * @param size - * Font size for base caption - */ - - public void setBaseFontSize(Float size) { - _conf._fontBasesGeneral = _conf._fontBasesGeneral.deriveFont(size); - } - - /** - * Sets the font size for displaying base numbers - * - * @param size - * Font size for base numbers - */ - - public void setNumbersFontSize(Float size) { - _conf._numbersFont = _conf._numbersFont.deriveFont(size); - } - - /** - * Sets the font style for displaying bases - * - * @param style - * An int that describes the new font style ("PLAIN","BOLD", - * "BOLDITALIC", or "ITALIC") - */ - - public void setBaseFontStyle(int style) { - _conf._fontBasesGeneral = _conf._fontBasesGeneral.deriveFont(style); - } - - private void updateTitleHeight() { - if (!getTitle().equals("")) { - _titleHeight = (int) (_conf._titleFont.getSize() * 1.5); - } else { - _titleHeight = 0; - } - if (Math.abs(this.getZoom() - 1) < .02) { - _translation.y = (int) (-getTitleHeight() / 2.0); - } - } - - /** - * Sets the panel's title, giving a short description of the RNA secondary - * structure. - * - * @param title - * The new title - */ - public void setTitle(String title) { - _RNA.setName(title); - updateTitleHeight(); - } - - /** - * Sets the distance between consecutive base numbers. Please notice that : - *
    - *
  • The first and last base are always numbered
  • - *
  • The numbering is based on the base numbers, not on the indices. So - * base numbers may appear more frequently than expected if bases are - * skipped
  • - *
  • The periodicity is measured starting from 0. This means that for a - * period of 10 and bases numbered from 1 to 52, the base numbers - * [1,10,20,30,40,50,52] will be drawn.
  • - *
- * - * @param n - * New numbering period - */ - public void setNumPeriod(int n) { - _conf._numPeriod = n; - } - - /** - * Returns the current numbering period. Please notice that : - *
    - *
  • The first and last base are always numbered
  • - *
  • The numbering is based on the base numbers, not on the indices. So - * base numbers may appear more frequently than expected if bases are - * skipped
  • - *
  • The periodicity is measured starting from 0. This means that for a - * period of 10 and bases numbered from 1 to 52, the base numbers - * [1,10,20,30,40,50,52] will be drawn.
  • - *
- * - * @return Current numbering period - */ - public int getNumPeriod() { - return _conf._numPeriod; - } - - private void setScaleFactor(double d) { - _scaleFactor = d; - } - - private double getScaleFactor() { - return _scaleFactor; - } - - private void setAutoFit(boolean fit) { - _conf._autoFit = fit; - repaint(); - } - - public void lockScrolling() { - setAutoFit(false); - setAutoCenter(false); - } - - public void unlockScrolling() { - setAutoFit(true); - setAutoCenter(true); - } - - private void drawStringOutline(VueVARNAGraphics g2D, String res, double x, - double y, double margin) { - Dimension d = g2D.getStringDimension(res); - x -= (double) d.width / 2.0; - y += (double) d.height / 2.0; - g2D.setColor(Color.GRAY); - g2D.setSelectionStroke(); - g2D.drawRect((x - margin), (y - d.height - margin), - (d.width + 2.0 * margin), (d.height + 2.0 * margin)); - } - - private void drawSymbol(VueVARNAGraphics g2D, double posx, double posy, - double normx, double normy, double radius, boolean isCIS, - ModeleBP.Edge e) { - Color bck = g2D.getColor(); - switch (e) { - case WC: - if (isCIS) { - g2D.setColor(bck); - g2D.fillCircle((posx - (radius) / 2.0), - (posy - (radius) / 2.0), radius); - g2D.drawCircle((posx - (radius) / 2.0), - (posy - (radius) / 2.0), radius); - } else { - g2D.setColor(Color.white); - g2D.fillCircle(posx - (radius) / 2.0, (posy - (radius) / 2.0), - (radius)); - g2D.setColor(bck); - g2D.drawCircle((posx - (radius) / 2.0), - (posy - (radius) / 2.0), (radius)); - } - break; - case HOOGSTEEN: { - GeneralPath p2 = new GeneralPath(); - radius /= 1.05; - p2.moveTo((float) (posx - radius * normx / 2.0 - radius * normy - / 2.0), (float) (posy - radius * normy / 2.0 + radius - * normx / 2.0)); - p2.lineTo((float) (posx + radius * normx / 2.0 - radius * normy - / 2.0), (float) (posy + radius * normy / 2.0 + radius - * normx / 2.0)); - p2.lineTo((float) (posx + radius * normx / 2.0 + radius * normy - / 2.0), (float) (posy + radius * normy / 2.0 - radius - * normx / 2.0)); - p2.lineTo((float) (posx - radius * normx / 2.0 + radius * normy - / 2.0), (float) (posy - radius * normy / 2.0 - radius - * normx / 2.0)); - p2.closePath(); - - if (isCIS) { - g2D.setColor(bck); - g2D.fill(p2); - g2D.draw(p2); - } else { - g2D.setColor(Color.white); - g2D.fill(p2); - g2D.setColor(bck); - g2D.draw(p2); - } - } - break; - case SUGAR: { - double ix = radius * normx / 2.0; - double iy = radius * normy / 2.0; - double jx = radius * normy / 2.0; - double jy = -radius * normx / 2.0; - - GeneralPath p2 = new GeneralPath(); - p2.moveTo((float) (posx - ix + jx), (float) (posy - iy + jy)); - p2.lineTo((float) (posx + ix + jx), (float) (posy + iy + jy)); - p2.lineTo((float) (posx - jx), (float) (posy - jy)); - p2.closePath(); - - if (isCIS) { - g2D.setColor(bck); - g2D.fill(p2); - g2D.draw(p2); - } else { - g2D.setColor(Color.white); - g2D.fill(p2); - g2D.setColor(bck); - g2D.draw(p2); - } - } - break; - } - g2D.setColor(bck); - } - - private void drawBasePairArc(VueVARNAGraphics g2D, int i, int j, - Point2D.Double orig, Point2D.Double dest, double scaleFactor, - ModeleBP style, double newRadius) { - double distance, coef; - if (j - i == 1) - coef = getBPHeightIncrement() * 1.75; - else - coef = getBPHeightIncrement(); - distance = dest.x - orig.x; - switch (_conf._mainBPStyle) { - case LW: { - double radiusCircle = ((RNA.BASE_PAIR_DISTANCE - _RNA.BASE_RADIUS) / 5.0) - * scaleFactor; - if (style.isCanonical()) { - if (style.isCanonicalGC()) { - if ((orig.x != dest.x) || (orig.y != dest.y)) { - g2D.drawArc((dest.x + orig.x) / 2., dest.y - - scaleFactor * _RNA.BASE_RADIUS / 2.0, - (distance - scaleFactor * _RNA.BASE_RADIUS - / 3.0), (distance * coef - scaleFactor - * _RNA.BASE_RADIUS / 3.0), 0, 180); - g2D.drawArc((dest.x + orig.x) / 2., dest.y - - scaleFactor * _RNA.BASE_RADIUS / 2.0, - (distance + scaleFactor * _RNA.BASE_RADIUS - / 3.0), (distance * coef + scaleFactor - * _RNA.BASE_RADIUS / 3.0), 0, 180); - } - } else if (style.isCanonicalAU()) { - g2D.drawArc((dest.x + orig.x) / 2., dest.y - scaleFactor - * _RNA.BASE_RADIUS / 2.0, (distance), - (distance * coef), 0, 180); - } else if (style.isWobbleUG()) { - Point2D.Double midtop = new Point2D.Double( - (dest.x + orig.x) / 2., dest.y - distance * coef - / 2. - scaleFactor * _RNA.BASE_RADIUS / 2.0); - g2D.drawArc(midtop.x, dest.y - scaleFactor - * _RNA.BASE_RADIUS / 2.0, (distance), - (distance * coef), 0, 180); - drawSymbol(g2D, midtop.x, midtop.y, 1., 0., radiusCircle, - false, ModeleBP.Edge.WC); - } else { - Point2D.Double midtop = new Point2D.Double( - (dest.x + orig.x) / 2., dest.y - distance * coef - / 2. - scaleFactor * _RNA.BASE_RADIUS / 2.0); - g2D.drawArc(midtop.x, dest.y - scaleFactor - * _RNA.BASE_RADIUS / 2.0, (distance), - (distance * coef), 0, 180); - drawSymbol(g2D, midtop.x, midtop.y, 1., 0., radiusCircle, - style.isCIS(), style.getEdgePartner5()); - } - } else { - ModeleBP.Edge p1 = style.getEdgePartner5(); - ModeleBP.Edge p2 = style.getEdgePartner3(); - Point2D.Double midtop = new Point2D.Double( - (dest.x + orig.x) / 2., dest.y - distance * coef / 2. - - scaleFactor * _RNA.BASE_RADIUS / 2.0); - g2D.drawArc(midtop.x, dest.y - scaleFactor * _RNA.BASE_RADIUS - / 2.0, (distance), (distance * coef), 0, 180); - if (p1 == p2) { - drawSymbol(g2D, midtop.x, midtop.y, 1., 0., radiusCircle, - false, style.getEdgePartner5()); - } else { - drawSymbol(g2D, midtop.x - scaleFactor * _RNA.BASE_RADIUS, - midtop.y, 1., 0., radiusCircle, style.isCIS(), p1); - drawSymbol(g2D, midtop.x + scaleFactor * _RNA.BASE_RADIUS, - midtop.y, -1., 0., radiusCircle, style.isCIS(), p2); - } - } - } - break; - case LW_ALT: { - double radiusCircle = ((RNA.BASE_PAIR_DISTANCE - _RNA.BASE_RADIUS) / 5.0) - * scaleFactor; - double distFromBaseCenter = DISTANCE_FACT*scaleFactor; - orig = new Point2D.Double(orig.x,orig.y-(distFromBaseCenter+newRadius)); - dest = new Point2D.Double(dest.x,dest.y-(distFromBaseCenter+newRadius)); - if (style.isCanonical()) { - if (style.isCanonicalGC()) { - if ((orig.x != dest.x) || (orig.y != dest.y)) { - g2D.drawArc((dest.x + orig.x) / 2., dest.y - - scaleFactor * _RNA.BASE_RADIUS / 2.0, - (distance - scaleFactor * _RNA.BASE_RADIUS - / 3.0), (distance * coef - scaleFactor - * _RNA.BASE_RADIUS / 3.0), 0, 180); - g2D.drawArc((dest.x + orig.x) / 2., dest.y - - scaleFactor * _RNA.BASE_RADIUS / 2.0, - (distance + scaleFactor * _RNA.BASE_RADIUS - / 3.0), (distance * coef + scaleFactor - * _RNA.BASE_RADIUS / 3.0), 0, 180); - } - } else if (style.isCanonicalAU()) { - g2D.drawArc((dest.x + orig.x) / 2., dest.y - scaleFactor - * _RNA.BASE_RADIUS / 2.0, (distance), - (distance * coef), 0, 180); - } - } else { - ModeleBP.Edge p1 = style.getEdgePartner5(); - ModeleBP.Edge p2 = style.getEdgePartner3(); - Point2D.Double midtop = new Point2D.Double( - (dest.x + orig.x) / 2., dest.y - distance * coef / 2. - - scaleFactor * _RNA.BASE_RADIUS / 2.0); - g2D.drawArc(midtop.x, dest.y - scaleFactor * _RNA.BASE_RADIUS - / 2.0, (distance), (distance * coef), 0, 180); - drawSymbol(g2D, orig.x, - orig.y-radiusCircle*.95, 1., 0., radiusCircle, style.isCIS(), p1); - drawSymbol(g2D, dest.x, - dest.y-radiusCircle*.95, -1., 0., radiusCircle, style.isCIS(), p2); - } - } - break; - default: - g2D.drawArc((dest.x + orig.x) / 2., dest.y - scaleFactor - * _RNA.BASE_RADIUS / 2.0, (distance), (distance * coef), 0, - 180); - break; - } - - } - - public static double DISTANCE_FACT = 2.; - - - private void drawBasePair(VueVARNAGraphics g2D, Point2D.Double orig, - Point2D.Double dest, ModeleBP style, double newRadius, - double scaleFactor) { - - double dx = dest.x - orig.x; - double dy = dest.y - orig.y; - double dist = Math.sqrt((dest.x - orig.x) * (dest.x - orig.x) - + (dest.y - orig.y) * (dest.y - orig.y)); - dx /= dist; - dy /= dist; - double nx = -dy; - double ny = dx; - orig = new Point2D.Double(orig.x + newRadius * dx, orig.y + newRadius - * dy); - dest = new Point2D.Double(dest.x - newRadius * dx, dest.y - newRadius - * dy); - switch (_conf._mainBPStyle) { - case LW: { - double radiusCircle = ((RNA.BASE_PAIR_DISTANCE - _RNA.BASE_RADIUS) / 5.0) - * scaleFactor; - if (style.isCanonical()) { - if (style.isCanonicalGC()) { - if ((orig.x != dest.x) || (orig.y != dest.y)) { - nx *= scaleFactor * _RNA.BASE_RADIUS / 4.0; - ny *= scaleFactor * _RNA.BASE_RADIUS / 4.0; - g2D.drawLine((orig.x + nx), (orig.y + ny), - (dest.x + nx), (dest.y + ny)); - g2D.drawLine((orig.x - nx), (orig.y - ny), - (dest.x - nx), (dest.y - ny)); - } - } else if (style.isCanonicalAU()) { - g2D.drawLine(orig.x, orig.y, dest.x, dest.y); - } else if (style.isWobbleUG()) { - double cx = (dest.x + orig.x) / 2.0; - double cy = (dest.y + orig.y) / 2.0; - g2D.drawLine(orig.x, orig.y, dest.x, dest.y); - drawSymbol(g2D, cx, cy, nx, ny, radiusCircle, false, - ModeleBP.Edge.WC); - } else { - double cx = (dest.x + orig.x) / 2.0; - double cy = (dest.y + orig.y) / 2.0; - g2D.drawLine(orig.x, orig.y, dest.x, dest.y); - drawSymbol(g2D, cx, cy, nx, ny, radiusCircle, - style.isCIS(), style.getEdgePartner5()); - } - } else { - ModeleBP.Edge p1 = style.getEdgePartner5(); - ModeleBP.Edge p2 = style.getEdgePartner3(); - double cx = (dest.x + orig.x) / 2.0; - double cy = (dest.y + orig.y) / 2.0; - g2D.drawLine(orig.x, orig.y, dest.x, dest.y); - if (p1 == p2) { - drawSymbol(g2D, cx, cy, nx, ny, radiusCircle, - style.isCIS(), p1); - - } else { - double vdx = (dest.x - orig.x); - double vdy = (dest.y - orig.y); - vdx /= 6.0; - vdy /= 6.0; - drawSymbol(g2D, cx + vdx, cy + vdy, -nx, -ny, radiusCircle, - style.isCIS(), p2); - drawSymbol(g2D, cx - vdx, cy - vdy, nx, ny, radiusCircle, - style.isCIS(), p1); - } - } - } - break; - case LW_ALT: { - double radiusCircle = ((RNA.BASE_PAIR_DISTANCE - _RNA.BASE_RADIUS) / 5.0) - * scaleFactor; - double distFromBaseCenter = DISTANCE_FACT*scaleFactor; - Point2D.Double norig = new Point2D.Double(orig.x+(distFromBaseCenter+.5*newRadius)*dx,orig.y+(distFromBaseCenter+.5*newRadius)*dy); - Point2D.Double ndest = new Point2D.Double(dest.x-(distFromBaseCenter+.5*newRadius)*dx,dest.y-(distFromBaseCenter+.5*newRadius)*dy); - if (style.isCanonical()) { - if (style.isCanonicalGC()) { - if ((norig.x != ndest.x) || (norig.y != ndest.y)) { - nx *= scaleFactor * _RNA.BASE_RADIUS / 4.0; - ny *= scaleFactor * _RNA.BASE_RADIUS / 4.0; - g2D.drawLine((norig.x + nx), (norig.y + ny), - (ndest.x + nx), (ndest.y + ny)); - g2D.drawLine((norig.x - nx), (norig.y - ny), - (ndest.x - nx), (ndest.y - ny)); - } - } else if (style.isCanonicalAU()) { - g2D.drawLine(norig.x, norig.y, ndest.x, ndest.y); - } else if (style.isWobbleUG()) { - double cx = (ndest.x + norig.x) / 2.0; - double cy = (ndest.y + norig.y) / 2.0; - g2D.drawLine(norig.x, norig.y, ndest.x, ndest.y); - drawSymbol(g2D, cx, cy, nx, ny, radiusCircle, false, - ModeleBP.Edge.WC); - } else { - double cx = (ndest.x + norig.x) / 2.0; - double cy = (ndest.y + norig.y) / 2.0; - g2D.drawLine(norig.x, norig.y, ndest.x, ndest.y); - drawSymbol(g2D, cx, cy, nx, ny, radiusCircle, - style.isCIS(), style.getEdgePartner5()); - } - } else { - ModeleBP.Edge p1 = style.getEdgePartner5(); - ModeleBP.Edge p2 = style.getEdgePartner3(); - double cx = (ndest.x + norig.x) / 2.0; - double cy = (ndest.y + norig.y) / 2.0; - g2D.drawLine(norig.x, norig.y, ndest.x, ndest.y); - if (p1 == p2) { - drawSymbol(g2D, cx, cy, nx, ny, radiusCircle, - style.isCIS(), p1); - - } else { - double fac = .4; - drawSymbol(g2D, ndest.x - fac*radiusCircle*dx, ndest.y - fac*radiusCircle*dy, -nx, -ny, radiusCircle, - style.isCIS(), p2); - drawSymbol(g2D, norig.x + fac*radiusCircle*dx, norig.y + fac*radiusCircle*dy, nx, ny, radiusCircle, - style.isCIS(), p1); - } - } - } - break; - case SIMPLE: - g2D.drawLine(orig.x, orig.y, dest.x, dest.y); - break; - case RNAVIZ: - double xcenter = (orig.x + dest.x) / 2.0; - double ycenter = (orig.y + dest.y) / 2.0; - double radius = Math.max(4.0 * scaleFactor, 1.0); - g2D.fillCircle((xcenter - radius), (ycenter - radius), - (2.0 * radius)); - break; - case NONE: - break; - } - } - - private Color getHighlightedVersion(Color c1, Color c2) { - int r1 = c1.getRed(); - int g1 = c1.getGreen(); - int b1 = c1.getBlue(); - int r2 = c2.getRed(); - int g2 = c2.getGreen(); - int b2 = c2.getBlue(); - double val = _blink.getVal(); - int nr = Math.max(0, - Math.min((int) ((r1 * val + r2 * (1.0 - val))), 255)); - int ng = Math.max(0, - Math.min((int) ((g1 * val + g2 * (1.0 - val))), 255)); - int nb = Math.max(0, - Math.min((int) ((b1 * val + b2 * (1.0 - val))), 255)); - return new Color(nr, ng, nb); - } - - private Color highlightFilter(int index, Color initialColor, Color c1, - Color c2, boolean localView) { - if (_selectedBases.contains(_RNA.getBaseAt(index)) && localView) { - return getHighlightedVersion(c1, c2); - } else - return initialColor; - } - - public static Point2D.Double computeExcentricUnitVector(int i, - Point2D.Double[] points, Point2D.Double[] centers) { - double dist = points[i].distance(centers[i]); - Point2D.Double byCenter = new Point2D.Double( - (points[i].x - centers[i].x) / dist, - (points[i].y - centers[i].y) / dist); - if ((i > 0) && (i < points.length - 1)) { - Point2D.Double p0 = points[i - 1]; - Point2D.Double p1 = points[i]; - Point2D.Double p2 = points[i + 1]; - double dist1 = p2.distance(p1); - Point2D.Double v1 = new Point2D.Double((p2.x - p1.x) / dist1, - (p2.y - p1.y) / dist1); - Point2D.Double vn1 = new Point2D.Double(v1.y, -v1.x); - double dist2 = p1.distance(p0); - Point2D.Double v2 = new Point2D.Double((p1.x - p0.x) / dist2, - (p1.y - p0.y) / dist2); - Point2D.Double vn2 = new Point2D.Double(v2.y, -v2.x); - Point2D.Double vn = new Point2D.Double((vn1.x + vn2.x) / 2.0, - (vn1.y + vn2.y) / 2.0); - double D = vn.distance(new Point2D.Double(0.0, 0.0)); - vn.x /= D; - vn.y /= D; - if (byCenter.x * vn.x + byCenter.y * vn.y < 0) { - vn.x = -vn.x; - vn.y = -vn.y; - } - return vn; - } - else if (((i==0) || (i==points.length-1)) && (points.length>1)) { - int a = (i==0)?0:points.length-1; - int b = (i==0)?1:points.length-2; - double D = points[a].distance(points[b]); - return new Point2D.Double( - (points[a].x - points[b].x) / D, - (points[a].y - points[b].y) / D); - } - else { - return byCenter; - } - } - - private void drawBase(VueVARNAGraphics g2D, int i, Point2D.Double[] points, - Point2D.Double[] centers, double newRadius, double _scaleFactor, - boolean localView) { - Point2D.Double p = points[i]; - ModeleBase mb = _RNA.get_listeBases().get(i); - g2D.setFont(_conf._fontBasesGeneral); - Color baseInnerColor = highlightFilter(i, - _RNA.getBaseInnerColor(i, _conf), Color.white, - _RNA.getBaseInnerColor(i, _conf), localView); - Color baseOuterColor = highlightFilter(i, - _RNA.getBaseOuterColor(i, _conf), - _RNA.getBaseOuterColor(i, _conf), Color.white, localView); - Color baseNameColor = highlightFilter(i, - _RNA.getBaseNameColor(i, _conf), - _RNA.getBaseNameColor(i, _conf), Color.white, localView); - if ( RNA.whiteLabelPreferrable(baseInnerColor)) - { - baseNameColor=Color.white; - } - - if (mb instanceof ModeleBaseNucleotide) { - ModeleBaseNucleotide mbn = (ModeleBaseNucleotide) mb; - String res = mbn.getBase(); - if (_hoveredBase == mb && localView && isModifiable()) { - g2D.setColor(_conf._hoverColor); - g2D.fillCircle(p.getX() - 1.5 * newRadius, p.getY() - 1.5 - * newRadius, 3.0 * newRadius); - g2D.setColor(_conf._hoverColor.darker()); - g2D.drawCircle(p.getX() - 1.5 * newRadius, p.getY() - 1.5 - * newRadius, 3.0 * newRadius); - g2D.setPlainStroke(); - } - if (_conf._fillBases) { - // Filling inner circle - g2D.setColor(baseInnerColor); - g2D.fillCircle(p.getX() - newRadius, p.getY() - newRadius, - 2.0 * newRadius); - } - - if (_conf._drawOutlineBases) { - // Drawing outline - g2D.setColor(baseOuterColor); - g2D.setStrokeThickness(_conf._baseThickness * _scaleFactor); - g2D.drawCircle(p.getX() - newRadius, p.getY() - newRadius, - 2.0 * newRadius); - } - // Drawing label - g2D.setColor(baseNameColor); - g2D.drawStringCentered(String.valueOf(res), p.getX(), p.getY()); - } else if (mb instanceof ModeleBasesComparison) { - - ModeleBasesComparison mbc = (ModeleBasesComparison) mb; - - // On lui donne l'aspect voulue (on a un trait droit) - g2D.setPlainStroke(); // On doit avoir un trait droit, sans arrondit - g2D.setStrokeThickness(_conf._baseThickness * _scaleFactor); - - // On dessine l'étiquette, rectangle aux bords arrondies. - g2D.setColor(baseInnerColor); - g2D.fillRoundRect((p.getX() - 1.5 * newRadius), - (p.getY() - newRadius), (3.0 * newRadius), - (2.0 * newRadius), 10 * _scaleFactor, 10 * _scaleFactor); - - /* Dessin du rectangle exterieur (bords) */ - g2D.setColor(baseOuterColor); - g2D.drawRoundRect((p.getX() - 1.5 * newRadius), - (p.getY() - newRadius), (3 * newRadius), (2 * newRadius), - 10 * _scaleFactor, 10 * _scaleFactor); - - // On le dessine au centre de l'étiquette. - g2D.drawLine((p.getX()), (p.getY() + newRadius) - 1, (p.getX()), - (p.getY() - newRadius) + 1); - - /* Dessin du nom de la base (A,C,G,U,etc...) */ - // On créer le texte des étiquettes - String label1 = String.valueOf(mbc.getBase1()); - String label2 = String.valueOf(mbc.getBase2()); - - // On leur donne une couleur - g2D.setColor(getRNA().get_listeBases().get(i).getStyleBase() - .getBaseNameColor()); - - // Et on les dessine. - g2D.drawStringCentered(label1, p.getX() - (.75 * newRadius), - p.getY()); - g2D.drawStringCentered(label2, p.getX() + (.75 * newRadius), - p.getY()); - } - - // Drawing base number - if (_RNA.isNumberDrawn(mb, getNumPeriod())) { - - Point2D.Double vn = computeExcentricUnitVector(i, points, centers); - g2D.setColor(mb.getStyleBase().getBaseNumberColor()); - g2D.setFont(_conf._numbersFont); - double factorMin = Math.min(.5, _conf._distNumbers); - double factorMax = Math.min(_conf._distNumbers - 1.5, - _conf._distNumbers); - g2D.drawLine(p.x + vn.x * ((1 + factorMin) * newRadius), p.y + vn.y - * ((1 + factorMin) * newRadius), p.x + vn.x - * ((1 + factorMax) * newRadius), p.y + vn.y - * ((1 + factorMax) * newRadius)); - g2D.drawStringCentered(mb.getLabel(), p.x + vn.x - * ((1 + _conf._distNumbers) * newRadius), p.y + vn.y - * ((1 + _conf._distNumbers) * newRadius)); - - } - } - - void drawChemProbAnnotation(VueVARNAGraphics g2D, ChemProbAnnotation cpa, - Point2D.Double anchor, double scaleFactor) { - g2D.setColor(cpa.getColor()); - g2D.setStrokeThickness(RNA.CHEM_PROB_ARROW_THICKNESS * scaleFactor - * cpa.getIntensity()); - g2D.setPlainStroke(); - Point2D.Double v = cpa.getDirVector(); - Point2D.Double vn = cpa.getNormalVector(); - Point2D.Double base = new Point2D.Double( - (anchor.x + _RNA.CHEM_PROB_DIST * scaleFactor * v.x), - (anchor.y + _RNA.CHEM_PROB_DIST * scaleFactor * v.y)); - Point2D.Double edge = new Point2D.Double( - (base.x + _RNA.CHEM_PROB_BASE_LENGTH * cpa.getIntensity() - * scaleFactor * v.x), - (base.y + _RNA.CHEM_PROB_BASE_LENGTH * cpa.getIntensity() - * scaleFactor * v.y)); - switch (cpa.getType()) { - case ARROW: { - Point2D.Double arrowTip1 = new Point2D.Double( - (base.x + cpa.getIntensity() - * scaleFactor - * (_RNA.CHEM_PROB_ARROW_WIDTH * vn.x + _RNA.CHEM_PROB_ARROW_HEIGHT - * v.x)), - (base.y + cpa.getIntensity() - * scaleFactor - * (_RNA.CHEM_PROB_ARROW_WIDTH * vn.y + _RNA.CHEM_PROB_ARROW_HEIGHT - * v.y))); - Point2D.Double arrowTip2 = new Point2D.Double( - (base.x + cpa.getIntensity() - * scaleFactor - * (-_RNA.CHEM_PROB_ARROW_WIDTH * vn.x + _RNA.CHEM_PROB_ARROW_HEIGHT - * v.x)), - (base.y + cpa.getIntensity() - * scaleFactor - * (-_RNA.CHEM_PROB_ARROW_WIDTH * vn.y + _RNA.CHEM_PROB_ARROW_HEIGHT - * v.y))); - g2D.drawLine(base.x, base.y, edge.x, edge.y); - g2D.drawLine(base.x, base.y, arrowTip1.x, arrowTip1.y); - g2D.drawLine(base.x, base.y, arrowTip2.x, arrowTip2.y); - } - break; - case PIN: { - Point2D.Double side1 = new Point2D.Double( - (edge.x - cpa.getIntensity() * scaleFactor - * (_RNA.CHEM_PROB_PIN_SEMIDIAG * v.x)), - (edge.y - cpa.getIntensity() * scaleFactor - * (_RNA.CHEM_PROB_PIN_SEMIDIAG * v.y))); - Point2D.Double side2 = new Point2D.Double( - (edge.x - cpa.getIntensity() * scaleFactor - * (_RNA.CHEM_PROB_PIN_SEMIDIAG * vn.x)), - (edge.y - cpa.getIntensity() * scaleFactor - * (_RNA.CHEM_PROB_PIN_SEMIDIAG * vn.y))); - Point2D.Double side3 = new Point2D.Double( - (edge.x + cpa.getIntensity() * scaleFactor - * (_RNA.CHEM_PROB_PIN_SEMIDIAG * v.x)), - (edge.y + cpa.getIntensity() * scaleFactor - * (_RNA.CHEM_PROB_PIN_SEMIDIAG * v.y))); - Point2D.Double side4 = new Point2D.Double( - (edge.x + cpa.getIntensity() * scaleFactor - * (_RNA.CHEM_PROB_PIN_SEMIDIAG * vn.x)), - (edge.y + cpa.getIntensity() * scaleFactor - * (_RNA.CHEM_PROB_PIN_SEMIDIAG * vn.y))); - GeneralPath p2 = new GeneralPath(); - p2.moveTo((float) side1.x, (float) side1.y); - p2.lineTo((float) side2.x, (float) side2.y); - p2.lineTo((float) side3.x, (float) side3.y); - p2.lineTo((float) side4.x, (float) side4.y); - p2.closePath(); - g2D.fill(p2); - g2D.drawLine(base.x, base.y, edge.x, edge.y); - } - break; - case TRIANGLE: { - Point2D.Double arrowTip1 = new Point2D.Double( - (edge.x + cpa.getIntensity() * scaleFactor - * (_RNA.CHEM_PROB_TRIANGLE_WIDTH * vn.x)), - (edge.y + cpa.getIntensity() * scaleFactor - * (_RNA.CHEM_PROB_TRIANGLE_WIDTH * vn.y))); - Point2D.Double arrowTip2 = new Point2D.Double( - (edge.x + cpa.getIntensity() * scaleFactor - * (-_RNA.CHEM_PROB_TRIANGLE_WIDTH * vn.x)), - (edge.y + cpa.getIntensity() * scaleFactor - * (-_RNA.CHEM_PROB_TRIANGLE_WIDTH * vn.y))); - GeneralPath p2 = new GeneralPath(); - p2.moveTo((float) base.x, (float) base.y); - p2.lineTo((float) arrowTip1.x, (float) arrowTip1.y); - p2.lineTo((float) arrowTip2.x, (float) arrowTip2.y); - p2.closePath(); - g2D.fill(p2); - } - break; - case DOT: { - Double radius = scaleFactor * _RNA.CHEM_PROB_DOT_RADIUS - * cpa.getIntensity(); - Point2D.Double center = new Point2D.Double((base.x + radius * v.x), - (base.y + radius * v.y)); - g2D.fillCircle((center.x - radius), (center.y - radius), - (2 * radius)); - } - break; - } - } - - Point2D.Double buildCaptionPosition(ModeleBase mb, double scaleFactor, - double heightEstimate) { - double radius = 2.0; - if (_RNA.isNumberDrawn(mb, getNumPeriod())) { - radius += _conf._distNumbers; - } - Point2D.Double center = mb.getCenter(); - Point2D.Double p = mb.getCoords(); - double realDistance = _RNA.BASE_RADIUS * radius + heightEstimate; - return new Point2D.Double(center.getX() + (p.getX() - center.getX()) - * ((p.distance(center) + realDistance) / p.distance(center)), - center.getY() - + (p.getY() - center.getY()) - * ((p.distance(center) + realDistance) / p - .distance(center))); - } - - private void renderAnnotations(VueVARNAGraphics g2D, double offX, - double offY, double rnaBBoxX, double rnaBBoxY, double scaleFactor) { - for (TextAnnotation textAnnotation : _RNA.getAnnotations()) { - g2D.setColor(textAnnotation.getColor()); - g2D.setFont(textAnnotation - .getFont() - .deriveFont( - (float) (2.0 * textAnnotation.getFont().getSize() * scaleFactor))); - Point2D.Double position = textAnnotation.getCenterPosition(); - if (textAnnotation.getType() == TextAnnotation.AnchorType.BASE) { - ModeleBase mb = (ModeleBase) textAnnotation.getAncrage(); - double fontHeight = Math.ceil(textAnnotation.getFont() - .getSize()); - position = buildCaptionPosition(mb, scaleFactor, fontHeight); - } - position = transformCoord(position, offX, offY, rnaBBoxX, rnaBBoxY, - scaleFactor); - g2D.drawStringCentered(textAnnotation.getTexte(), position.x, - position.y); - if ((_selectedAnnotation == textAnnotation) - && (_highlightAnnotation)) { - drawStringOutline(g2D, textAnnotation.getTexte(), position.x, - position.y, 5); - } - } - for (ChemProbAnnotation cpa : _RNA.getChemProbAnnotations()) { - Point2D.Double anchor = transformCoord(cpa.getAnchorPosition(), - offX, offY, rnaBBoxX, rnaBBoxY, scaleFactor); - drawChemProbAnnotation(g2D, cpa, anchor, scaleFactor); - } - - } - - public Rectangle2D.Double getExtendedRNABBox() { - // We get the logical bounding box - Rectangle2D.Double rnabbox = _RNA.getBBox(); - rnabbox.y -= _conf._distNumbers * _RNA.BASE_RADIUS; - rnabbox.height += 2.0 * _conf._distNumbers * _RNA.BASE_RADIUS; - rnabbox.x -= _conf._distNumbers * _RNA.BASE_RADIUS; - rnabbox.width += 2.0 * _conf._distNumbers * _RNA.BASE_RADIUS; - if (_RNA.hasVirtualLoops()) { - rnabbox.y -= RNA.VIRTUAL_LOOP_RADIUS; - rnabbox.height += 2.0 * RNA.VIRTUAL_LOOP_RADIUS; - rnabbox.x -= RNA.VIRTUAL_LOOP_RADIUS; - rnabbox.width += 2.0 * RNA.VIRTUAL_LOOP_RADIUS; - } - return rnabbox; - } - - public void drawBackbone(VueVARNAGraphics g2D, Point2D.Double[] newCoords, - double newRadius, double _scaleFactor) { - // Drawing backbone - if (getDrawBackbone()) { - g2D.setStrokeThickness(1.5 * _scaleFactor); - g2D.setColor(_conf._backboneColor); - - ModeleBackbone bck = _RNA.getBackbone(); - - - for (int i = 1; i < _RNA.get_listeBases().size(); i++) { - Point2D.Double p1 = newCoords[i - 1]; - Point2D.Double p2 = newCoords[i]; - double dist = p1.distance(p2); - int a = _RNA.getBaseAt(i - 1).getElementStructure(); - int b = _RNA.getBaseAt(i).getElementStructure(); - boolean consecutivePair = (a == i) && (b == i - 1); - - if ((dist > 0)) { - Point2D.Double vbp = new Point2D.Double(); - vbp.x = (p2.x - p1.x) / dist; - vbp.y = (p2.y - p1.y) / dist; - - BackboneType bt = bck.getTypeBefore(i); - if (bt!=BackboneType.DISCONTINUOUS_TYPE) - { - if (bt==BackboneType.MISSING_PART_TYPE) { - g2D.setSelectionStroke(); - } else { - g2D.setPlainStroke(); - } - g2D.setColor(bck.getColorBefore(i, _conf._backboneColor)); - - if (consecutivePair - && (_RNA.getDrawMode() != RNA.DRAW_MODE_LINEAR) - && (_RNA.getDrawMode() != RNA.DRAW_MODE_CIRCULAR)) { - int dir = 0; - if (i + 1 < newCoords.length) { - dir = (_RNA.testDirectionality(i - 1, i, i + 1) ? -1 - : 1); - } else if (i - 2 >= 0) { - dir = (_RNA.testDirectionality(i - 2, i - 1, i) ? -1 - : 1); - } - Point2D.Double vn = new Point2D.Double(dir * vbp.y, - -dir * vbp.x); - Point2D.Double centerSeg = new Point2D.Double( - (p1.x + p2.x) / 2.0, (p1.y + p2.y) / 2.0); - double distp1CenterSeq = p1.distance(centerSeg); - double centerDist = Math - .sqrt((RNA.VIRTUAL_LOOP_RADIUS * _scaleFactor - * RNA.VIRTUAL_LOOP_RADIUS * _scaleFactor) - - distp1CenterSeq * distp1CenterSeq); - Point2D.Double centerLoop = new Point2D.Double( - centerSeg.x + centerDist * vn.x, centerSeg.y - + centerDist * vn.y); - double radius = centerLoop.distance(p1); - double a1 = 360. - * (Math.atan2(-(p1.y - centerLoop.y), - (p1.x - centerLoop.x))) - / (2. * Math.PI); - double a2 = 360. - * (Math.atan2(-(p2.y - centerLoop.y), - (p2.x - centerLoop.x))) - / (2. * Math.PI); - double angle = (a2 - a1); - if (-dir * angle < 0) { - angle += -dir * 360.; - } - // if (angle<0.) angle += 360.; - // angle = -dir*(360-dir*angle); - g2D.drawArc(centerLoop.x + .8 * newRadius * vn.x, - centerLoop.y + .8 * newRadius * vn.y, - 2 * radius, 2 * radius, a1, angle); - } else { - g2D.drawLine((newCoords[i - 1].x + newRadius * vbp.x), - (newCoords[i - 1].y + newRadius * vbp.y), - (newCoords[i].x - newRadius * vbp.x), - (newCoords[i].y - newRadius * vbp.y)); - } - } - } - } - } - } - - public Point2D.Double logicToPanel(Point2D.Double logicPoint) { - return new Point2D.Double(_offX - + (getScaleFactor() * (logicPoint.x - _offsetRNA.x)), _offY - + (getScaleFactor() * (logicPoint.y - _offsetRNA.y))); - - } - - public Rectangle2D.Double renderRNA(VueVARNAGraphics g2D, - Rectangle2D.Double bbox) { - return renderRNA(g2D, bbox, false, true); - } - - private double computeScaleFactor(Rectangle2D.Double bbox, - boolean localView, boolean autoCenter) { - Rectangle2D.Double rnabbox = getExtendedRNABBox(); - double scaleFactor = Math.min((double) bbox.width - / (double) rnabbox.width, (double) bbox.height - / (double) rnabbox.height); - - // Use it to get an estimate of the font size for numbers ... - float newFontSize = Math.max(1, - (int) ((1.7 * _RNA.BASE_RADIUS) * scaleFactor)); - // ... and increase bounding box accordingly - rnabbox.y -= newFontSize; - rnabbox.height += newFontSize; - if (_conf._drawColorMap) { - rnabbox.height += getColorMapHeight(); - } - rnabbox.x -= newFontSize; - rnabbox.width += newFontSize; - - // Now, compute the final scaling factor and corresponding font size - scaleFactor = Math.min((double) bbox.width / (double) rnabbox.width, - (double) bbox.height / (double) rnabbox.height); - if (localView) { - if (_conf._autoFit) - setScaleFactor(scaleFactor); - scaleFactor = getScaleFactor(); - } - return scaleFactor; - } - - public synchronized Rectangle2D.Double renderRNA(VueVARNAGraphics g2D, - Rectangle2D.Double bbox, boolean localView, boolean autoCenter) { - Rectangle2D.Double rnaMultiBox = new Rectangle2D.Double(0, 0, 1, 1); - double scaleFactor = computeScaleFactor(bbox, localView, autoCenter); - float newFontSize = Math.max(1, - (int) ((1.7 * _RNA.BASE_RADIUS) * scaleFactor)); - double newRadius = Math.max(1.0, (scaleFactor * _RNA.BASE_RADIUS)); - setBaseFontSize(newFontSize); - setNumbersFontSize(newFontSize); - double offX = bbox.x; - double offY = bbox.y; - Rectangle2D.Double rnabbox = getExtendedRNABBox(); - - if (_RNA.getSize() != 0) { - - Point2D.Double offsetRNA = new Point2D.Double(rnabbox.x, rnabbox.y); - - if (autoCenter) { - offX = (bbox.x + (bbox.width - Math.round(rnabbox.width - * scaleFactor)) / 2.0); - offY = (bbox.y + (bbox.height - Math.round(rnabbox.height - * scaleFactor)) / 2.0); - if (localView) { - _offX = offX; - _offY = offY; - _offsetPanel = new Point2D.Double(_offX, _offY); - _offsetRNA = new Point2D.Double(rnabbox.x, rnabbox.y); - } - } - - if (localView) { - offX = _offX; - offY = _offY; - offsetRNA = _offsetRNA; - } - - // Re-scaling once and for all - Point2D.Double[] newCoords = new Point2D.Double[_RNA - .get_listeBases().size()]; - Point2D.Double[] newCenters = new Point2D.Double[_RNA - .get_listeBases().size()]; - for (int i = 0; i < _RNA.get_listeBases().size(); i++) { - ModeleBase mb = _RNA.getBaseAt(i); - newCoords[i] = new Point2D.Double(offX - + (scaleFactor * (mb.getCoords().x - offsetRNA.x)), - offY + (scaleFactor * (mb.getCoords().y - offsetRNA.y))); - - Point2D.Double centerBck = _RNA.getCenter(i); - // si la base est dans un angle entre une boucle et une helice - if (_RNA.get_drawMode() == RNA.DRAW_MODE_NAVIEW - || _RNA.get_drawMode() == RNA.DRAW_MODE_RADIATE) { - if ((mb.getElementStructure() != -1) - && i < _RNA.get_listeBases().size() - 1 && i > 1) { - ModeleBase b1 = _RNA.get_listeBases().get(i - 1); - ModeleBase b2 = _RNA.get_listeBases().get(i + 1); - int j1 = b1.getElementStructure(); - int j2 = b2.getElementStructure(); - if ((j1 == -1) ^ (j2 == -1)) { - // alors la position du nombre associé doit etre - Point2D.Double a1 = b1.getCoords(); - Point2D.Double a2 = b2.getCoords(); - Point2D.Double c1 = b1.getCenter(); - Point2D.Double c2 = b2.getCenter(); - - centerBck.x = mb.getCoords().x + (c1.x - a1.x) - / c1.distance(a1) + (c2.x - a2.x) - / c2.distance(a2); - centerBck.y = mb.getCoords().y + (c1.y - a1.y) - / c1.distance(a1) + (c2.y - a2.y) - / c2.distance(a2); - } - } - } - newCenters[i] = new Point2D.Double(offX - + (scaleFactor * (centerBck.x - offsetRNA.x)), offY - + (scaleFactor * (centerBck.y - offsetRNA.y))); - } - // Keep track of coordinates for mouse interactions - if (localView) { - _realCoords = newCoords; - _realCenters = newCenters; - } - - g2D.setStrokeThickness(1.5 * scaleFactor); - g2D.setPlainStroke(); - g2D.setFont(_conf._fontBasesGeneral); - - // Drawing region highlights Annotation - drawRegionHighlightsAnnotation(g2D, _realCoords, _realCenters, - scaleFactor); - drawBackbone(g2D, newCoords, newRadius, scaleFactor); - - // Drawing base-pairs - // pour chaque base - for (int i = 0; i < _RNA.get_listeBases().size(); i++) { - int j = _RNA.get_listeBases().get(i).getElementStructure(); - // si c'est une parenthese ouvrante (premiere base du - // couple) - if (j > i) { - ModeleBP msbp = _RNA.get_listeBases().get(i).getStyleBP(); - // System.err.println(msbp); - if (msbp.isCanonical() || _conf._drawnNonCanonicalBP) { - if (_RNA.get_drawMode() == RNA.DRAW_MODE_LINEAR) { - g2D.setStrokeThickness(_RNA.getBasePairThickness( - msbp, _conf) - * 2.0 - * scaleFactor - * _conf._bpThickness); - } else { - g2D.setStrokeThickness(_RNA.getBasePairThickness( - msbp, _conf) * 1.5 * scaleFactor); - } - g2D.setColor(_RNA.getBasePairColor(msbp, _conf)); - - if (_RNA.get_drawMode() == RNA.DRAW_MODE_LINEAR) { - drawBasePairArc(g2D, i, j, newCoords[i], - newCoords[j], scaleFactor, msbp, newRadius); - } else { - drawBasePair(g2D, newCoords[i], newCoords[j], msbp, - newRadius, scaleFactor); - } - } - } - } - - // Liaisons additionelles (non planaires) - if (_conf._drawnNonPlanarBP) { - ArrayList bpaux = _RNA.getStructureAux(); - for (int k = 0; k < bpaux.size(); k++) { - ModeleBP msbp = bpaux.get(k); - if (msbp.isCanonical() || _conf._drawnNonCanonicalBP) { - int i = msbp.getPartner5().getIndex(); - int j = msbp.getPartner3().getIndex(); - if (_RNA.get_drawMode() == RNA.DRAW_MODE_LINEAR) { - g2D.setStrokeThickness(_RNA.getBasePairThickness( - msbp, _conf) - * 2.5 - * scaleFactor - * _conf._bpThickness); - g2D.setPlainStroke(); - } else { - g2D.setStrokeThickness(_RNA.getBasePairThickness( - msbp, _conf) * 1.5 * scaleFactor); - g2D.setPlainStroke(); - } - - g2D.setColor(_RNA.getBasePairColor(msbp, _conf)); - if (j > i) { - if (_RNA.get_drawMode() == RNA.DRAW_MODE_LINEAR) { - drawBasePairArc(g2D, i, j, newCoords[i], - newCoords[j], scaleFactor, msbp, newRadius); - } else { - drawBasePair(g2D, newCoords[i], newCoords[j], - msbp, newRadius, scaleFactor); - } - } - } - } - } - - // Drawing bases - g2D.setPlainStroke(); - for (int i = 0; i < Math.min(_RNA.get_listeBases().size(), - newCoords.length); i++) { - drawBase(g2D, i, newCoords, newCenters, newRadius, scaleFactor, - localView); - } - - rnaMultiBox = new Rectangle2D.Double(offX, offY, - (scaleFactor * rnabbox.width) - 1, - (scaleFactor * rnabbox.height) - 1); - - if (localView) { - // Drawing bbox - if (_debug || _drawBBox) { - g2D.setColor(Color.RED); - g2D.setSelectionStroke(); - g2D.drawRect(rnaMultiBox.x, rnaMultiBox.y, - rnaMultiBox.width, rnaMultiBox.height); - } - - // Draw color map - if (_conf._drawColorMap) { - drawColorMap(g2D, scaleFactor, rnabbox); - } - - if (_debug || _drawBBox) { - g2D.setColor(Color.GRAY); - g2D.setSelectionStroke(); - g2D.drawRect(0, 0, getWidth() - 1, getHeight() - - getTitleHeight() - 1); - } - } - // Draw annotations - renderAnnotations(g2D, offX, offY, offsetRNA.x, offsetRNA.y, - scaleFactor); - // Draw additional debug shape - if (_RNA._debugShape != null) { - Color c = new Color(255, 0, 0, 50); - g2D.setColor(c); - AffineTransform at = new AffineTransform(); - at.translate(offX - scaleFactor * rnabbox.x, offY - scaleFactor - * rnabbox.y); - at.scale(scaleFactor, scaleFactor); - Shape s = at.createTransformedShape(_RNA._debugShape); - if (s instanceof GeneralPath) { - g2D.fill((GeneralPath) s); - } - } - } else { - g2D.setColor(VARNAConfig.DEFAULT_MESSAGE_COLOR); - g2D.setFont(VARNAConfig.DEFAULT_MESSAGE_FONT); - rnaMultiBox = new Rectangle2D.Double(0,0,10,10); - g2D.drawStringCentered("No RNA here", bbox.getCenterX(),bbox.getCenterY()); - } - return rnaMultiBox; - } - - public void centerViewOn(double x, double y) { - Rectangle2D.Double r = _RNA.getBBox(); - _target = new Point2D.Double(x, y); - Point2D.Double q = logicToPanel(_target); - Point p = new Point((int) (-q.x), (int) (-q.y)); - setTranslation(p); - repaint(); - } - - Point2D.Double _target = new Point2D.Double(0, 0); - Point2D.Double _target2 = new Point2D.Double(0, 0); - - public ModeleBase getBaseAt(Point2D.Double po) { - ModeleBase mb = null; - Point2D.Double p = panelToLogicPoint(po); - double dist = Double.MAX_VALUE; - for (ModeleBase tmp : _RNA.get_listeBases()) { - double ndist = tmp.getCoords().distance(p); - if (dist > ndist) { - mb = tmp; - dist = ndist; - } - } - return mb; - } - - public void setColorMapValues(Double[] values) { - _RNA.setColorMapValues(values, _conf._cm, true); - _conf._drawColorMap = true; - repaint(); - } - - public void setColorMapMaxValue(double d) { - _conf._cm.setMaxValue(d); - } - - public void setColorMapMinValue(double d) { - _conf._cm.setMinValue(d); - } - - public ModeleColorMap getColorMap() { - return _conf._cm; - } - - public void setColorMap(ModeleColorMap cm) { - //_RNA.adaptColorMapToValues(cm); - _conf._cm = cm; - repaint(); - } - - public void setColorMapCaption(String caption) { - _conf._colorMapCaption = caption; - repaint(); - } - - public String getColorMapCaption() { - return _conf._colorMapCaption; - } - - public void drawColorMap(boolean draw) { - _conf._drawColorMap = draw; - } - - private double getColorMapHeight() { - double result = VARNAConfig.DEFAULT_COLOR_MAP_FONT_SIZE - + _conf._colorMapHeight; - if (!_conf._colorMapCaption.equals("")) - result += VARNAConfig.DEFAULT_COLOR_MAP_FONT_SIZE; - return result; - } - - private void drawColorMap(VueVARNAGraphics g2D, double scaleFactor, - Rectangle2D.Double rnabbox) { - double v1 = _conf._cm.getMinValue(); - double v2 = _conf._cm.getMaxValue(); - double x, y; - g2D.setPlainStroke(); - - double xSpaceAvail = 0; - double ySpaceAvail = Math - .min((getHeight() - rnabbox.height * scaleFactor - getTitleHeight()) / 2.0, - scaleFactor - * (_conf._colorMapHeight + VARNAConfig.DEFAULT_COLOR_MAP_FONT_SIZE)); - if ((int) ySpaceAvail == 0) { - xSpaceAvail = Math.min( - (getWidth() - rnabbox.width * scaleFactor) / 2, scaleFactor - * (_conf._colorMapWidth) - + VARNAConfig.DEFAULT_COLOR_MAP_STRIPE_WIDTH); - } - double xBase = (xSpaceAvail + _offX + scaleFactor - * (rnabbox.width - _conf._colorMapWidth - _conf._colorMapXOffset)); - double hcaption = VARNAConfig.DEFAULT_COLOR_MAP_FONT_SIZE; - double yBase = (ySpaceAvail + _offY + scaleFactor - * (rnabbox.height - _conf._colorMapHeight - - _conf._colorMapYOffset - hcaption)); - - for (int i = 0; i < _conf._colorMapWidth; i++) { - double ratio = (((double) i) / ((double) _conf._colorMapWidth)); - double val = v1 + (v2 - v1) * ratio; - g2D.setColor(_conf._cm.getColorForValue(val)); - x = (xBase + scaleFactor * i); - y = yBase; - g2D.fillRect(x, y, scaleFactor - * VARNAConfig.DEFAULT_COLOR_MAP_STRIPE_WIDTH, - (scaleFactor * _conf._colorMapHeight)); - } - g2D.setColor(VARNAConfig.DEFAULT_COLOR_MAP_OUTLINE); - g2D.drawRect(xBase, yBase, - (VARNAConfig.DEFAULT_COLOR_MAP_STRIPE_WIDTH - 1 + scaleFactor - * _conf._colorMapWidth), - ((scaleFactor * _conf._colorMapHeight))); - g2D.setFont(getFont() - .deriveFont( - (float) (scaleFactor * VARNAConfig.DEFAULT_COLOR_MAP_FONT_SIZE))); - g2D.setColor(VARNAConfig.DEFAULT_COLOR_MAP_FONT_COLOR); - NumberFormat nf = NumberFormat.getInstance(); - nf.setMaximumFractionDigits(2); - nf.setMinimumFractionDigits(0); - g2D.drawStringCentered(nf.format(_conf._cm.getMinValue()), xBase, - yBase - + scaleFactor * (_conf._colorMapHeight+(VARNAConfig.DEFAULT_COLOR_MAP_FONT_SIZE / 1.7))); - g2D.drawStringCentered(nf.format(_conf._cm.getMaxValue()), xBase - + VARNAConfig.DEFAULT_COLOR_MAP_STRIPE_WIDTH + scaleFactor - * _conf._colorMapWidth, - yBase - + scaleFactor * (_conf._colorMapHeight+(VARNAConfig.DEFAULT_COLOR_MAP_FONT_SIZE / 1.7))); - if (!_conf._colorMapCaption.equals("")) - g2D.drawStringCentered( - "" + _conf._colorMapCaption, - xBase + scaleFactor * _conf._colorMapWidth / 2.0, - yBase - + scaleFactor - * (VARNAConfig.DEFAULT_COLOR_MAP_FONT_SIZE / 1.7 + _conf._colorMapHeight)); - - } - - public Point2D.Double panelToLogicPoint(Point2D.Double p) { - return new Point2D.Double( - ((p.x - getOffsetPanel().x) / getScaleFactor()) - + getRNAOffset().x, - ((p.y - getOffsetPanel().y) / getScaleFactor()) - + getRNAOffset().y); - } - - public Point2D.Double transformCoord(Point2D.Double coordDebut, - double offX, double offY, double rnaBBoxX, double rnaBBoxY, - double scaleFactor) { - return new Point2D.Double(offX - + (scaleFactor * (coordDebut.x - rnaBBoxX)), offY - + (scaleFactor * (coordDebut.y - rnaBBoxY))); - } - - public void eraseSequence() { - _RNA.eraseSequence(); - } - - public Point2D.Double transformCoord(Point2D.Double coordDebut) { - Rectangle2D.Double rnabbox = getExtendedRNABBox(); - return new Point2D.Double(_offX - + (getScaleFactor() * (coordDebut.x - rnabbox.x)), _offY - + (getScaleFactor() * (coordDebut.y - rnabbox.y))); - } - - public void paintComponent(Graphics g) { - paintComponent(g, false); - } - - public void paintComponent(Graphics g, boolean transparentBackground) { - if (_premierAffichage) { - // _border = new Dimension(0, 0); - _translation.x = 0; - _translation.y = (int) (-getTitleHeight() / 2.0); - _popup.buildPopupMenu(); - this.add(_popup); - _premierAffichage = false; - } - - Graphics2D g2 = (Graphics2D) g; - Stroke dflt = g2.getStroke(); - VueVARNAGraphics g2D = new SwingGraphics(g2); - g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, - RenderingHints.VALUE_ANTIALIAS_ON); - this.removeAll(); - super.paintComponent(g2); - renderComponent(g2D, transparentBackground, getScaleFactor()); - if (isFocusOwner()) { - g2.setStroke(new BasicStroke(1.5f)); - g2.setColor(Color.decode("#C0C0C0")); - g2.drawRect(0, 0, getWidth() - 1, getHeight() - 1); - - } - g2.setStroke(dflt); - /* - * PSExport e = new PSExport(); SecStrProducerGraphics export = new - * SecStrProducerGraphics(e); renderRNA(export, getExtendedRNABBox()); - * try { export.saveToDisk("./out.ps"); } catch - * (ExceptionWritingForbidden e1) { e1.printStackTrace(); } - */ - } - - /** - * Draws current RNA structure in a given Graphics "device". - * - * @param g2D - * A graphical device - * @param transparentBackground - * Whether the background should be transparent, or drawn. - */ - public synchronized void renderComponent(VueVARNAGraphics g2D, - boolean transparentBackground, double scaleFactor) { - - updateTitleHeight(); - - if (_debug || _drawBorder) { - g2D.setColor(Color.BLACK); - g2D.setPlainStroke(); - g2D.drawRect(getLeftOffset(), getTopOffset(), getInnerWidth(), - getInnerHeight()); - - } - - - if (!transparentBackground) { - super.setBackground(_conf._backgroundColor); - } else { - super.setBackground(new Color(0, 0, 0, 120)); - } - - // BH 2018 was lt, not lteq here - // SwingJS sets the minimum panel size -- probably incorrectly -- to the size for VARNAPanel - if (getMinimumSize().height <= getSize().height - && getMinimumSize().width <= getSize().width) { - // Draw Title - if (!getTitle().equals("")) { - g2D.setColor(_conf._titleColor); - g2D.setFont(_conf._titleFont); - g2D.drawStringCentered(getTitle(), this.getWidth() / 2, - this.getHeight() - getTitleHeight() / 2.0); - } - // Draw RNA - renderRNA(g2D, getClip(), true, _conf._autoCenter); - } - if (_selectionRectangle != null) { - g2D.setColor(Color.BLACK); - g2D.setSelectionStroke(); - g2D.drawRect(_selectionRectangle.x, _selectionRectangle.y, - _selectionRectangle.width, _selectionRectangle.height); - } - if ((_linkOrigin != null) && (_linkDestination != null)) { - g2D.setColor(_conf._bondColor); - g2D.setPlainStroke(); - g2D.setStrokeThickness(3.0 * scaleFactor); - Point2D.Double linkOrigin = (_linkOrigin); - Point2D.Double linkDestination = (_linkDestination); - g2D.drawLine(linkOrigin.x, linkOrigin.y, linkDestination.x, - linkDestination.y); - for (int i : getSelection().getIndices()) - drawBase(g2D, i, _realCoords, _realCenters, scaleFactor - * _RNA.BASE_RADIUS, scaleFactor, true); - } - - if (_debug) { - g2D.setStrokeThickness(3.0 * scaleFactor); - g2D.setColor(Color.black); - Point2D.Double t = this.logicToPanel(_target); - g2D.drawLine(t.x - 3, t.y - 3, t.x + 3, t.y + 3); - g2D.drawLine(t.x - 3, t.y + 3, t.x + 3, t.y - 3); - g2D.setColor(Color.red); - t = this.logicToPanel(_target2); - g2D.drawLine(t.x - 3, t.y - 3, t.x + 3, t.y + 3); - g2D.drawLine(t.x - 3, t.y + 3, t.x + 3, t.y - 3); - } - } - - public void drawRegionHighlightsAnnotation(VueVARNAGraphics g2D, - Point2D.Double[] realCoords, Point2D.Double[] realCenters, - double scaleFactor) { - g2D.setStrokeThickness(2.0 * scaleFactor); - g2D.setPlainStroke(); - for (HighlightRegionAnnotation r : _RNA.getHighlightRegion()) { - GeneralPath s = r.getShape(realCoords, realCenters, scaleFactor); - g2D.setColor(r.getFillColor()); - g2D.fill(s); - g2D.setColor(r.getOutlineColor()); - g2D.draw(s); - } - } - - private Rectangle2D.Double getClip() { - return new Rectangle2D.Double(getLeftOffset(), getTopOffset(), - this.getInnerWidth(), this.getInnerHeight()); - } - - public Rectangle2D.Double getViewClip() { - return new Rectangle2D.Double(this.getLeftOffset(), - this.getTopOffset(), this.getInnerWidth(), - this.getInnerHeight()); - } - - /** - * Returns the color used to draw backbone bounds. - * - * @return The color used to draw backbone bounds - */ - public Color getBackboneColor() { - return _conf._backboneColor; - } - - /** - * Sets the color to be used for drawing backbone interactions. - * - * @param backbone_color - * The new color for the backbone bounds - */ - public void setBackboneColor(Color backbone_color) { - _conf._backboneColor = backbone_color; - } - - /** - * Returns the color used to display hydrogen bonds (base pairings) - * - * @return The color of hydrogen bonds - */ - public Color getBondColor() { - return _conf._bondColor; - } - - /** - * Returns the title of this panel - * - * @return The title - */ - public String getTitle() { - return _RNA.getName(); - } - - /** - * Sets the new color to be used for hydrogen bonds (base pairings) - * - * @param bond_color - * The new color for hydrogen bonds - */ - public void setDefaultBPColor(Color bond_color) { - _conf._bondColor = bond_color; - } - - /** - * Sets the size of the border, i.e. the empty space between the end of the - * drawing area and the actual border. - * - * @param b - * The new border size - */ - public void setBorderSize(Dimension b) { - _border = b; - } - - /** - * Returns the size of the border, i.e. the empty space between the end of - * the drawing area - * - * @return The border size - */ - public Dimension getBorderSize() { - return _border; - } - - /** - * Sets the RNA to be displayed within this Panel. This method does not use - * a drawing algorithm to reassigns base coordinates, rather assuming that - * the RNA was previously drawn. - * - * @param r - * An already drawn RNA to display in this panel - */ - public synchronized void showRNA(RNA r) { - fireUINewStructure(r); - _RNA = r; - } - - /** - * Sets the RNA secondary structure to be drawn in this panel, using the - * default layout algorithm. In addition to the raw nucleotides sequence, - * the secondary structure is given in the so-called "Dot-bracket notation" - * (DBN) format. This format is a well-parenthesized word over the alphabet - * '(',')','.'.
- * Ex:((((((((....))))..(((((...))).))))))
- * Returns true if the sequence/structure couple could be - * parsed into a valid secondary structure, and false - * otherwise. - * - * @param seq - * The raw nucleotides sequence - * @param str - * The secondary structure - * @throws ExceptionNonEqualLength - */ - public void drawRNA(String seq, String str) throws ExceptionNonEqualLength { - drawRNA(seq, str, _RNA.get_drawMode()); - } - - /** - * Sets the RNA secondary structure to be drawn in this panel, using a given - * layout algorithm. - * - * @param r - * The new secondary structure - * @param drawMode - * The drawing algorithm - */ - public void drawRNA(RNA r, int drawMode) { - r.setDrawMode(drawMode); - drawRNA(r); - } - - /** - * Redraws the current RNA. This reassigns base coordinates to their default - * value using the current drawing algorithm. - */ - - public void drawRNA() { - try { - _RNA.drawRNA(_RNA.get_drawMode(), _conf); - } catch (ExceptionNAViewAlgorithm e) { - errorDialog(e); - e.printStackTrace(); - } - repaint(); - } - - /** - * Sets the RNA secondary structure to be drawn in this panel, using the - * current drawing algorithm. - * - * @param r - * The new secondary structure - */ - public void drawRNA(RNA r) { - if (r != null) { - _RNA = r; - drawRNA(); - } - } - - /** - * Sets the RNA secondary structure to be drawn in this panel, using a given - * layout algorithm. In addition to the raw nucleotides sequence, the - * secondary structure is given in the so-called "Dot-bracket notation" - * (DBN) format. This format is a well-parenthesized word over the alphabet - * '(',')','.'.
- * Ex: ((((((((....))))..(((((...))).))))))
- * Returns true if the sequence/structure couple could be - * parsed into a valid secondary structure, and false - * otherwise. - * - * @param seq - * The raw nucleotides sequence - * @param str - * The secondary structure - * @param drawMode - * The drawing algorithm - * @throws ExceptionNonEqualLength - */ - public void drawRNA(String seq, String str, int drawMode) - throws ExceptionNonEqualLength { - _RNA.setDrawMode(drawMode); - try { - _RNA.setRNA(seq, str); - drawRNA(); - } catch (ExceptionUnmatchedClosingParentheses e) { - errorDialog(e); - } catch (ExceptionFileFormatOrSyntax e1) { - errorDialog(e1); - } - } - - public void drawRNA(Reader r, int drawMode) throws ExceptionNonEqualLength, - ExceptionFileFormatOrSyntax { - _RNA.setDrawMode(drawMode); - Collection rnas = RNAFactory.loadSecStr(r); - if (rnas.isEmpty()) { - throw new ExceptionFileFormatOrSyntax( - "No RNA could be parsed from that source."); - } - _RNA = rnas.iterator().next(); - drawRNA(); - } - - /** - * Draws a secondary structure of RNA using the default drawing algorithm - * and displays it, using an interpolated transition between the previous - * one and the new one. Extra bases, resulting from a size difference - * between the two successive RNAs, are assumed to initiate from the middle - * of the sequence. In other words, both prefixes and suffixes of the RNAs - * are assumed to match, and what remains is an insertion. - * - * @param seq - * Sequence - * @param str - * Structure in dot bracket notation - * @throws ExceptionNonEqualLength - * If len(seq)!=len(str) - */ - public void drawRNAInterpolated(String seq, String str) - throws ExceptionNonEqualLength { - drawRNAInterpolated(seq, str, _RNA.get_drawMode()); - } - - /** - * Draws a secondary structure of RNA using a given algorithm and displays - * it, using an interpolated transition between the previous one and the new - * one. Extra bases, resulting from a size difference between the two - * successive RNAs, are assumed to initiate from the middle of the sequence. - * In other words, both prefixes and suffixes of the RNAs are assumed to - * match, and what remains is an insertion. - * - * @param seq - * Sequence - * @param str - * Structure in dot bracket notation - * @param drawMode - * The drawing algorithm to be used for the initial placement - * @throws ExceptionNonEqualLength - * If len(seq)!=len(str) - */ - public void drawRNAInterpolated(String seq, String str, int drawMode) { - drawRNAInterpolated(seq, str, drawMode, - Mapping.DefaultOutermostMapping(_RNA.get_listeBases().size(), - str.length())); - } - - /** - * Draws a secondary structure of RNA using the default drawing algorithm - * and displays it, using an interpolated transition between the previous - * one and the new one. Here, a mapping between those bases of the new - * structure and the previous one is explicitly provided. - * - * @param seq - * Sequence - * @param str - * Structure in dot bracket notation - * @param m - * A mapping between the currently rendered structure and its - * successor (seq,str) - * @throws ExceptionNonEqualLength - * If len(seq)!=len(str) - */ - public void drawRNAInterpolated(String seq, String str, Mapping m) { - drawRNAInterpolated(seq, str, _RNA.get_drawMode(), m); - } - - /** - * Draws a secondary structure of RNA using a given drawing algorithm and - * displays it, using an interpolated transition between the previous one - * and the new one. Here, a mapping between those bases of the new structure - * and the previous one is provided. - * - * @param seq - * Sequence - * @param str - * Structure in dot bracket notation - * @param drawMode - * The drawing algorithm to be used for the initial placement - * @param m - * A mapping between the currently rendered structure and its - * successor (seq,str) - */ - public void drawRNAInterpolated(String seq, String str, int drawMode, - Mapping m) { - RNA target = new RNA(); - try { - target.setRNA(seq, str); - drawRNAInterpolated(target, drawMode, m); - } catch (ExceptionUnmatchedClosingParentheses e) { - errorDialog(e); - } catch (ExceptionFileFormatOrSyntax e) { - errorDialog(e); - } - } - - /** - * Draws a secondary structure of RNA using the default drawing algorithm - * and displays it, using an interpolated transition between the previous - * one and the new one. Here, a mapping between those bases of the new - * structure and the previous one is explicitly provided. - * - * @param target - * Secondary structure - */ - public void drawRNAInterpolated(RNA target) { - drawRNAInterpolated(target, target.get_drawMode(), - Mapping.DefaultOutermostMapping(_RNA.get_listeBases().size(), - target.getSize())); - } - - /** - * Draws a secondary structure of RNA using the default drawing algorithm - * and displays it, using an interpolated transition between the previous - * one and the new one. Here, a mapping between those bases of the new - * structure and the previous one is explicitly provided. - * - * @param target - * Secondary structure - * @param m - * A mapping between the currently rendered structure and its - * successor (seq,str) - */ - public void drawRNAInterpolated(RNA target, Mapping m) { - drawRNAInterpolated(target, target.get_drawMode(), m); - } - - /** - * Draws a secondary structure of RNA using a given drawing algorithm and - * displays it, using an interpolated transition between the previous one - * and the new one. Here, a mapping between those bases of the new structure - * and the previous one is provided. - * - * @param target - * Secondary structure of RNA - * @param drawMode - * The drawing algorithm to be used for the initial placement - * @param m - * A mapping between the currently rendered structure and its - * successor (seq,str) - */ - public void drawRNAInterpolated(RNA target, int drawMode, Mapping m) { - try { - target.drawRNA(drawMode, _conf); - _conf._drawColorMap = false; - _interpolator.addTarget(target, m); - } catch (ExceptionNAViewAlgorithm e) { - errorDialog(e); - e.printStackTrace(); - } - } - - /** - * Returns the current algorithm used for drawing the structure - * - * @return The current drawing algorithm - */ - public int getDrawMode() { - return this._RNA.getDrawMode(); - } - - public void showRNA(RNA t, VARNAConfig cfg) { - showRNA(t); - if (cfg != null) { - this.setConfig(cfg); - } - repaint(); - } - - /** - * Checks whether an interpolated transition bewteen two RNAs is occurring. - * - * @return True if an interpolated transition is occurring, false otherwise - */ - - public boolean isInterpolationInProgress() { - if (_interpolator == null) { - return false; - } else - return _interpolator.isInterpolationInProgress(); - } - - /** - * Simply displays (does not redraw) a secondary structure , using an - * interpolated transition between the previous one and the new one. A - * default mapping between those bases of the new structure and the previous - * one is used. - * - * @param target - * Secondary structure of RNA - */ - public void showRNAInterpolated(RNA target) { - showRNAInterpolated(target, Mapping.DefaultOutermostMapping(_RNA - .get_listeBases().size(), target.getSize())); - } - - /** - * Simply displays (does not redraw) a secondary structure , using an - * interpolated transition between the previous one and the new one. Here, a - * mapping between bases of the new structure and the previous one is given. - * - * @param target - * Secondary structure of RNA - * @param m - * A mapping between the currently rendered structure and its - * successor (seq,str) - * @throws ExceptionNonEqualLength - * If len(seq)!=len(str) - */ - public void showRNAInterpolated(RNA target, Mapping m) { - showRNAInterpolated(target, null, m); - } - - public void showRNAInterpolated(RNA target, VARNAConfig cfg, Mapping m) { - _interpolator.addTarget(target, cfg, m); - } - - /** - * When comparison mode is ON, sets the two RNA secondary structure to be - * drawn in this panel, using a given layout algorithm. In addition to the - * raw nucleotides sequence, the secondary structure is given in the - * so-called "Dot-bracket notation" (DBN) format. This format is a - * well-parenthesized word over the alphabet '(',')','.'.
- * Ex: ((((((((....))))..(((((...))).))))))
- * - * @param firstSeq - * The first RNA raw nucleotides sequence - * @param firstStruct - * The first RNA secondary structure - * @param secondSeq - * The second RNA raw nucleotides sequence - * @param secondStruct - * The second RNA secondary structure - * @param drawMode - * The drawing algorithm - */ - public void drawRNA(String firstSeq, String firstStruct, String secondSeq, - String secondStruct, int drawMode) { - _RNA.setDrawMode(drawMode); - /** - * Checking the sequences and structures validities... - */ - - // This is a comparison, so the two RNA alignment past in parameters - // must - // have the same sequence and structure length. - if (firstSeq.length() == secondSeq.length() - && firstStruct.length() == secondStruct.length()) { - // First RNA - if (firstSeq.length() != firstStruct.length()) { - if (_conf._showWarnings) { - emitWarning("First sequence length " + firstSeq.length() - + " differs from that of it's secondary structure " - + firstStruct.length() - + ". \nAdapting first sequence length ..."); - } - if (firstSeq.length() < firstStruct.length()) { - while (firstSeq.length() < firstStruct.length()) { - firstSeq += " "; - } - } else { - firstSeq = firstSeq.substring(0, firstStruct.length()); - } - } - - // Second RNA - if (secondSeq.length() != secondStruct.length()) { - if (_conf._showWarnings) { - emitWarning("Second sequence length " + secondSeq.length() - + " differs from that of it's secondary structure " - + secondStruct.length() - + ". \nAdapting second sequence length ..."); - } - if (secondSeq.length() < secondStruct.length()) { - while (secondSeq.length() < secondStruct.length()) { - secondSeq += " "; - } - } else { - secondSeq = secondSeq.substring(0, secondStruct.length()); - } - } - - int RNALength = firstSeq.length(); - String string_superStruct = new String(""); - String string_superSeq = new String(""); - /** - * In this array, we'll have for each indexes of each characters of - * the final super-structure, the RNA number which is own it. - */ - ArrayList array_rnaOwn = new ArrayList(); - - /** - * Generating super-structure sequences and structures... - */ - - firstStruct = firstStruct.replace('-', '.'); - secondStruct = secondStruct.replace('-', '.'); - // First of all, we make the structure - for (int i = 0; i < RNALength; i++) { - // If both characters are the same, so it'll be in the super - // structure - if (firstStruct.charAt(i) == secondStruct.charAt(i)) { - string_superStruct = string_superStruct - + firstStruct.charAt(i); - array_rnaOwn.add(0); - } - // Else if one of the characters is an opening parenthese, so - // it'll be an opening parenthese in the super structure - else if (firstStruct.charAt(i) == '(' - || secondStruct.charAt(i) == '(') { - string_superStruct = string_superStruct + '('; - array_rnaOwn.add((firstStruct.charAt(i) == '(') ? 1 : 2); - } - // Else if one of the characters is a closing parenthese, so - // it'll be a closing parenthese in the super structure - else if (firstStruct.charAt(i) == ')' - || secondStruct.charAt(i) == ')') { - string_superStruct = string_superStruct + ')'; - array_rnaOwn.add((firstStruct.charAt(i) == ')') ? 1 : 2); - } else { - string_superStruct = string_superStruct + '.'; - array_rnaOwn.add(-1); - } - } - - // Next, we make the sequence taking the characters at the same - // index in the first and second sequence - for (int i = 0; i < RNALength; i++) { - string_superSeq = string_superSeq + firstSeq.charAt(i) - + secondSeq.charAt(i); - } - - // Now, we need to create the super-structure RNA with the owning - // bases array - // in order to color bases outer depending on the owning statement - // of each bases. - if (!string_superSeq.equals("") && !string_superStruct.equals("")) { - try { - _RNA.setRNA(string_superSeq, string_superStruct, - array_rnaOwn); - } catch (ExceptionUnmatchedClosingParentheses e) { - errorDialog(e); - } catch (ExceptionFileFormatOrSyntax e) { - errorDialog(e); - } - } else { - emitWarning("ERROR : The super-structure is NULL."); - } - - switch (_RNA.get_drawMode()) { - case RNA.DRAW_MODE_RADIATE: - _RNA.drawRNARadiate(_conf); - break; - case RNA.DRAW_MODE_CIRCULAR: - _RNA.drawRNACircle(_conf); - break; - case RNA.DRAW_MODE_LINEAR: - _RNA.drawRNALine(_conf); - break; - case RNA.DRAW_MODE_NAVIEW: - try { - _RNA.drawRNANAView(_conf); - } catch (ExceptionNAViewAlgorithm e) { - errorDialog(e); - } - break; - default: - break; - } - - } - } - - /** - * Returns the currently selected base index, obtained through a mouse-left - * click - * - * @return Selected base - * - * public int getSelectedBaseIndex() { return _selectedBase; } - * - * /** Returns the currently selected base, obtained through a - * mouse-left click - * - * @return Selected base - * - * public ModeleBase getSelectedBase() { return - * _RNA.get_listeBases().get(_selectedBase); } - * - * /** Sets the selected base index - * - * @param base - * New selected base index - * - * public void setSelectedBase(int base) { _selectedBase = base; - * } - */ - - /** - * Returns the coordinates of the currently displayed RNA - * - * @return Coordinates array - */ - public Point2D.Double[] getRealCoords() { - return _realCoords; - } - - /** - * Sets the coordinates of the currently displayed RNA - * - * @param coords - * New coordinates - */ - public void setRealCoords(Point2D.Double[] coords) { - _realCoords = coords; - } - - /** - * Returns the popup menu used for user mouse iteractions - * - * @return Popup menu - */ - public VueMenu getPopup() { - return _popup; - } - - /** - * Sets the color used to display hydrogen bonds (base pairings) - * - * @param bond_color - * The color of hydrogen bonds - */ - public void setBondColor(Color bond_color) { - _conf._bondColor = bond_color; - } - - /** - * Returns the color used to draw the title - * - * @return The color used to draw the title - */ - public Color getTitleColor() { - return _conf._titleColor; - } - - /** - * Sets the color used to draw the title - * - * @param title_color - * The new color used to draw the title - */ - public void setTitleColor(Color title_color) { - _conf._titleColor = title_color; - } - - /** - * Returns the height taken by the title - * - * @return The height taken by the title - */ - private int getTitleHeight() { - return _titleHeight; - } - - /** - * Sets the height taken by the title - * - * @param title_height - * The height taken by the title - */ - @SuppressWarnings("unused") - private void setTitleHeight(int title_height) { - _titleHeight = title_height; - } - - /** - * Returns the current state of auto centering mode. - * - * @return True if autocentered, false otherwise - */ - public boolean isAutoCentered() { - return _conf._autoCenter; - } - - /** - * Sets the current state of auto centering mode. - * - * @param center - * New auto-centered state - */ - public void setAutoCenter(boolean center) { - _conf._autoCenter = center; - } - - /** - * Returns the font currently used for rendering the title. - * - * @return Current title font - */ - public Font getTitleFont() { - return _conf._titleFont; - } - - /** - * Sets the font used for rendering the title. - * - * @param font - * New title font - */ - public void setTitleFont(Font font) { - _conf._titleFont = font; - updateTitleHeight(); - } - - /** - * For the LINE_MODE drawing algorithm, sets the base pair height increment, - * i.e. the vertical distance between two nested arcs. - * - * @return The current base pair increment - */ - public double getBPHeightIncrement() { - return _RNA._bpHeightIncrement; - } - - /** - * Sets the base pair height increment, i.e. the vertical distance between - * two arcs to be used in LINE_MODE. - * - * @param inc - * New height increment - */ - public void setBPHeightIncrement(double inc) { - _RNA._bpHeightIncrement = inc; - } - - /** - * Returns the shifting of the origin of the Panel in zoom mode - * - * @return The logical coordinate of the top-left panel point - */ - public Point2D.Double getOffsetPanel() { - return _offsetPanel; - } - - /** - * Returns the vector bringing the logical coordinate of left-top-most point - * in the panel to the left-top-most point of the RNA. - * - * @return The logical coordinate of the top-left panel point - */ - private Point2D.Double getRNAOffset() { - return _offsetRNA; - } - - /** - * Returns this panel's UI menu - * - * @return Applet's UI popupmenu - */ - public VueMenu getPopupMenu() { - return _popup; - } - - /** - * Returns the atomic zoom factor step, or increment. - * - * @return Atomic zoom factor increment - */ - public double getZoomIncrement() { - return _conf._zoomAmount; - } - - /** - * Sets the atomic zoom factor step, or increment. - * - * @param amount - * Atomic zoom factor increment - */ - public void setZoomIncrement(Object amount) { - setZoomIncrement(Float.valueOf(amount.toString())); - } - - /** - * Sets the atomic zoom factor step, or increment. - * - * @param amount - * Atomic zoom factor increment - */ - public void setZoomIncrement(double amount) { - _conf._zoomAmount = amount; - } - - /** - * Returns the current zoom factor - * - * @return Current zoom factor - */ - public double getZoom() { - return _conf._zoom; - } - - /** - * Sets the current zoom factor - * - * @param _zoom - * New zoom factor - */ - public void setZoom(Object _zoom) { - double d = Float.valueOf(_zoom.toString()); - if (_conf._zoom != d) { - _conf._zoom = d; - fireZoomLevelChanged(d); - } - } - - /** - * Returns the translation used for zooming in and out - * - * @return A vector describing the translation - */ - public Point getTranslation() { - return _translation; - } - - /** - * Sets the translation used for zooming in and out - * - * @param trans - * A vector describing the new translation - */ - public void setTranslation(Point trans) { - _translation = trans; - checkTranslation(); - fireTranslationChanged(); - } - - /** - * Returns the current RNA model - * - * @return Current RNA model - */ - public RNA getRNA() { - return _RNA; - } - - /** - * Checks whether the drawn RNA is too large to be displayed, allowing for - * shifting mouse interactions. - * - * @return true if the RNA is too large to be displayed, false otherwise - */ - public boolean isOutOfFrame() { - return _horsCadre; - } - - /** - * Pops up an error Dialog displaying an exception in an human-readable way. - * - * @param error - * The exception to display within the Dialog - */ - public void errorDialog(Exception error) { - errorDialog(error, this); - } - - /** - * Pops up an error Dialog displaying an exception in an human-readable way - * if errors are set to be displayed. - * - * @see #setErrorsOn(boolean) - * @param error - * The exception to display within the Dialog - * @param c - * Parent component for the dialog box - */ - public void errorDialog(Exception error, Component c) { - if (isErrorsOn()) { - JOptionPane.showMessageDialog(c, error.getMessage(), "VARNA Error", - JOptionPane.ERROR_MESSAGE); - } - } - - /** - * Pops up an error Dialog displaying an exception in an human-readable way. - * - * @param error - * The exception to display within the Dialog - * @param c - * Parent component for the dialog box - */ - public static void errorDialogStatic(Exception error, Component c) { - if (c != null) { - JOptionPane.showMessageDialog(c, error.getMessage(), - "VARNA Critical Error", JOptionPane.ERROR_MESSAGE); - } else { - System.err.println("Error: " + error.getMessage()); - } - } - - /** - * Displays a warning message through a modal dialog if warnings are set to - * be displayed. - * - * @see #setShowWarnings(boolean) - * @param warning - * A message expliciting the warning - */ - public void emitWarning(String warning) { - if (_conf._showWarnings) - JOptionPane.showMessageDialog(this, warning, "VARNA Warning", - JOptionPane.WARNING_MESSAGE); - } - - public static void emitWarningStatic(Exception e, Component c) { - emitWarningStatic(e.getMessage(), c); - } - - public static void emitWarningStatic(String warning, Component c) { - if (c != null) { - JOptionPane.showMessageDialog(c, warning, "VARNA Warning", - JOptionPane.WARNING_MESSAGE); - } else { - System.err.println("Error: " + warning); - } - } - - /** - * Toggles modifications on and off - * - * @param modifiable - * Modification status - */ - public void setModifiable(boolean modifiable) { - _conf._modifiable = modifiable; - } - - /** - * Returns current modification status - * - * @return current modification status - */ - public boolean isModifiable() { - return _conf._modifiable; - } - - /** - * Resets the visual aspects (Zoom factor, shift) for the Panel. - */ - public void reset() { - this.setBorderSize(new Dimension(0, 0)); - this.setTranslation(new Point(0, (int) (-getTitleHeight() / 2.0))); - this.setZoom(VARNAConfig.DEFAULT_ZOOM); - this.setZoomIncrement(VARNAConfig.DEFAULT_AMOUNT); - } - - /** - * Returns the color used to draw non-standard bases - * - * @return The color used to draw non-standard bases - */ - public Color getNonStandardBasesColor() { - return _conf._specialBasesColor; - } - - /** - * Sets the color used to draw non-standard bases - * - * @param basesColor - * The color used to draw non-standard bases - */ - public void setNonStandardBasesColor(Color basesColor) { - _conf._specialBasesColor = basesColor; - } - - /** - * Checks if the current translation doesn't "kick" the whole RNA out of the - * panel, and corrects the situation if necessary. - */ - public void checkTranslation() { - // verification pour un zoom < 1 - if (this.getZoom() <= 1) { - // verification sortie gauche - if (this.getTranslation().x < -(int) ((this.getWidth() - this - .getInnerWidth()) / 2.0)) { - this.setTranslation(new Point(-(int) ((this.getWidth() - this - .getInnerWidth()) / 2.0), this.getTranslation().y)); - } - // verification sortie droite - if (this.getTranslation().x > (int) ((this.getWidth() - this - .getInnerWidth()) / 2.0)) { - this.setTranslation(new Point((int) ((this.getWidth() - this - .getInnerWidth()) / 2.0), this.getTranslation().y)); - } - // verification sortie bas - if (this.getTranslation().y > (int) ((this.getHeight() - - getTitleHeight() * 2 - this.getInnerHeight()) / 2.0)) { - this.setTranslation(new Point(this.getTranslation().x, - (int) ((this.getHeight() - getTitleHeight() * 2 - this - .getInnerHeight()) / 2.0))); - } - // verification sortie haut - if (this.getTranslation().y < -(int) ((this.getHeight() - this - .getInnerHeight()) / 2.0)) { - this.setTranslation(new Point( - this.getTranslation().x, - -(int) ((this.getHeight() - this.getInnerHeight()) / 2.0))); - } - } else { - // zoom > 1 - Rectangle r2 = getZoomedInTranslationBox(); - int LBoundX = r2.x; - int UBoundX = r2.x + r2.width; - int LBoundY = r2.y; - int UBoundY = r2.y + r2.height; - if (this.getTranslation().x < LBoundX) { - this.setTranslation(new Point(LBoundX, getTranslation().y)); - } else if (this.getTranslation().x > UBoundX) { - this.setTranslation(new Point(UBoundX, getTranslation().y)); - } - if (this.getTranslation().y < LBoundY) { - this.setTranslation(new Point(getTranslation().x, LBoundY)); - } else if (this.getTranslation().y > UBoundY) { - this.setTranslation(new Point(getTranslation().x, UBoundY)); - } - } - } - - public Rectangle getZoomedInTranslationBox() { - int LBoundX = -(int) ((this.getInnerWidth()) / 2.0); - int UBoundX = (int) ((this.getInnerWidth()) / 2.0); - int LBoundY = -(int) ((this.getInnerHeight()) / 2.0); - int UBoundY = (int) ((this.getInnerHeight()) / 2.0); - return new Rectangle(LBoundX, LBoundY, UBoundX - LBoundX, UBoundY - - LBoundY); - - } - - /** - * Returns the "real pixels" x-coordinate of the RNA. - * - * @return X-coordinate of the translation - */ - public int getLeftOffset() { - return _border.width - + ((this.getWidth() - 2 * _border.width) - this.getInnerWidth()) - / 2 + _translation.x; - } - - /** - * Returns the "real pixels" width of the drawing surface for our RNA. - * - * @return Width of the drawing surface for our RNA - */ - public int getInnerWidth() { - // Largeur du dessin - return (int) Math.round((this.getWidth() - 2 * _border.width) - * _conf._zoom); - } - - /** - * Returns the "real pixels" y-coordinate of the RNA. - * - * @return Y-coordinate of the translation - */ - public int getTopOffset() { - return _border.height - + ((this.getHeight() - 2 * _border.height) - this - .getInnerHeight()) / 2 + _translation.y; - } - - /** - * Returns the "real pixels" height of the drawing surface for our RNA. - * - * @return Height of the drawing surface for our RNA - */ - public int getInnerHeight() { - // Hauteur du dessin - return (int) Math.round((this.getHeight()) * _conf._zoom - 2 - * _border.height - getTitleHeight()); - } - - /** - * Checks if the current mode is the "comparison" mode - * - * @return True if comparison, false otherwise - */ - public boolean isComparisonMode() { - return _conf._comparisonMode; - } - - /** - * Rotates the RNA coordinates by a certain angle - * - * @param angleDegres - * Rotation angle, in degrees - */ - public void globalRotation(Double angleDegres) { - _RNA.globalRotation(angleDegres); - fireLayoutChanged(); - repaint(); - } - - /** - * Returns the index of the currently selected base, defaulting to the - * closest base to the last mouse-click. - * - * @return Index of the currently selected base - */ - public Integer getNearestBase() { - return _nearestBase; - } - - /** - * Sets the index of the currently selected base. - * - * @param base - * Index of the new selected base - */ - public void setNearestBase(Integer base) { - _nearestBase = base; - } - - /** - * Returns the color used to draw 'Gaps' bases in comparison mode - * - * @return Color used for 'Gaps' - */ - public Color getGapsBasesColor() { - return _conf._dashBasesColor; - } - - /** - * Sets the color to use for 'Gaps' bases in comparison mode - * - * @param c - * Color used for 'Gaps' - */ - public void setGapsBasesColor(Color c) { - _conf._dashBasesColor = c; - } - - @SuppressWarnings("unused") - private void imprimer() { - // PrintPanel canvas; - // canvas = new PrintPanel(); - PrintRequestAttributeSet attributes; - attributes = new HashPrintRequestAttributeSet(); - try { - PrinterJob job = PrinterJob.getPrinterJob(); - // job.setPrintable(this); - if (job.printDialog(attributes)) { - job.print(attributes); - } - } catch (PrinterException exception) { - errorDialog(exception); - } - } - - /** - * Checks whether errors are to be displayed - * - * @return Error display status - */ - public boolean isErrorsOn() { - return _conf._errorsOn; - } - - /** - * Sets whether errors are to be displayed - * - * @param on - * New error display status - */ - public void setErrorsOn(boolean on) { - _conf._errorsOn = on; - } - - /** - * Returns the view associated with user interactions - * - * @return A view associated with user interactions - */ - public VueUI getVARNAUI() { - return _UI; - } - - /** - * Toggles on/off using base inner color for drawing base-pairs - * - * @param on - * True for using base inner color for drawing base-pairs, false - * for classic mode - */ - public void setUseBaseColorsForBPs(boolean on) { - _conf._useBaseColorsForBPs = on; - } - - /** - * Returns true if current base color is used as inner color for drawing - * base-pairs - * - * @return True for using base inner color for drawing base-pairs, false for - * classic mode - */ - public boolean getUseBaseColorsForBPs() { - return _conf._useBaseColorsForBPs; - } - - /** - * Toggles on/off using a special color used for drawing "non-standard" - * bases - * - * @param on - * True for using a special color used for drawing "non-standard" - * bases, false for classic mode - */ - public void setColorNonStandardBases(boolean on) { - _conf._colorSpecialBases = on; - } - - /** - * Returns true if a special color is used as inner color for non-standard - * base - * - * @return True for using a special color used for drawing "non-standard" - * bases, false for classic mode - */ - public boolean getColorSpecialBases() { - return _conf._colorSpecialBases; - } - - /** - * Toggles on/off using a special color used for drawing "Gaps" bases in - * comparison mode - * - * @param on - * True for using a special color used for drawing "Gaps" bases - * in comparison mode, false for classic mode - */ - public void setColorGapsBases(boolean on) { - _conf._colorDashBases = on; - } - - /** - * Returns true if a special color is used for drawing "Gaps" bases in - * comparison mode - * - * @return True for using a special color used for drawing "Gaps" bases in - * comparison mode, false for classic mode - */ - public boolean getColorGapsBases() { - return _conf._colorDashBases; - } - - /** - * Toggles on/off displaying warnings - * - * @param on - * True to display warnings, false otherwise - */ - public void setShowWarnings(boolean on) { - _conf._showWarnings = on; - } - - /** - * Get current warning display status - * - * @return True to display warnings, false otherwise - */ - public boolean getShowWarnings() { - return _conf._showWarnings; - } - - /** - * Toggles on/off displaying non-canonical base-pairs - * - * @param on - * True to display NC base-pairs, false otherwise - */ - public void setShowNonCanonicalBP(boolean on) { - _conf._drawnNonCanonicalBP = on; - } - - /** - * Return the current display status for non-canonical base-pairs - * - * @return True if NC base-pairs are displayed, false otherwise - */ - public boolean getShowNonCanonicalBP() { - return _conf._drawnNonCanonicalBP; - } - - /** - * Toggles on/off displaying "non-planar" base-pairs - * - * @param on - * True to display "non-planar" base-pairs, false otherwise - */ - public void setShowNonPlanarBP(boolean on) { - _conf._drawnNonPlanarBP = on; - } - - /** - * Return the current display status for non-planar base-pairs - * - * @return True if non-planars base-pairs are displayed, false otherwise - */ - public boolean getShowNonPlanarBP() { - return _conf._drawnNonPlanarBP; - } - - /** - * Sets the base-pair representation style - * - * @param st - * The new base-pair style - */ - public void setBPStyle(VARNAConfig.BP_STYLE st) { - _conf._mainBPStyle = st; - } - - /** - * Returns the base-pair representation style - * - * @return The current base-pair style - */ - public VARNAConfig.BP_STYLE getBPStyle() { - return _conf._mainBPStyle; - } - - /** - * Returns the current VARNA Panel configuration. The returned instance - * should not be modified directly, but rather through the getters/setters - * from the VARNAPanel class. - * - * @return Current configuration - */ - public VARNAConfig getConfig() { - return _conf; - } - - /** - * Sets the background color - * - * @param c - * New background color - */ - public void setBackground(Color c) { - if (_conf != null) { - if (c != null) { - _conf._backgroundColor = c; - _conf._drawBackground = (!c - .equals(VARNAConfig.DEFAULT_BACKGROUND_COLOR)); - } else { - _conf._backgroundColor = VARNAConfig.DEFAULT_BACKGROUND_COLOR; - _conf._drawBackground = false; - } - } - - } - - /** - * Starts highlighting the selected base. - */ - public void highlightSelectedBase(ModeleBase m) { - ArrayList v = new ArrayList(); - int sel = m.getIndex(); - if (sel != -1) { - v.add(sel); - } - setSelection(v); - } - - /** - * Starts highlighting the selected base. - */ - public void highlightSelectedStem(ModeleBase m) { - ArrayList v = new ArrayList(); - int sel = m.getIndex(); - if (sel != -1) { - ArrayList r = _RNA.findStem(sel); - v.addAll(r); - } - setSelection(v); - } - - public BaseList getSelection() { - return _selectedBases; - } - - public ArrayList getSelectionIndices() { - return _selectedBases.getIndices(); - } - - public void setSelection(ArrayList indices) { - setSelection(_RNA.getBasesAt(indices)); - } - - public void setSelection(Collection mbs) { - BaseList bck = new BaseList(_selectedBases); - _selectedBases.clear(); - _selectedBases.addBases(mbs); - _blink.setActive(true); - fireSelectionChanged(bck, _selectedBases); - } - - public ArrayList getBasesInRectangleDiff(Rectangle recIn, - Rectangle recOut) { - ArrayList result = new ArrayList(); - for (int i = 0; i < _realCoords.length; i++) { - if (recIn.contains(_realCoords[i]) - ^ recOut.contains(_realCoords[i])) - result.add(i); - } - return result; - } - - public ArrayList getBasesInRectangle(Rectangle rec) { - ArrayList result = new ArrayList(); - for (int i = 0; i < _realCoords.length; i++) { - if (rec.contains(_realCoords[i])) - result.add(i); - } - return result; - } - - public void setSelectionRectangle(Rectangle rec) { - ArrayList result = new ArrayList(); - if (_selectionRectangle != null) { - result = getBasesInRectangleDiff(_selectionRectangle, rec); - } else { - result = getBasesInRectangle(rec); - } - _selectionRectangle = new Rectangle(rec); - toggleSelection(result); - repaint(); - } - - public void removeSelectionRectangle() { - _selectionRectangle = null; - } - - public void addToSelection(Collection indices) { - for (int i : indices) { - addToSelection(i); - } - } - - public void addToSelection(int i) { - BaseList bck = new BaseList(_selectedBases); - ModeleBase mb = _RNA.getBaseAt(i); - _selectedBases.addBase(mb); - _blink.setActive(true); - fireSelectionChanged(bck, _selectedBases); - } - - public void removeFromSelection(int i) { - BaseList bck = new BaseList(_selectedBases); - ModeleBase mb = _RNA.getBaseAt(i); - _selectedBases.removeBase(mb); - if (_selectedBases.size() == 0) { - _blink.setActive(false); - } else { - _blink.setActive(true); - } - fireSelectionChanged(bck, _selectedBases); - } - - public boolean isInSelection(int i) { - return _selectedBases.contains(_RNA.getBaseAt(i)); - } - - public void toggleSelection(int i) { - if (isInSelection(i)) - removeFromSelection(i); - else - addToSelection(i); - } - - public void toggleSelection(Collection indices) { - for (int i : indices) { - toggleSelection(i); - } - } - - /** - * Stops highlighting bases - */ - public void clearSelection() { - BaseList bck = new BaseList(_selectedBases); - _selectedBases.clear(); - _blink.setActive(false); - repaint(); - fireSelectionChanged(bck, _selectedBases); - } - - public void saveSelection() { - _backupSelection.clear(); - _backupSelection.addAll(_selectedBases.getBases()); - } - - public void restoreSelection() { - setSelection(_backupSelection); - } - - /** - * Stops highlighting bases - */ - public void resetAnnotationHighlight() { - _highlightAnnotation = false; - repaint(); - } - - /** - * Toggles on/off a rectangular outline of the bounding box. - * - * @param on - * True to draw the bounding box, false otherwise - */ - public void drawBBox(boolean on) { - _drawBBox = on; - } - - /** - * Toggles on/off a rectangular outline of the border. - * - * @param on - * True to draw the bounding box, false otherwise - */ - public void drawBorder(boolean on) { - _drawBorder = on; - } - - public void setBaseInnerColor(Color c) { - _RNA.setBaseInnerColor(c); - } - - public void setBaseNumbersColor(Color c) { - _RNA.setBaseNumbersColor(c); - } - - public void setBaseNameColor(Color c) { - _RNA.setBaseNameColor(c); - } - - public void setBaseOutlineColor(Color c) { - _RNA.setBaseOutlineColor(c); - } - - public ArrayList getListeAnnotations() { - return _RNA.getAnnotations(); - } - - public void resetListeAnnotations() { - _RNA.clearAnnotations(); - repaint(); - } - - public void addAnnotation(TextAnnotation textAnnotation) { - _RNA.addAnnotation(textAnnotation); - repaint(); - } - - public boolean removeAnnotation(TextAnnotation textAnnotation) { - boolean done = _RNA.removeAnnotation(textAnnotation); - repaint(); - return done; - } - - public TextAnnotation get_selectedAnnotation() { - return _selectedAnnotation; - } - - public void set_selectedAnnotation(TextAnnotation annotation) { - _selectedAnnotation = annotation; - } - - public void removeSelectedAnnotation() { - _highlightAnnotation = false; - _selectedAnnotation = null; - } - - public void highlightSelectedAnnotation() { - _highlightAnnotation = true; - } - - public boolean getFlatExteriorLoop() { - return _conf._flatExteriorLoop; - } - - public void setFlatExteriorLoop(boolean on) { - _conf._flatExteriorLoop = on; - } - - public void setLastSelectedPosition(Point2D.Double p) { - _lastSelectedCoord.x = p.x; - _lastSelectedCoord.y = p.y; - } - - public Point2D.Double getLastSelectedPosition() { - return _lastSelectedCoord; - } - - public void setSequence(String s) { - _RNA.setSequence(s); - repaint(); - } - - public void setColorMapVisible(boolean b) { - _conf._drawColorMap = b; - repaint(); - } - - public boolean getColorMapVisible() { - return _conf._drawColorMap; - } - - public void removeColorMap() { - _conf._drawColorMap = false; - repaint(); - } - - public void saveSession(String path) { - /* - * FileOutputStream fos = null; ObjectOutputStream out = null; try { fos - * = new FileOutputStream(path); out = new ObjectOutputStream(fos); - * out.writeObject(new FullBackup(_conf, _RNA, _conf._title)); - * out.close(); } catch (Exception ex) { ex.printStackTrace(); } - */ - toXML(path); - } - - public FullBackup loadSession(String path) throws ExceptionLoadingFailed { - return loadSession(new File(path)); +public class VARNAPanel extends JPanel implements PropertyChangeListener +{ + + /** + * SwingJS uses a PropertyChangeEvent to signal that a pseudo-modal dialog has + * been closed. + * + * @param event + */ + @Override + public void propertyChange(PropertyChangeEvent event) + { + Object val = event.getNewValue(); + switch (event.getPropertyName()) + { + case "value": + _UI.onDialogReturn(val == null ? JOptionPane.CLOSED_OPTION + : ((Integer) val).intValue()); + return; + case "SelectedFile": + case "SelectedColor": + case "inputValue": + _UI.onDialogReturn(val); + break; + } + } + + private static final long serialVersionUID = 8194421570308956001L; + + private RNA _RNA = new RNA(); + + private boolean _debug = false; + + private VARNAConfig _conf = new VARNAConfig(); + + private ArrayList _VARNAListeners = new ArrayList<>(); + + private ArrayList _selectionListeners = new ArrayList<>(); + + private ArrayList _RNAListeners = new ArrayList<>(); + + private ArrayList _basesListeners = new ArrayList<>(); + + UndoManager _manager; + + // private boolean _foldMode = true; + + private Point2D.Double[] _realCoords = new Point2D.Double[0]; + + private Point2D.Double[] _realCenters = new Point2D.Double[0]; + + private double _scaleFactor = 1.0; + + private Point2D.Double _offsetPanel = new Point2D.Double(); + + private Point2D.Double _offsetRNA = new Point2D.Double(); + + private double _offX; + + private double _offY; + + private ControleurBlinkingThread _blink; + + private BaseList _selectedBases = new BaseList("selection"); + + private ArrayList _backupSelection = new ArrayList<>(); + + private Integer _nearestBase = null; + + private Point2D.Double _lastSelectedCoord = new Point2D.Double(0.0, 0.0); + + private Point2D.Double _linkOrigin = null; + + private Point2D.Double _linkDestination = null; + + private Rectangle _selectionRectangle = null; + + private boolean _highlightAnnotation = false; + + private int _titleHeight; + + // BH SwingJS issue here is that we are using _border already. Hmm. + private Dimension _border = new Dimension(0, 0); + + private boolean _drawBBox = false; + + private boolean _drawBorder = false; + + // private Point _positionRelativeSouris; + private Point _translation; + + private boolean _horsCadre; + + private boolean _premierAffichage; + + private ControleurInterpolator _interpolator; + + /** + * If comparison mode is TRUE (ON), then the application will be used to + * display a super-structure resulting on an RNA secondary structure + * comparison. Else, the application is used by default. + */ + + private VueMenu _popup = new VueMenu(this); + + private VueUI _UI = new VueUI(this); + + private TextAnnotation _selectedAnnotation; + + /** + * Creates an RNA 2D panel with initially displays the empty structure. + * + * @throws ExceptionNonEqualLength + * + */ + public VARNAPanel() + { + init(); + drawRNA(); + } + + /** + * Creates an RNA 2D panel, and creates and displays an RNA coupled with its + * secondary structure formatted as a well-balanced parenthesis with dots word + * (DBN format). + * + * @param seq + * The raw nucleotide sequence + * @param str + * The secondary structure in DBN format + * @throws ExceptionNonEqualLength + */ + + public VARNAPanel(String seq, String str) throws ExceptionNonEqualLength + { + this(seq, str, RNA.DRAW_MODE_RADIATE); + } + + /** + * Creates a VARNAPanel instance, and creates and displays an RNA coupled with + * its secondary structure formatted as a well-balanced parenthesis with dots + * word (DBN format). Allows the user to choose the drawing algorithm to be + * used. + * + * @param seq + * The raw nucleotide sequence + * @param str + * The secondary structure in DBN format + * @param drawMode + * The drawing mode + * @throws ExceptionNonEqualLength + * @see RNA#DRAW_MODE_RADIATE + * @see RNA#DRAW_MODE_CIRCULAR + * @see RNA#DRAW_MODE_NAVIEW + */ + public VARNAPanel(String seq, String str, int drawMode) + throws ExceptionNonEqualLength + { + this(seq, str, drawMode, ""); + } + + public VARNAPanel(Reader r) + throws ExceptionNonEqualLength, ExceptionFileFormatOrSyntax + { + this(r, RNA.DRAW_MODE_RADIATE); + } + + public VARNAPanel(Reader r, int drawMode) + throws ExceptionNonEqualLength, ExceptionFileFormatOrSyntax + { + this(r, drawMode, ""); + } + + public VARNAPanel(Reader r, int drawMode, String title) + throws ExceptionNonEqualLength, ExceptionFileFormatOrSyntax + { + init(); + drawRNA(r, drawMode); + setTitle(title); + } + + public void setOriginLink(Point2D.Double p) + { + _linkOrigin = (p); + } + + public void setDestinationLink(Point2D.Double p) + { + _linkDestination = (p); + } + + public void removeLink() + { + _linkOrigin = null; + _linkDestination = null; + } + + /** + * Creates a VARNAPanel instance, and displays an RNA. + * + * @param r + * The RNA to be displayed within this panel + */ + + public VARNAPanel(RNA r) + { + showRNA(r); + init(); + } + + /** + * Creates a VARNAPanel instance, and creates and displays an RNA coupled with + * its secondary structure formatted as a well-balanced parenthesis with dots + * word (DBN format). Allows the user to choose the drawing algorithm to be + * used. Additionally, sets the panel's title. + * + * @param seq + * The raw nucleotide sequence + * @param str + * The secondary structure in DBN format + * @param drawMode + * The drawing mode + * @param title + * The panel title + * @throws ExceptionNonEqualLength + * @see RNA#DRAW_MODE_CIRCULAR + * @see RNA#DRAW_MODE_RADIATE + * @see RNA#DRAW_MODE_NAVIEW + */ + + public VARNAPanel(String seq, String str, int drawMode, String title) + throws ExceptionNonEqualLength + { + drawRNA(seq, str, drawMode); + init(); + setTitle(title); + // VARNASecDraw._vp = this; + } + + public VARNAPanel(String seq1, String struct1, String seq2, + String struct2, int drawMode, String title) + { + _conf._comparisonMode = true; + drawRNA(seq1, struct1, seq2, struct2, drawMode); + init(); + setTitle(title); + } + + private void init() + { + _popup.buildPopupMenu(); + // BH 2019.05.16 *add* a popup menu? SwingJS issue here -- actually does ADD + // the menu + // this.add(_popup); + setBackground(VARNAConfig.DEFAULT_BACKGROUND_COLOR); + _manager = new UndoManager(); + _manager.setLimit(10000); + _UI.addUndoableEditListener(_manager); + + _blink = new ControleurBlinkingThread(this, + ControleurBlinkingThread.DEFAULT_FREQUENCY, 0, 1.0, 0.0, 0.2); + _blink.start(); + + _premierAffichage = true; + _translation = new Point(0, 0); + + _horsCadre = false; + this.setFont(_conf._fontBasesGeneral); + + // ajout des controleurs au VARNAPanel + ControleurClicMovement controleurClicMovement = new ControleurClicMovement( + this); + this.addMouseListener(controleurClicMovement); + this.addMouseMotionListener(controleurClicMovement); + this.addMouseWheelListener(new ControleurMolette(this)); + + ControleurDraggedMolette ctrlDraggedMolette = new ControleurDraggedMolette( + this); + this.addMouseMotionListener(ctrlDraggedMolette); + this.addMouseListener(ctrlDraggedMolette); + + ControleurVARNAPanelKeys ctrlKey = new ControleurVARNAPanelKeys(this); + this.addKeyListener(ctrlKey); + this.addFocusListener(ctrlKey); + + _interpolator = new ControleurInterpolator(this); + /** + * + * BH SwingJS do not start this thread + * + * @j2sNative + */ + { + _interpolator.start(); + } + + } + + public void undo() + { + if (_manager.canUndo()) + { + _manager.undo(); + } + } + + public void redo() + { + if (_manager.canRedo()) + { + _manager.redo(); + } + } + + /** + * Sets the new style of the title font. + * + * @param newStyle + * An int that describes the new font style ("PLAIN","BOLD", + * "BOLDITALIC", or "ITALIC") + */ + public void setTitleFontStyle(int newStyle) + { + _conf._titleFont = _conf._titleFont.deriveFont(newStyle); + updateTitleHeight(); + } + + /** + * Sets the new size of the title font. + * + * @param newSize + * The new size of the title font + */ + public void setTitleFontSize(float newSize) + { + // System.err.println("Applying title size "+newSize); + _conf._titleFont = _conf._titleFont.deriveFont(newSize); + updateTitleHeight(); + } + + /** + * Sets the new font family to be used for the title. Available fonts are + * system-specific, yet it seems that "Arial", "Dialog", and "MonoSpaced" are + * almost always available. + * + * @param newFamily + * New font family used for the title + */ + public void setTitleFontFamily(String newFamily) + { + _conf._titleFont = new Font(newFamily, _conf._titleFont.getStyle(), + _conf._titleFont.getSize()); + updateTitleHeight(); + } + + /** + * Sets the color to be used for the title. + * + * @param newColor + * A color used to draw the title + */ + public void setTitleFontColor(Color newColor) + { + _conf._titleColor = newColor; + updateTitleHeight(); + } + + /** + * Sets the font size for displaying bases + * + * @param size + * Font size for base caption + */ + + public void setBaseFontSize(Float size) + { + _conf._fontBasesGeneral = _conf._fontBasesGeneral.deriveFont(size); + } + + /** + * Sets the font size for displaying base numbers + * + * @param size + * Font size for base numbers + */ + + public void setNumbersFontSize(Float size) + { + _conf._numbersFont = _conf._numbersFont.deriveFont(size); + } + + /** + * Sets the font style for displaying bases + * + * @param style + * An int that describes the new font style ("PLAIN","BOLD", + * "BOLDITALIC", or "ITALIC") + */ + + public void setBaseFontStyle(int style) + { + _conf._fontBasesGeneral = _conf._fontBasesGeneral.deriveFont(style); + } + + private void updateTitleHeight() + { + if (!getTitle().equals("")) + { + _titleHeight = (int) (_conf._titleFont.getSize() * 1.5); + } + else + { + _titleHeight = 0; + } + if (Math.abs(this.getZoom() - 1) < .02) + { + _translation.y = (int) (-getTitleHeight() / 2.0); + } + } + + /** + * Sets the panel's title, giving a short description of the RNA secondary + * structure. + * + * @param title + * The new title + */ + public void setTitle(String title) + { + _RNA.setName(title); + updateTitleHeight(); + } + + /** + * Sets the distance between consecutive base numbers. Please notice that : + *
    + *
  • The first and last base are always numbered
  • + *
  • The numbering is based on the base numbers, not on the indices. So base + * numbers may appear more frequently than expected if bases are skipped
  • + *
  • The periodicity is measured starting from 0. This means that for a + * period of 10 and bases numbered from 1 to 52, the base numbers + * [1,10,20,30,40,50,52] will be drawn.
  • + *
+ * + * @param n + * New numbering period + */ + public void setNumPeriod(int n) + { + _conf._numPeriod = n; + } + + /** + * Returns the current numbering period. Please notice that : + *
    + *
  • The first and last base are always numbered
  • + *
  • The numbering is based on the base numbers, not on the indices. So base + * numbers may appear more frequently than expected if bases are skipped
  • + *
  • The periodicity is measured starting from 0. This means that for a + * period of 10 and bases numbered from 1 to 52, the base numbers + * [1,10,20,30,40,50,52] will be drawn.
  • + *
+ * + * @return Current numbering period + */ + public int getNumPeriod() + { + return _conf._numPeriod; + } + + private void setScaleFactor(double d) + { + _scaleFactor = d; + } + + private double getScaleFactor() + { + return _scaleFactor; + } + + private void setAutoFit(boolean fit) + { + _conf._autoFit = fit; + repaint(); + } + + public void lockScrolling() + { + setAutoFit(false); + setAutoCenter(false); + } + + public void unlockScrolling() + { + setAutoFit(true); + setAutoCenter(true); + } + + private void drawStringOutline(VueVARNAGraphics g2D, String res, double x, + double y, double margin) + { + Dimension d = g2D.getStringDimension(res); + x -= d.width / 2.0; + y += d.height / 2.0; + g2D.setColor(Color.GRAY); + g2D.setSelectionStroke(); + g2D.drawRect((x - margin), (y - d.height - margin), + (d.width + 2.0 * margin), (d.height + 2.0 * margin)); + } + + private void drawSymbol(VueVARNAGraphics g2D, double posx, double posy, + double normx, double normy, double radius, boolean isCIS, + ModeleBP.Edge e) + { + Color bck = g2D.getColor(); + switch (e) + { + case WC: + if (isCIS) + { + g2D.setColor(bck); + g2D.fillCircle((posx - (radius) / 2.0), (posy - (radius) / 2.0), + radius); + g2D.drawCircle((posx - (radius) / 2.0), (posy - (radius) / 2.0), + radius); + } + else + { + g2D.setColor(Color.white); + g2D.fillCircle(posx - (radius) / 2.0, (posy - (radius) / 2.0), + (radius)); + g2D.setColor(bck); + g2D.drawCircle((posx - (radius) / 2.0), (posy - (radius) / 2.0), + (radius)); + } + break; + case HOOGSTEEN: + { + GeneralPath p2 = new GeneralPath(); + radius /= 1.05; + p2.moveTo( + (float) (posx - radius * normx / 2.0 - radius * normy / 2.0), + (float) (posy - radius * normy / 2.0 + radius * normx / 2.0)); + p2.lineTo( + (float) (posx + radius * normx / 2.0 - radius * normy / 2.0), + (float) (posy + radius * normy / 2.0 + radius * normx / 2.0)); + p2.lineTo( + (float) (posx + radius * normx / 2.0 + radius * normy / 2.0), + (float) (posy + radius * normy / 2.0 - radius * normx / 2.0)); + p2.lineTo( + (float) (posx - radius * normx / 2.0 + radius * normy / 2.0), + (float) (posy - radius * normy / 2.0 - radius * normx / 2.0)); + p2.closePath(); + + if (isCIS) + { + g2D.setColor(bck); + g2D.fill(p2); + g2D.draw(p2); + } + else + { + g2D.setColor(Color.white); + g2D.fill(p2); + g2D.setColor(bck); + g2D.draw(p2); + } + } + break; + case SUGAR: + { + double ix = radius * normx / 2.0; + double iy = radius * normy / 2.0; + double jx = radius * normy / 2.0; + double jy = -radius * normx / 2.0; + + GeneralPath p2 = new GeneralPath(); + p2.moveTo((float) (posx - ix + jx), (float) (posy - iy + jy)); + p2.lineTo((float) (posx + ix + jx), (float) (posy + iy + jy)); + p2.lineTo((float) (posx - jx), (float) (posy - jy)); + p2.closePath(); + + if (isCIS) + { + g2D.setColor(bck); + g2D.fill(p2); + g2D.draw(p2); + } + else + { + g2D.setColor(Color.white); + g2D.fill(p2); + g2D.setColor(bck); + g2D.draw(p2); + } + } + break; + } + g2D.setColor(bck); + } + + private void drawBasePairArc(VueVARNAGraphics g2D, int i, int j, + Point2D.Double orig, Point2D.Double dest, double scaleFactor, + ModeleBP style, double newRadius) + { + double distance, coef; + if (j - i == 1) + { + coef = getBPHeightIncrement() * 1.75; + } + else + { + coef = getBPHeightIncrement(); + } + distance = dest.x - orig.x; + switch (_conf._mainBPStyle) + { + case LW: + { + double radiusCircle = ((RNA.BASE_PAIR_DISTANCE - _RNA.BASE_RADIUS) + / 5.0) * scaleFactor; + if (style.isCanonical()) + { + if (style.isCanonicalGC()) + { + if ((orig.x != dest.x) || (orig.y != dest.y)) + { + g2D.drawArc((dest.x + orig.x) / 2., + dest.y - scaleFactor * _RNA.BASE_RADIUS / 2.0, + (distance - scaleFactor * _RNA.BASE_RADIUS / 3.0), + (distance * coef + - scaleFactor * _RNA.BASE_RADIUS / 3.0), + 0, 180); + g2D.drawArc((dest.x + orig.x) / 2., + dest.y - scaleFactor * _RNA.BASE_RADIUS / 2.0, + (distance + scaleFactor * _RNA.BASE_RADIUS / 3.0), + (distance * coef + + scaleFactor * _RNA.BASE_RADIUS / 3.0), + 0, 180); + } + } + else if (style.isCanonicalAU()) + { + g2D.drawArc((dest.x + orig.x) / 2., + dest.y - scaleFactor * _RNA.BASE_RADIUS / 2.0, (distance), + (distance * coef), 0, 180); + } + else if (style.isWobbleUG()) + { + Point2D.Double midtop = new Point2D.Double((dest.x + orig.x) / 2., + dest.y - distance * coef / 2. + - scaleFactor * _RNA.BASE_RADIUS / 2.0); + g2D.drawArc(midtop.x, + dest.y - scaleFactor * _RNA.BASE_RADIUS / 2.0, (distance), + (distance * coef), 0, 180); + drawSymbol(g2D, midtop.x, midtop.y, 1., 0., radiusCircle, false, + ModeleBP.Edge.WC); + } + else + { + Point2D.Double midtop = new Point2D.Double((dest.x + orig.x) / 2., + dest.y - distance * coef / 2. + - scaleFactor * _RNA.BASE_RADIUS / 2.0); + g2D.drawArc(midtop.x, + dest.y - scaleFactor * _RNA.BASE_RADIUS / 2.0, (distance), + (distance * coef), 0, 180); + drawSymbol(g2D, midtop.x, midtop.y, 1., 0., radiusCircle, + style.isCIS(), style.getEdgePartner5()); + } + } + else + { + ModeleBP.Edge p1 = style.getEdgePartner5(); + ModeleBP.Edge p2 = style.getEdgePartner3(); + Point2D.Double midtop = new Point2D.Double((dest.x + orig.x) / 2., + dest.y - distance * coef / 2. + - scaleFactor * _RNA.BASE_RADIUS / 2.0); + g2D.drawArc(midtop.x, dest.y - scaleFactor * _RNA.BASE_RADIUS / 2.0, + (distance), (distance * coef), 0, 180); + if (p1 == p2) + { + drawSymbol(g2D, midtop.x, midtop.y, 1., 0., radiusCircle, false, + style.getEdgePartner5()); + } + else + { + drawSymbol(g2D, midtop.x - scaleFactor * _RNA.BASE_RADIUS, + midtop.y, 1., 0., radiusCircle, style.isCIS(), p1); + drawSymbol(g2D, midtop.x + scaleFactor * _RNA.BASE_RADIUS, + midtop.y, -1., 0., radiusCircle, style.isCIS(), p2); + } + } + } + break; + case LW_ALT: + { + double radiusCircle = ((RNA.BASE_PAIR_DISTANCE - _RNA.BASE_RADIUS) + / 5.0) * scaleFactor; + double distFromBaseCenter = DISTANCE_FACT * scaleFactor; + orig = new Point2D.Double(orig.x, + orig.y - (distFromBaseCenter + newRadius)); + dest = new Point2D.Double(dest.x, + dest.y - (distFromBaseCenter + newRadius)); + if (style.isCanonical()) + { + if (style.isCanonicalGC()) + { + if ((orig.x != dest.x) || (orig.y != dest.y)) + { + g2D.drawArc((dest.x + orig.x) / 2., + dest.y - scaleFactor * _RNA.BASE_RADIUS / 2.0, + (distance - scaleFactor * _RNA.BASE_RADIUS / 3.0), + (distance * coef + - scaleFactor * _RNA.BASE_RADIUS / 3.0), + 0, 180); + g2D.drawArc((dest.x + orig.x) / 2., + dest.y - scaleFactor * _RNA.BASE_RADIUS / 2.0, + (distance + scaleFactor * _RNA.BASE_RADIUS / 3.0), + (distance * coef + + scaleFactor * _RNA.BASE_RADIUS / 3.0), + 0, 180); + } + } + else if (style.isCanonicalAU()) + { + g2D.drawArc((dest.x + orig.x) / 2., + dest.y - scaleFactor * _RNA.BASE_RADIUS / 2.0, (distance), + (distance * coef), 0, 180); + } + } + else + { + ModeleBP.Edge p1 = style.getEdgePartner5(); + ModeleBP.Edge p2 = style.getEdgePartner3(); + Point2D.Double midtop = new Point2D.Double((dest.x + orig.x) / 2., + dest.y - distance * coef / 2. + - scaleFactor * _RNA.BASE_RADIUS / 2.0); + g2D.drawArc(midtop.x, dest.y - scaleFactor * _RNA.BASE_RADIUS / 2.0, + (distance), (distance * coef), 0, 180); + drawSymbol(g2D, orig.x, orig.y - radiusCircle * .95, 1., 0., + radiusCircle, style.isCIS(), p1); + drawSymbol(g2D, dest.x, dest.y - radiusCircle * .95, -1., 0., + radiusCircle, style.isCIS(), p2); + } + } + break; + default: + g2D.drawArc((dest.x + orig.x) / 2., + dest.y - scaleFactor * _RNA.BASE_RADIUS / 2.0, (distance), + (distance * coef), 0, 180); + break; + } + + } + + public static double DISTANCE_FACT = 2.; + + private void drawBasePair(VueVARNAGraphics g2D, Point2D.Double orig, + Point2D.Double dest, ModeleBP style, double newRadius, + double scaleFactor) + { + + double dx = dest.x - orig.x; + double dy = dest.y - orig.y; + double dist = Math.sqrt((dest.x - orig.x) * (dest.x - orig.x) + + (dest.y - orig.y) * (dest.y - orig.y)); + dx /= dist; + dy /= dist; + double nx = -dy; + double ny = dx; + orig = new Point2D.Double(orig.x + newRadius * dx, + orig.y + newRadius * dy); + dest = new Point2D.Double(dest.x - newRadius * dx, + dest.y - newRadius * dy); + switch (_conf._mainBPStyle) + { + case LW: + { + double radiusCircle = ((RNA.BASE_PAIR_DISTANCE - _RNA.BASE_RADIUS) + / 5.0) * scaleFactor; + if (style.isCanonical()) + { + if (style.isCanonicalGC()) + { + if ((orig.x != dest.x) || (orig.y != dest.y)) + { + nx *= scaleFactor * _RNA.BASE_RADIUS / 4.0; + ny *= scaleFactor * _RNA.BASE_RADIUS / 4.0; + g2D.drawLine((orig.x + nx), (orig.y + ny), (dest.x + nx), + (dest.y + ny)); + g2D.drawLine((orig.x - nx), (orig.y - ny), (dest.x - nx), + (dest.y - ny)); + } + } + else if (style.isCanonicalAU()) + { + g2D.drawLine(orig.x, orig.y, dest.x, dest.y); + } + else if (style.isWobbleUG()) + { + double cx = (dest.x + orig.x) / 2.0; + double cy = (dest.y + orig.y) / 2.0; + g2D.drawLine(orig.x, orig.y, dest.x, dest.y); + drawSymbol(g2D, cx, cy, nx, ny, radiusCircle, false, + ModeleBP.Edge.WC); + } + else + { + double cx = (dest.x + orig.x) / 2.0; + double cy = (dest.y + orig.y) / 2.0; + g2D.drawLine(orig.x, orig.y, dest.x, dest.y); + drawSymbol(g2D, cx, cy, nx, ny, radiusCircle, style.isCIS(), + style.getEdgePartner5()); + } + } + else + { + ModeleBP.Edge p1 = style.getEdgePartner5(); + ModeleBP.Edge p2 = style.getEdgePartner3(); + double cx = (dest.x + orig.x) / 2.0; + double cy = (dest.y + orig.y) / 2.0; + g2D.drawLine(orig.x, orig.y, dest.x, dest.y); + if (p1 == p2) + { + drawSymbol(g2D, cx, cy, nx, ny, radiusCircle, style.isCIS(), p1); + + } + else + { + double vdx = (dest.x - orig.x); + double vdy = (dest.y - orig.y); + vdx /= 6.0; + vdy /= 6.0; + drawSymbol(g2D, cx + vdx, cy + vdy, -nx, -ny, radiusCircle, + style.isCIS(), p2); + drawSymbol(g2D, cx - vdx, cy - vdy, nx, ny, radiusCircle, + style.isCIS(), p1); + } + } + } + break; + case LW_ALT: + { + double radiusCircle = ((RNA.BASE_PAIR_DISTANCE - _RNA.BASE_RADIUS) + / 5.0) * scaleFactor; + double distFromBaseCenter = DISTANCE_FACT * scaleFactor; + Point2D.Double norig = new Point2D.Double( + orig.x + (distFromBaseCenter + .5 * newRadius) * dx, + orig.y + (distFromBaseCenter + .5 * newRadius) * dy); + Point2D.Double ndest = new Point2D.Double( + dest.x - (distFromBaseCenter + .5 * newRadius) * dx, + dest.y - (distFromBaseCenter + .5 * newRadius) * dy); + if (style.isCanonical()) + { + if (style.isCanonicalGC()) + { + if ((norig.x != ndest.x) || (norig.y != ndest.y)) + { + nx *= scaleFactor * _RNA.BASE_RADIUS / 4.0; + ny *= scaleFactor * _RNA.BASE_RADIUS / 4.0; + g2D.drawLine((norig.x + nx), (norig.y + ny), (ndest.x + nx), + (ndest.y + ny)); + g2D.drawLine((norig.x - nx), (norig.y - ny), (ndest.x - nx), + (ndest.y - ny)); + } + } + else if (style.isCanonicalAU()) + { + g2D.drawLine(norig.x, norig.y, ndest.x, ndest.y); + } + else if (style.isWobbleUG()) + { + double cx = (ndest.x + norig.x) / 2.0; + double cy = (ndest.y + norig.y) / 2.0; + g2D.drawLine(norig.x, norig.y, ndest.x, ndest.y); + drawSymbol(g2D, cx, cy, nx, ny, radiusCircle, false, + ModeleBP.Edge.WC); + } + else + { + double cx = (ndest.x + norig.x) / 2.0; + double cy = (ndest.y + norig.y) / 2.0; + g2D.drawLine(norig.x, norig.y, ndest.x, ndest.y); + drawSymbol(g2D, cx, cy, nx, ny, radiusCircle, style.isCIS(), + style.getEdgePartner5()); + } + } + else + { + ModeleBP.Edge p1 = style.getEdgePartner5(); + ModeleBP.Edge p2 = style.getEdgePartner3(); + double cx = (ndest.x + norig.x) / 2.0; + double cy = (ndest.y + norig.y) / 2.0; + g2D.drawLine(norig.x, norig.y, ndest.x, ndest.y); + if (p1 == p2) + { + drawSymbol(g2D, cx, cy, nx, ny, radiusCircle, style.isCIS(), p1); + + } + else + { + double fac = .4; + drawSymbol(g2D, ndest.x - fac * radiusCircle * dx, + ndest.y - fac * radiusCircle * dy, -nx, -ny, radiusCircle, + style.isCIS(), p2); + drawSymbol(g2D, norig.x + fac * radiusCircle * dx, + norig.y + fac * radiusCircle * dy, nx, ny, radiusCircle, + style.isCIS(), p1); + } + } + } + break; + case SIMPLE: + g2D.drawLine(orig.x, orig.y, dest.x, dest.y); + break; + case RNAVIZ: + double xcenter = (orig.x + dest.x) / 2.0; + double ycenter = (orig.y + dest.y) / 2.0; + double radius = Math.max(4.0 * scaleFactor, 1.0); + g2D.fillCircle((xcenter - radius), (ycenter - radius), + (2.0 * radius)); + break; + case NONE: + break; + } + } + + private Color getHighlightedVersion(Color c1, Color c2) + { + int r1 = c1.getRed(); + int g1 = c1.getGreen(); + int b1 = c1.getBlue(); + int r2 = c2.getRed(); + int g2 = c2.getGreen(); + int b2 = c2.getBlue(); + double val = _blink.getVal(); + int nr = Math.max(0, + Math.min((int) ((r1 * val + r2 * (1.0 - val))), 255)); + int ng = Math.max(0, + Math.min((int) ((g1 * val + g2 * (1.0 - val))), 255)); + int nb = Math.max(0, + Math.min((int) ((b1 * val + b2 * (1.0 - val))), 255)); + return new Color(nr, ng, nb); + } + + private Color highlightFilter(int index, Color initialColor, Color c1, + Color c2, boolean localView) + { + if (_selectedBases.contains(_RNA.getBaseAt(index)) && localView) + { + return getHighlightedVersion(c1, c2); + } + else + { + return initialColor; + } + } + + public static Point2D.Double computeExcentricUnitVector(int i, + Point2D.Double[] points, Point2D.Double[] centers) + { + double dist = points[i].distance(centers[i]); + Point2D.Double byCenter = new Point2D.Double( + (points[i].x - centers[i].x) / dist, + (points[i].y - centers[i].y) / dist); + if ((i > 0) && (i < points.length - 1)) + { + Point2D.Double p0 = points[i - 1]; + Point2D.Double p1 = points[i]; + Point2D.Double p2 = points[i + 1]; + double dist1 = p2.distance(p1); + Point2D.Double v1 = new Point2D.Double((p2.x - p1.x) / dist1, + (p2.y - p1.y) / dist1); + Point2D.Double vn1 = new Point2D.Double(v1.y, -v1.x); + double dist2 = p1.distance(p0); + Point2D.Double v2 = new Point2D.Double((p1.x - p0.x) / dist2, + (p1.y - p0.y) / dist2); + Point2D.Double vn2 = new Point2D.Double(v2.y, -v2.x); + Point2D.Double vn = new Point2D.Double((vn1.x + vn2.x) / 2.0, + (vn1.y + vn2.y) / 2.0); + double D = vn.distance(new Point2D.Double(0.0, 0.0)); + vn.x /= D; + vn.y /= D; + if (byCenter.x * vn.x + byCenter.y * vn.y < 0) + { + vn.x = -vn.x; + vn.y = -vn.y; + } + return vn; + } + else if (((i == 0) || (i == points.length - 1)) && (points.length > 1)) + { + int a = (i == 0) ? 0 : points.length - 1; + int b = (i == 0) ? 1 : points.length - 2; + double D = points[a].distance(points[b]); + return new Point2D.Double((points[a].x - points[b].x) / D, + (points[a].y - points[b].y) / D); + } + else + { + return byCenter; + } + } + + private void drawBase(VueVARNAGraphics g2D, int i, + Point2D.Double[] points, Point2D.Double[] centers, + double newRadius, double _scaleFactor, boolean localView) + { + Point2D.Double p = points[i]; + ModeleBase mb = _RNA.get_listeBases().get(i); + g2D.setFont(_conf._fontBasesGeneral); + Color baseInnerColor = highlightFilter(i, + _RNA.getBaseInnerColor(i, _conf), Color.white, + _RNA.getBaseInnerColor(i, _conf), localView); + Color baseOuterColor = highlightFilter(i, + _RNA.getBaseOuterColor(i, _conf), + _RNA.getBaseOuterColor(i, _conf), Color.white, localView); + Color baseNameColor = highlightFilter(i, + _RNA.getBaseNameColor(i, _conf), + _RNA.getBaseNameColor(i, _conf), Color.white, localView); + if (RNA.whiteLabelPreferrable(baseInnerColor)) + { + baseNameColor = Color.white; + } + + if (mb instanceof ModeleBaseNucleotide) + { + ModeleBaseNucleotide mbn = (ModeleBaseNucleotide) mb; + String res = mbn.getBase(); + if (_hoveredBase == mb && localView && isModifiable()) + { + g2D.setColor(_conf._hoverColor); + g2D.fillCircle(p.getX() - 1.5 * newRadius, + p.getY() - 1.5 * newRadius, 3.0 * newRadius); + g2D.setColor(_conf._hoverColor.darker()); + g2D.drawCircle(p.getX() - 1.5 * newRadius, + p.getY() - 1.5 * newRadius, 3.0 * newRadius); + g2D.setPlainStroke(); + } + if (_conf._fillBases) + { + // Filling inner circle + g2D.setColor(baseInnerColor); + g2D.fillCircle(p.getX() - newRadius, p.getY() - newRadius, + 2.0 * newRadius); + } + + if (_conf._drawOutlineBases) + { + // Drawing outline + g2D.setColor(baseOuterColor); + g2D.setStrokeThickness(_conf._baseThickness * _scaleFactor); + g2D.drawCircle(p.getX() - newRadius, p.getY() - newRadius, + 2.0 * newRadius); + } + // Drawing label + g2D.setColor(baseNameColor); + g2D.drawStringCentered(String.valueOf(res), p.getX(), p.getY()); + } + else if (mb instanceof ModeleBasesComparison) + { + + ModeleBasesComparison mbc = (ModeleBasesComparison) mb; + + // On lui donne l'aspect voulue (on a un trait droit) + g2D.setPlainStroke(); // On doit avoir un trait droit, sans arrondit + g2D.setStrokeThickness(_conf._baseThickness * _scaleFactor); + + // On dessine l'étiquette, rectangle aux bords arrondies. + g2D.setColor(baseInnerColor); + g2D.fillRoundRect((p.getX() - 1.5 * newRadius), + (p.getY() - newRadius), (3.0 * newRadius), (2.0 * newRadius), + 10 * _scaleFactor, 10 * _scaleFactor); + + /* Dessin du rectangle exterieur (bords) */ + g2D.setColor(baseOuterColor); + g2D.drawRoundRect((p.getX() - 1.5 * newRadius), + (p.getY() - newRadius), (3 * newRadius), (2 * newRadius), + 10 * _scaleFactor, 10 * _scaleFactor); + + // On le dessine au centre de l'étiquette. + g2D.drawLine((p.getX()), (p.getY() + newRadius) - 1, (p.getX()), + (p.getY() - newRadius) + 1); + + /* Dessin du nom de la base (A,C,G,U,etc...) */ + // On créer le texte des étiquettes + String label1 = String.valueOf(mbc.getBase1()); + String label2 = String.valueOf(mbc.getBase2()); + + // On leur donne une couleur + g2D.setColor(getRNA().get_listeBases().get(i).getStyleBase() + .getBaseNameColor()); + + // Et on les dessine. + g2D.drawStringCentered(label1, p.getX() - (.75 * newRadius), + p.getY()); + g2D.drawStringCentered(label2, p.getX() + (.75 * newRadius), + p.getY()); + } + + // Drawing base number + if (_RNA.isNumberDrawn(mb, getNumPeriod())) + { + + Point2D.Double vn = computeExcentricUnitVector(i, points, centers); + g2D.setColor(mb.getStyleBase().getBaseNumberColor()); + g2D.setFont(_conf._numbersFont); + double factorMin = Math.min(.5, _conf._distNumbers); + double factorMax = Math.min(_conf._distNumbers - 1.5, + _conf._distNumbers); + g2D.drawLine(p.x + vn.x * ((1 + factorMin) * newRadius), + p.y + vn.y * ((1 + factorMin) * newRadius), + p.x + vn.x * ((1 + factorMax) * newRadius), + p.y + vn.y * ((1 + factorMax) * newRadius)); + g2D.drawStringCentered(mb.getLabel(), + p.x + vn.x * ((1 + _conf._distNumbers) * newRadius), + p.y + vn.y * ((1 + _conf._distNumbers) * newRadius)); + + } + } + + void drawChemProbAnnotation(VueVARNAGraphics g2D, ChemProbAnnotation cpa, + Point2D.Double anchor, double scaleFactor) + { + g2D.setColor(cpa.getColor()); + g2D.setStrokeThickness(RNA.CHEM_PROB_ARROW_THICKNESS * scaleFactor + * cpa.getIntensity()); + g2D.setPlainStroke(); + Point2D.Double v = cpa.getDirVector(); + Point2D.Double vn = cpa.getNormalVector(); + Point2D.Double base = new Point2D.Double( + (anchor.x + _RNA.CHEM_PROB_DIST * scaleFactor * v.x), + (anchor.y + _RNA.CHEM_PROB_DIST * scaleFactor * v.y)); + Point2D.Double edge = new Point2D.Double( + (base.x + _RNA.CHEM_PROB_BASE_LENGTH * cpa.getIntensity() + * scaleFactor * v.x), + (base.y + _RNA.CHEM_PROB_BASE_LENGTH * cpa.getIntensity() + * scaleFactor * v.y)); + switch (cpa.getType()) + { + case ARROW: + { + Point2D.Double arrowTip1 = new Point2D.Double( + (base.x + cpa.getIntensity() * scaleFactor + * (_RNA.CHEM_PROB_ARROW_WIDTH * vn.x + + _RNA.CHEM_PROB_ARROW_HEIGHT * v.x)), + (base.y + cpa.getIntensity() * scaleFactor + * (_RNA.CHEM_PROB_ARROW_WIDTH * vn.y + + _RNA.CHEM_PROB_ARROW_HEIGHT * v.y))); + Point2D.Double arrowTip2 = new Point2D.Double( + (base.x + cpa.getIntensity() * scaleFactor + * (-_RNA.CHEM_PROB_ARROW_WIDTH * vn.x + + _RNA.CHEM_PROB_ARROW_HEIGHT * v.x)), + (base.y + cpa.getIntensity() * scaleFactor + * (-_RNA.CHEM_PROB_ARROW_WIDTH * vn.y + + _RNA.CHEM_PROB_ARROW_HEIGHT * v.y))); + g2D.drawLine(base.x, base.y, edge.x, edge.y); + g2D.drawLine(base.x, base.y, arrowTip1.x, arrowTip1.y); + g2D.drawLine(base.x, base.y, arrowTip2.x, arrowTip2.y); + } + break; + case PIN: + { + Point2D.Double side1 = new Point2D.Double( + (edge.x - cpa.getIntensity() * scaleFactor + * (_RNA.CHEM_PROB_PIN_SEMIDIAG * v.x)), + (edge.y - cpa.getIntensity() * scaleFactor + * (_RNA.CHEM_PROB_PIN_SEMIDIAG * v.y))); + Point2D.Double side2 = new Point2D.Double( + (edge.x - cpa.getIntensity() * scaleFactor + * (_RNA.CHEM_PROB_PIN_SEMIDIAG * vn.x)), + (edge.y - cpa.getIntensity() * scaleFactor + * (_RNA.CHEM_PROB_PIN_SEMIDIAG * vn.y))); + Point2D.Double side3 = new Point2D.Double( + (edge.x + cpa.getIntensity() * scaleFactor + * (_RNA.CHEM_PROB_PIN_SEMIDIAG * v.x)), + (edge.y + cpa.getIntensity() * scaleFactor + * (_RNA.CHEM_PROB_PIN_SEMIDIAG * v.y))); + Point2D.Double side4 = new Point2D.Double( + (edge.x + cpa.getIntensity() * scaleFactor + * (_RNA.CHEM_PROB_PIN_SEMIDIAG * vn.x)), + (edge.y + cpa.getIntensity() * scaleFactor + * (_RNA.CHEM_PROB_PIN_SEMIDIAG * vn.y))); + GeneralPath p2 = new GeneralPath(); + p2.moveTo((float) side1.x, (float) side1.y); + p2.lineTo((float) side2.x, (float) side2.y); + p2.lineTo((float) side3.x, (float) side3.y); + p2.lineTo((float) side4.x, (float) side4.y); + p2.closePath(); + g2D.fill(p2); + g2D.drawLine(base.x, base.y, edge.x, edge.y); + } + break; + case TRIANGLE: + { + Point2D.Double arrowTip1 = new Point2D.Double( + (edge.x + cpa.getIntensity() * scaleFactor + * (_RNA.CHEM_PROB_TRIANGLE_WIDTH * vn.x)), + (edge.y + cpa.getIntensity() * scaleFactor + * (_RNA.CHEM_PROB_TRIANGLE_WIDTH * vn.y))); + Point2D.Double arrowTip2 = new Point2D.Double( + (edge.x + cpa.getIntensity() * scaleFactor + * (-_RNA.CHEM_PROB_TRIANGLE_WIDTH * vn.x)), + (edge.y + cpa.getIntensity() * scaleFactor + * (-_RNA.CHEM_PROB_TRIANGLE_WIDTH * vn.y))); + GeneralPath p2 = new GeneralPath(); + p2.moveTo((float) base.x, (float) base.y); + p2.lineTo((float) arrowTip1.x, (float) arrowTip1.y); + p2.lineTo((float) arrowTip2.x, (float) arrowTip2.y); + p2.closePath(); + g2D.fill(p2); + } + break; + case DOT: + { + Double radius = scaleFactor * _RNA.CHEM_PROB_DOT_RADIUS + * cpa.getIntensity(); + Point2D.Double center = new Point2D.Double((base.x + radius * v.x), + (base.y + radius * v.y)); + g2D.fillCircle((center.x - radius), (center.y - radius), + (2 * radius)); + } + break; + } + } + + Point2D.Double buildCaptionPosition(ModeleBase mb, double scaleFactor, + double heightEstimate) + { + double radius = 2.0; + if (_RNA.isNumberDrawn(mb, getNumPeriod())) + { + radius += _conf._distNumbers; + } + Point2D.Double center = mb.getCenter(); + Point2D.Double p = mb.getCoords(); + double realDistance = _RNA.BASE_RADIUS * radius + heightEstimate; + return new Point2D.Double(center.getX() + (p.getX() - center.getX()) + * ((p.distance(center) + realDistance) / p.distance(center)), + center.getY() + (p.getY() - center.getY()) + * ((p.distance(center) + realDistance) + / p.distance(center))); + } + + private void renderAnnotations(VueVARNAGraphics g2D, double offX, + double offY, double rnaBBoxX, double rnaBBoxY, double scaleFactor) + { + for (TextAnnotation textAnnotation : _RNA.getAnnotations()) + { + g2D.setColor(textAnnotation.getColor()); + g2D.setFont(textAnnotation.getFont().deriveFont((float) (2.0 + * textAnnotation.getFont().getSize() * scaleFactor))); + Point2D.Double position = textAnnotation.getCenterPosition(); + if (textAnnotation.getType() == TextAnnotation.AnchorType.BASE) + { + ModeleBase mb = (ModeleBase) textAnnotation.getAncrage(); + double fontHeight = Math.ceil(textAnnotation.getFont().getSize()); + position = buildCaptionPosition(mb, scaleFactor, fontHeight); + } + position = transformCoord(position, offX, offY, rnaBBoxX, rnaBBoxY, + scaleFactor); + g2D.drawStringCentered(textAnnotation.getTexte(), position.x, + position.y); + if ((_selectedAnnotation == textAnnotation) && (_highlightAnnotation)) + { + drawStringOutline(g2D, textAnnotation.getTexte(), position.x, + position.y, 5); + } + } + for (ChemProbAnnotation cpa : _RNA.getChemProbAnnotations()) + { + Point2D.Double anchor = transformCoord(cpa.getAnchorPosition(), offX, + offY, rnaBBoxX, rnaBBoxY, scaleFactor); + drawChemProbAnnotation(g2D, cpa, anchor, scaleFactor); + } + + } + + public Rectangle2D.Double getExtendedRNABBox() + { + // We get the logical bounding box + Rectangle2D.Double rnabbox = _RNA.getBBox(); + rnabbox.y -= _conf._distNumbers * _RNA.BASE_RADIUS; + rnabbox.height += 2.0 * _conf._distNumbers * _RNA.BASE_RADIUS; + rnabbox.x -= _conf._distNumbers * _RNA.BASE_RADIUS; + rnabbox.width += 2.0 * _conf._distNumbers * _RNA.BASE_RADIUS; + if (_RNA.hasVirtualLoops()) + { + rnabbox.y -= RNA.VIRTUAL_LOOP_RADIUS; + rnabbox.height += 2.0 * RNA.VIRTUAL_LOOP_RADIUS; + rnabbox.x -= RNA.VIRTUAL_LOOP_RADIUS; + rnabbox.width += 2.0 * RNA.VIRTUAL_LOOP_RADIUS; + } + return rnabbox; + } + + public void drawBackbone(VueVARNAGraphics g2D, Point2D.Double[] newCoords, + double newRadius, double _scaleFactor) + { + // Drawing backbone + if (getDrawBackbone()) + { + g2D.setStrokeThickness(1.5 * _scaleFactor); + g2D.setColor(_conf._backboneColor); + + ModeleBackbone bck = _RNA.getBackbone(); + + for (int i = 1; i < _RNA.get_listeBases().size(); i++) + { + Point2D.Double p1 = newCoords[i - 1]; + Point2D.Double p2 = newCoords[i]; + double dist = p1.distance(p2); + int a = _RNA.getBaseAt(i - 1).getElementStructure(); + int b = _RNA.getBaseAt(i).getElementStructure(); + boolean consecutivePair = (a == i) && (b == i - 1); + + if ((dist > 0)) + { + Point2D.Double vbp = new Point2D.Double(); + vbp.x = (p2.x - p1.x) / dist; + vbp.y = (p2.y - p1.y) / dist; + + BackboneType bt = bck.getTypeBefore(i); + if (bt != BackboneType.DISCONTINUOUS_TYPE) + { + if (bt == BackboneType.MISSING_PART_TYPE) + { + g2D.setSelectionStroke(); + } + else + { + g2D.setPlainStroke(); + } + g2D.setColor(bck.getColorBefore(i, _conf._backboneColor)); + + if (consecutivePair + && (_RNA.getDrawMode() != RNA.DRAW_MODE_LINEAR) + && (_RNA.getDrawMode() != RNA.DRAW_MODE_CIRCULAR)) + { + int dir = 0; + if (i + 1 < newCoords.length) + { + dir = (_RNA.testDirectionality(i - 1, i, i + 1) ? -1 : 1); + } + else if (i - 2 >= 0) + { + dir = (_RNA.testDirectionality(i - 2, i - 1, i) ? -1 : 1); + } + Point2D.Double vn = new Point2D.Double(dir * vbp.y, + -dir * vbp.x); + Point2D.Double centerSeg = new Point2D.Double( + (p1.x + p2.x) / 2.0, (p1.y + p2.y) / 2.0); + double distp1CenterSeq = p1.distance(centerSeg); + double centerDist = Math + .sqrt((RNA.VIRTUAL_LOOP_RADIUS * _scaleFactor + * RNA.VIRTUAL_LOOP_RADIUS * _scaleFactor) + - distp1CenterSeq * distp1CenterSeq); + Point2D.Double centerLoop = new Point2D.Double( + centerSeg.x + centerDist * vn.x, + centerSeg.y + centerDist * vn.y); + double radius = centerLoop.distance(p1); + double a1 = 360. * (Math.atan2(-(p1.y - centerLoop.y), + (p1.x - centerLoop.x))) / (2. * Math.PI); + double a2 = 360. * (Math.atan2(-(p2.y - centerLoop.y), + (p2.x - centerLoop.x))) / (2. * Math.PI); + double angle = (a2 - a1); + if (-dir * angle < 0) + { + angle += -dir * 360.; + } + // if (angle<0.) angle += 360.; + // angle = -dir*(360-dir*angle); + g2D.drawArc(centerLoop.x + .8 * newRadius * vn.x, + centerLoop.y + .8 * newRadius * vn.y, 2 * radius, + 2 * radius, a1, angle); + } + else + { + g2D.drawLine((newCoords[i - 1].x + newRadius * vbp.x), + (newCoords[i - 1].y + newRadius * vbp.y), + (newCoords[i].x - newRadius * vbp.x), + (newCoords[i].y - newRadius * vbp.y)); + } + } + } + } + } + } + + public Point2D.Double logicToPanel(Point2D.Double logicPoint) + { + return new Point2D.Double( + _offX + (getScaleFactor() * (logicPoint.x - _offsetRNA.x)), + _offY + (getScaleFactor() * (logicPoint.y - _offsetRNA.y))); + + } + + public Rectangle2D.Double renderRNA(VueVARNAGraphics g2D, + Rectangle2D.Double bbox) + { + return renderRNA(g2D, bbox, false, true); + } + + private double computeScaleFactor(Rectangle2D.Double bbox, + boolean localView, boolean autoCenter) + { + Rectangle2D.Double rnabbox = getExtendedRNABBox(); + double scaleFactor = Math.min( + bbox.width / rnabbox.width, + bbox.height / rnabbox.height); + + // Use it to get an estimate of the font size for numbers ... + float newFontSize = Math.max(1, + (int) ((1.7 * _RNA.BASE_RADIUS) * scaleFactor)); + // ... and increase bounding box accordingly + rnabbox.y -= newFontSize; + rnabbox.height += newFontSize; + if (_conf._drawColorMap) + { + rnabbox.height += getColorMapHeight(); + } + rnabbox.x -= newFontSize; + rnabbox.width += newFontSize; + + // Now, compute the final scaling factor and corresponding font size + scaleFactor = Math.min(bbox.width / rnabbox.width, + bbox.height / rnabbox.height); + if (localView) + { + if (_conf._autoFit) + { + setScaleFactor(scaleFactor); + } + scaleFactor = getScaleFactor(); + } + return scaleFactor; + } + + public synchronized Rectangle2D.Double renderRNA(VueVARNAGraphics g2D, + Rectangle2D.Double bbox, boolean localView, boolean autoCenter) + { + Rectangle2D.Double rnaMultiBox = new Rectangle2D.Double(0, 0, 1, 1); + double scaleFactor = computeScaleFactor(bbox, localView, autoCenter); + float newFontSize = Math.max(1, + (int) ((1.7 * _RNA.BASE_RADIUS) * scaleFactor)); + double newRadius = Math.max(1.0, (scaleFactor * _RNA.BASE_RADIUS)); + setBaseFontSize(newFontSize); + setNumbersFontSize(newFontSize); + double offX = bbox.x; + double offY = bbox.y; + Rectangle2D.Double rnabbox = getExtendedRNABBox(); + + if (_RNA.getSize() != 0) + { + + Point2D.Double offsetRNA = new Point2D.Double(rnabbox.x, rnabbox.y); + + if (autoCenter) + { + offX = (bbox.x + + (bbox.width - Math.round(rnabbox.width * scaleFactor)) + / 2.0); + offY = (bbox.y + + (bbox.height - Math.round(rnabbox.height * scaleFactor)) + / 2.0); + if (localView) + { + _offX = offX; + _offY = offY; + _offsetPanel = new Point2D.Double(_offX, _offY); + _offsetRNA = new Point2D.Double(rnabbox.x, rnabbox.y); + } + } + + if (localView) + { + offX = _offX; + offY = _offY; + offsetRNA = _offsetRNA; + } + + // Re-scaling once and for all + Point2D.Double[] newCoords = new Point2D.Double[_RNA.get_listeBases() + .size()]; + Point2D.Double[] newCenters = new Point2D.Double[_RNA.get_listeBases() + .size()]; + for (int i = 0; i < _RNA.get_listeBases().size(); i++) + { + ModeleBase mb = _RNA.getBaseAt(i); + newCoords[i] = new Point2D.Double( + offX + (scaleFactor * (mb.getCoords().x - offsetRNA.x)), + offY + (scaleFactor * (mb.getCoords().y - offsetRNA.y))); + + Point2D.Double centerBck = _RNA.getCenter(i); + // si la base est dans un angle entre une boucle et une helice + if (_RNA.get_drawMode() == RNA.DRAW_MODE_NAVIEW + || _RNA.get_drawMode() == RNA.DRAW_MODE_RADIATE) + { + if ((mb.getElementStructure() != -1) + && i < _RNA.get_listeBases().size() - 1 && i > 1) + { + ModeleBase b1 = _RNA.get_listeBases().get(i - 1); + ModeleBase b2 = _RNA.get_listeBases().get(i + 1); + int j1 = b1.getElementStructure(); + int j2 = b2.getElementStructure(); + if ((j1 == -1) ^ (j2 == -1)) + { + // alors la position du nombre associé doit etre + Point2D.Double a1 = b1.getCoords(); + Point2D.Double a2 = b2.getCoords(); + Point2D.Double c1 = b1.getCenter(); + Point2D.Double c2 = b2.getCenter(); + + centerBck.x = mb.getCoords().x + + (c1.x - a1.x) / c1.distance(a1) + + (c2.x - a2.x) / c2.distance(a2); + centerBck.y = mb.getCoords().y + + (c1.y - a1.y) / c1.distance(a1) + + (c2.y - a2.y) / c2.distance(a2); + } + } + } + newCenters[i] = new Point2D.Double( + offX + (scaleFactor * (centerBck.x - offsetRNA.x)), + offY + (scaleFactor * (centerBck.y - offsetRNA.y))); + } + // Keep track of coordinates for mouse interactions + if (localView) + { + _realCoords = newCoords; + _realCenters = newCenters; + } + + g2D.setStrokeThickness(1.5 * scaleFactor); + g2D.setPlainStroke(); + g2D.setFont(_conf._fontBasesGeneral); + + // Drawing region highlights Annotation + drawRegionHighlightsAnnotation(g2D, _realCoords, _realCenters, + scaleFactor); + drawBackbone(g2D, newCoords, newRadius, scaleFactor); + + // Drawing base-pairs + // pour chaque base + for (int i = 0; i < _RNA.get_listeBases().size(); i++) + { + int j = _RNA.get_listeBases().get(i).getElementStructure(); + // si c'est une parenthese ouvrante (premiere base du + // couple) + if (j > i) + { + ModeleBP msbp = _RNA.get_listeBases().get(i).getStyleBP(); + // System.err.println(msbp); + if (msbp.isCanonical() || _conf._drawnNonCanonicalBP) + { + if (_RNA.get_drawMode() == RNA.DRAW_MODE_LINEAR) + { + g2D.setStrokeThickness(_RNA.getBasePairThickness(msbp, _conf) + * 2.0 * scaleFactor * _conf._bpThickness); + } + else + { + g2D.setStrokeThickness(_RNA.getBasePairThickness(msbp, _conf) + * 1.5 * scaleFactor); + } + g2D.setColor(_RNA.getBasePairColor(msbp, _conf)); + + if (_RNA.get_drawMode() == RNA.DRAW_MODE_LINEAR) + { + drawBasePairArc(g2D, i, j, newCoords[i], newCoords[j], + scaleFactor, msbp, newRadius); + } + else + { + drawBasePair(g2D, newCoords[i], newCoords[j], msbp, newRadius, + scaleFactor); + } + } + } + } + + // Liaisons additionelles (non planaires) + if (_conf._drawnNonPlanarBP) + { + ArrayList bpaux = _RNA.getStructureAux(); + for (int k = 0; k < bpaux.size(); k++) + { + ModeleBP msbp = bpaux.get(k); + if (msbp.isCanonical() || _conf._drawnNonCanonicalBP) + { + int i = msbp.getPartner5().getIndex(); + int j = msbp.getPartner3().getIndex(); + if (_RNA.get_drawMode() == RNA.DRAW_MODE_LINEAR) + { + g2D.setStrokeThickness(_RNA.getBasePairThickness(msbp, _conf) + * 2.5 * scaleFactor * _conf._bpThickness); + g2D.setPlainStroke(); + } + else + { + g2D.setStrokeThickness(_RNA.getBasePairThickness(msbp, _conf) + * 1.5 * scaleFactor); + g2D.setPlainStroke(); + } + + g2D.setColor(_RNA.getBasePairColor(msbp, _conf)); + if (j > i) + { + if (_RNA.get_drawMode() == RNA.DRAW_MODE_LINEAR) + { + drawBasePairArc(g2D, i, j, newCoords[i], newCoords[j], + scaleFactor, msbp, newRadius); + } + else + { + drawBasePair(g2D, newCoords[i], newCoords[j], msbp, + newRadius, scaleFactor); + } + } + } + } + } + + // Drawing bases + g2D.setPlainStroke(); + for (int i = 0; i < Math.min(_RNA.get_listeBases().size(), + newCoords.length); i++) + { + drawBase(g2D, i, newCoords, newCenters, newRadius, scaleFactor, + localView); + } + + rnaMultiBox = new Rectangle2D.Double(offX, offY, + (scaleFactor * rnabbox.width) - 1, + (scaleFactor * rnabbox.height) - 1); + + if (localView) + { + // Drawing bbox + if (_debug || _drawBBox) + { + g2D.setColor(Color.RED); + g2D.setSelectionStroke(); + g2D.drawRect(rnaMultiBox.x, rnaMultiBox.y, rnaMultiBox.width, + rnaMultiBox.height); + } + + // Draw color map + if (_conf._drawColorMap) + { + drawColorMap(g2D, scaleFactor, rnabbox); } - public FullBackup loadSession(File path) throws ExceptionLoadingFailed { - - FullBackup bck = importSession(path); - Mapping map = Mapping.DefaultOutermostMapping(getRNA().getSize(), - bck.rna.getSize()); - showRNAInterpolated(bck.rna, map); - _conf = bck.config; - repaint(); - return bck; - } - - public static String VARNA_SESSION_EXTENSION = "varna"; - - public static FullBackup importSession(Object path) // BH was String - throws ExceptionLoadingFailed { - try { - FileInputStream fis = (path instanceof File ? new FileInputStream((File) path) : new FileInputStream(path.toString())); - // ZipInputStream zis = new - // ZipInputStream(new BufferedInputStream(fis)); - // zis.getNextEntry(); - FullBackup h = importSession(fis, path.toString()); - // zis.close(); - return h; - } catch (FileNotFoundException e) { - throw (new ExceptionLoadingFailed("File not found.", path.toString())); - } catch (IOException e) { - // TODO Auto-generated catch block - throw (new ExceptionLoadingFailed( - "I/O error while loading session.", path.toString())); - } - } - - public static FullBackup importSession(InputStream fis, String path) - throws ExceptionLoadingFailed { - System.setProperty("javax.xml.parsers.SAXParserFactory", - "com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl"); - SAXParserFactory saxFact = javax.xml.parsers.SAXParserFactory - .newInstance(); - saxFact.setValidating(false); - saxFact.setXIncludeAware(false); - saxFact.setNamespaceAware(false); - try { - SAXParser sp = saxFact.newSAXParser(); - VARNASessionParser sessionData = new VARNASessionParser(); - sp.parse(fis, sessionData); - FullBackup res = new FullBackup(sessionData.getVARNAConfig(), - sessionData.getRNA(), "test"); - return res; - } catch (ParserConfigurationException e) { - throw new ExceptionLoadingFailed("Bad XML parser configuration", - path); - } catch (SAXException e) { - throw new ExceptionLoadingFailed("XML parser Exception", path); - } catch (IOException e) { - throw new ExceptionLoadingFailed("I/O error", path); - } - } - - public void loadFile(File path) { - loadFile(path, false); - } - - public boolean getDrawBackbone() { - return _conf._drawBackbone; - } - - public void setDrawBackbone(boolean b) { - _conf._drawBackbone = b; - } - - public void addHighlightRegion(HighlightRegionAnnotation n) { - _RNA.addHighlightRegion(n); - } - - public void removeHighlightRegion(HighlightRegionAnnotation n) { - _RNA.removeHighlightRegion(n); - } - - public void addHighlightRegion(int i, int j) { - _RNA.addHighlightRegion(i, j); - } - - public void addHighlightRegion(int i, int j, Color fill, Color outline, - double radius) { - _RNA.addHighlightRegion(i, j, fill, outline, radius); - } - - public void loadRNA(String path) { - loadRNA(path, false); - } - - public void loadRNA(Object path, boolean interpolate) { // BH was String - try { - Collection rnas = (path instanceof File ? RNAFactory.loadSecStr(new FileReader((File) path)) : RNAFactory.loadSecStr(path.toString())); - if (rnas.isEmpty()) { - throw new ExceptionFileFormatOrSyntax( - "No RNA could be parsed from that source."); - } - RNA rna = rnas.iterator().next(); - try { - rna.drawRNA(_conf); - } catch (ExceptionNAViewAlgorithm e) { - e.printStackTrace(); - } - if (!interpolate) { - showRNA(rna); - } else { - this.showRNAInterpolated(rna); - } - - } catch (FileNotFoundException e) { - e.printStackTrace(); - } catch (ExceptionFileFormatOrSyntax e) { - e.printStackTrace(); - } catch (Exception e) { - e.printStackTrace(); - } - } - - public void loadFile(File path, boolean interpolate) { // was String BH StringJS - try { - loadSession(path); - } catch (Exception e1) { - loadRNA(path, interpolate); - } - } - - public void setConfig(VARNAConfig cfg) { - _conf = cfg; - } - - public void toggleDrawOutlineBases() { - _conf._drawOutlineBases = !_conf._drawOutlineBases; - } - - public void toggleFillBases() { - _conf._fillBases = !_conf._fillBases; - } - - public void setDrawOutlineBases(boolean drawn) { - _conf._drawOutlineBases = drawn; - } - - public void setFillBases(boolean drawn) { - _conf._fillBases = drawn; - } - - public void readValues(Reader r) { - this._RNA.readValues(r, _conf._cm); - } - - public void addVARNAListener(InterfaceVARNAListener v) { - _VARNAListeners.add(v); - } - - public void fireLayoutChanged() { - for (InterfaceVARNAListener v : _VARNAListeners) { - v.onStructureRedrawn(); - } - } - - public void fireUINewStructure(RNA r) { - for (InterfaceVARNAListener v : _VARNAListeners) { - v.onUINewStructure(_conf, r); - } - } - - public void fireZoomLevelChanged(double d) { - for (InterfaceVARNAListener v : _VARNAListeners) { - v.onZoomLevelChanged(); - } - } - - public void fireTranslationChanged() { - for (InterfaceVARNAListener v2 : _VARNAListeners) { - v2.onTranslationChanged(); - } - } - - public void addSelectionListener(InterfaceVARNASelectionListener v) { - _selectionListeners.add(v); - } - - public void fireSelectionChanged(BaseList mold, BaseList mnew) { - BaseList addedBases = mnew.removeAll(mold); - BaseList removedBases = mold.removeAll(mnew); - for (InterfaceVARNASelectionListener v2 : _selectionListeners) { - v2.onSelectionChanged(mnew, addedBases, removedBases); - } - } - - public void fireHoverChanged(ModeleBase mold, ModeleBase mnew) { - for (InterfaceVARNASelectionListener v2 : _selectionListeners) { - v2.onHoverChanged(mold, mnew); - } - } - - public void addRNAListener(InterfaceVARNARNAListener v) { - _RNAListeners.add(v); - } - - public void addVARNABasesListener(InterfaceVARNABasesListener l) { - _basesListeners.add(l); - } - - public void fireSequenceChanged(int index, String oldseq, String newseq) { - for (InterfaceVARNARNAListener v2 : _RNAListeners) { - v2.onSequenceModified(index, oldseq, newseq); - } - } - - public void fireStructureChanged(Set current, - Set addedBasePairs, Set removedBasePairs) { - for (InterfaceVARNARNAListener v2 : _RNAListeners) { - v2.onStructureModified(current, addedBasePairs, removedBasePairs); - } - } - - public void fireLayoutChanged( - Hashtable movedPositions) { - for (InterfaceVARNARNAListener v2 : _RNAListeners) { - v2.onRNALayoutChanged(movedPositions); - } - } - - public void fireBaseClicked(ModeleBase mb, MouseEvent me) { - if (mb != null) { - for (InterfaceVARNABasesListener v2 : _basesListeners) { - v2.onBaseClicked(mb, me); - } - } - } - - public double getOrientation() { - return _RNA.getOrientation(); - } - - public ModeleBase _hoveredBase = null; - - public void setHoverBase(ModeleBase m) { - if (m != _hoveredBase) { - ModeleBase bck = _hoveredBase; - _hoveredBase = m; - repaint(); - fireHoverChanged(bck, m); - } - } - - public void toXML(String path) { - FileOutputStream fis; - try { - fis = new FileOutputStream(path); - // ZipOutputStream zis = new ZipOutputStream(new - // BufferedOutputStream(fis)); - // ZipEntry entry = new ZipEntry("VARNASession"); - // zis.putNextEntry(entry); - PrintWriter pw = new PrintWriter(fis); - toXML(pw); - pw.flush(); - // zis.closeEntry(); - // zis.close(); - fis.close(); - } catch (FileNotFoundException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - - public void toXML(PrintWriter out) { - try { - - // out = new PrintWriter(System.out); - StreamResult streamResult = new StreamResult(out); - SAXTransformerFactory tf = (SAXTransformerFactory) SAXTransformerFactory - .newInstance(); - // SAX2.0 ContentHandler. - TransformerHandler hd = tf.newTransformerHandler(); - Transformer serializer = hd.getTransformer(); - serializer.setOutputProperty(OutputKeys.ENCODING, "ISO-8859-1"); - serializer - .setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, "users.dtd"); - serializer.setOutputProperty(OutputKeys.INDENT, "yes"); - hd.setResult(streamResult); - hd.startDocument(); - toXML(hd); - hd.endDocument(); - } catch (TransformerConfigurationException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (SAXException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - - } - - public static String XML_ELEMENT_NAME = "VARNASession"; - - public void toXML(TransformerHandler hd) throws SAXException { - AttributesImpl atts = new AttributesImpl(); - hd.startElement("", "", XML_ELEMENT_NAME, atts); - _RNA.toXML(hd); - _conf.toXML(hd); - hd.endElement("", "", XML_ELEMENT_NAME); - } - - public TextAnnotation getNearestAnnotation(int x, int y) { - TextAnnotation t = null; - if (getListeAnnotations().size() != 0) { - double dist = Double.MAX_VALUE; - double d2; - Point2D.Double position; - for (TextAnnotation textAnnot : getListeAnnotations()) { - // calcul de la distance - position = textAnnot.getCenterPosition(); - position = transformCoord(position); - d2 = Math.sqrt(Math.pow((position.x - x), 2) - + Math.pow((position.y - y), 2)); - // si la valeur est inferieur au minimum actuel - if ((dist > d2) - && (d2 < getScaleFactor() - * ControleurClicMovement.MIN_SELECTION_DISTANCE)) { - t = textAnnot; - dist = d2; - } - } - } - return t; - } - - public ModeleBase getNearestBase(int x, int y, boolean always, - boolean onlyPaired) { - int i = getNearestBaseIndex(x, y, always, onlyPaired); - if (i == -1) - return null; - return getRNA().get_listeBases().get(i); - } - - public ModeleBase getNearestBase(int x, int y) { - return getNearestBase(x, y, false, false); - } - - public int getNearestBaseIndex(int x, int y, boolean always, - boolean onlyPaired) { - double d2, dist = Double.MAX_VALUE; - int mb = -1; - for (int i = 0; i < getRealCoords().length; i++) { - if (!onlyPaired - || (getRNA().get_listeBases().get(i).getElementStructure() != -1)) { - d2 = Math.sqrt(Math.pow((getRealCoords()[i].x - x), 2) - + Math.pow((getRealCoords()[i].y - y), 2)); - if ((dist > d2) - && ((d2 < getScaleFactor() - * ControleurClicMovement.MIN_SELECTION_DISTANCE) || always)) { - dist = d2; - mb = i; - } - } - } - return mb; - } - - public void globalRescale(double factor) { - _RNA.rescale(factor); - fireLayoutChanged(); - repaint(); - } - - public void setSpaceBetweenBases(double sp) { - _conf._spaceBetweenBases = sp; - } - - public double getSpaceBetweenBases() { - return _conf._spaceBetweenBases; - } + if (_debug || _drawBBox) + { + g2D.setColor(Color.GRAY); + g2D.setSelectionStroke(); + g2D.drawRect(0, 0, getWidth() - 1, + getHeight() - getTitleHeight() - 1); + } + } + // Draw annotations + renderAnnotations(g2D, offX, offY, offsetRNA.x, offsetRNA.y, + scaleFactor); + // Draw additional debug shape + if (_RNA._debugShape != null) + { + Color c = new Color(255, 0, 0, 50); + g2D.setColor(c); + AffineTransform at = new AffineTransform(); + at.translate(offX - scaleFactor * rnabbox.x, + offY - scaleFactor * rnabbox.y); + at.scale(scaleFactor, scaleFactor); + Shape s = at.createTransformedShape(_RNA._debugShape); + if (s instanceof GeneralPath) + { + g2D.fill((GeneralPath) s); + } + } + } + else + { + g2D.setColor(VARNAConfig.DEFAULT_MESSAGE_COLOR); + g2D.setFont(VARNAConfig.DEFAULT_MESSAGE_FONT); + rnaMultiBox = new Rectangle2D.Double(0, 0, 10, 10); + g2D.drawStringCentered("No RNA here", bbox.getCenterX(), + bbox.getCenterY()); + } + return rnaMultiBox; + } + + public void centerViewOn(double x, double y) + { + Rectangle2D.Double r = _RNA.getBBox(); + _target = new Point2D.Double(x, y); + Point2D.Double q = logicToPanel(_target); + Point p = new Point((int) (-q.x), (int) (-q.y)); + setTranslation(p); + repaint(); + } + + Point2D.Double _target = new Point2D.Double(0, 0); + + Point2D.Double _target2 = new Point2D.Double(0, 0); + + public ModeleBase getBaseAt(Point2D.Double po) + { + ModeleBase mb = null; + Point2D.Double p = panelToLogicPoint(po); + double dist = Double.MAX_VALUE; + for (ModeleBase tmp : _RNA.get_listeBases()) + { + double ndist = tmp.getCoords().distance(p); + if (dist > ndist) + { + mb = tmp; + dist = ndist; + } + } + return mb; + } + + public void setColorMapValues(Double[] values) + { + _RNA.setColorMapValues(values, _conf._cm, true); + _conf._drawColorMap = true; + repaint(); + } + + public void setColorMapMaxValue(double d) + { + _conf._cm.setMaxValue(d); + } + + public void setColorMapMinValue(double d) + { + _conf._cm.setMinValue(d); + } + + public ModeleColorMap getColorMap() + { + return _conf._cm; + } + + public void setColorMap(ModeleColorMap cm) + { + // _RNA.adaptColorMapToValues(cm); + _conf._cm = cm; + repaint(); + } + + public void setColorMapCaption(String caption) + { + _conf._colorMapCaption = caption; + repaint(); + } + + public String getColorMapCaption() + { + return _conf._colorMapCaption; + } + + public void drawColorMap(boolean draw) + { + _conf._drawColorMap = draw; + } + + private double getColorMapHeight() + { + double result = VARNAConfig.DEFAULT_COLOR_MAP_FONT_SIZE + + _conf._colorMapHeight; + if (!_conf._colorMapCaption.equals("")) + { + result += VARNAConfig.DEFAULT_COLOR_MAP_FONT_SIZE; + } + return result; + } + + private void drawColorMap(VueVARNAGraphics g2D, double scaleFactor, + Rectangle2D.Double rnabbox) + { + double v1 = _conf._cm.getMinValue(); + double v2 = _conf._cm.getMaxValue(); + double x, y; + g2D.setPlainStroke(); + + double xSpaceAvail = 0; + double ySpaceAvail = Math.min( + (getHeight() - rnabbox.height * scaleFactor - getTitleHeight()) + / 2.0, + scaleFactor * (_conf._colorMapHeight + + VARNAConfig.DEFAULT_COLOR_MAP_FONT_SIZE)); + if ((int) ySpaceAvail == 0) + { + xSpaceAvail = Math.min((getWidth() - rnabbox.width * scaleFactor) / 2, + scaleFactor * (_conf._colorMapWidth) + + VARNAConfig.DEFAULT_COLOR_MAP_STRIPE_WIDTH); + } + double xBase = (xSpaceAvail + _offX + scaleFactor * (rnabbox.width + - _conf._colorMapWidth - _conf._colorMapXOffset)); + double hcaption = VARNAConfig.DEFAULT_COLOR_MAP_FONT_SIZE; + double yBase = (ySpaceAvail + _offY + scaleFactor * (rnabbox.height + - _conf._colorMapHeight - _conf._colorMapYOffset - hcaption)); + + for (int i = 0; i < _conf._colorMapWidth; i++) + { + double ratio = ((i) / (_conf._colorMapWidth)); + double val = v1 + (v2 - v1) * ratio; + g2D.setColor(_conf._cm.getColorForValue(val)); + x = (xBase + scaleFactor * i); + y = yBase; + g2D.fillRect(x, y, + scaleFactor * VARNAConfig.DEFAULT_COLOR_MAP_STRIPE_WIDTH, + (scaleFactor * _conf._colorMapHeight)); + } + g2D.setColor(VARNAConfig.DEFAULT_COLOR_MAP_OUTLINE); + g2D.drawRect(xBase, yBase, + (VARNAConfig.DEFAULT_COLOR_MAP_STRIPE_WIDTH - 1 + + scaleFactor * _conf._colorMapWidth), + ((scaleFactor * _conf._colorMapHeight))); + g2D.setFont(getFont().deriveFont((float) (scaleFactor + * VARNAConfig.DEFAULT_COLOR_MAP_FONT_SIZE))); + g2D.setColor(VARNAConfig.DEFAULT_COLOR_MAP_FONT_COLOR); + NumberFormat nf = NumberFormat.getInstance(); + nf.setMaximumFractionDigits(2); + nf.setMinimumFractionDigits(0); + g2D.drawStringCentered(nf.format(_conf._cm.getMinValue()), xBase, + yBase + scaleFactor * (_conf._colorMapHeight + + (VARNAConfig.DEFAULT_COLOR_MAP_FONT_SIZE / 1.7))); + g2D.drawStringCentered(nf.format(_conf._cm.getMaxValue()), + xBase + VARNAConfig.DEFAULT_COLOR_MAP_STRIPE_WIDTH + + scaleFactor * _conf._colorMapWidth, + yBase + scaleFactor * (_conf._colorMapHeight + + (VARNAConfig.DEFAULT_COLOR_MAP_FONT_SIZE / 1.7))); + if (!_conf._colorMapCaption.equals("")) + { + g2D.drawStringCentered("" + _conf._colorMapCaption, + xBase + scaleFactor * _conf._colorMapWidth / 2.0, + yBase + scaleFactor + * (VARNAConfig.DEFAULT_COLOR_MAP_FONT_SIZE / 1.7 + + _conf._colorMapHeight)); + } + + } + + public Point2D.Double panelToLogicPoint(Point2D.Double p) + { + return new Point2D.Double( + ((p.x - getOffsetPanel().x) / getScaleFactor()) + + getRNAOffset().x, + ((p.y - getOffsetPanel().y) / getScaleFactor()) + + getRNAOffset().y); + } + + public Point2D.Double transformCoord(Point2D.Double coordDebut, + double offX, double offY, double rnaBBoxX, double rnaBBoxY, + double scaleFactor) + { + return new Point2D.Double( + offX + (scaleFactor * (coordDebut.x - rnaBBoxX)), + offY + (scaleFactor * (coordDebut.y - rnaBBoxY))); + } + + public void eraseSequence() + { + _RNA.eraseSequence(); + } + + public Point2D.Double transformCoord(Point2D.Double coordDebut) + { + Rectangle2D.Double rnabbox = getExtendedRNABBox(); + return new Point2D.Double( + _offX + (getScaleFactor() * (coordDebut.x - rnabbox.x)), + _offY + (getScaleFactor() * (coordDebut.y - rnabbox.y))); + } + + @Override + public void paintComponent(Graphics g) + { + paintComponent(g, false); + } + + public void paintComponent(Graphics g, boolean transparentBackground) + { + if (_premierAffichage) + { + // _border = new Dimension(0, 0); + _translation.x = 0; + _translation.y = (int) (-getTitleHeight() / 2.0); + _premierAffichage = false; + } + + Graphics2D g2 = (Graphics2D) g; + Stroke dflt = g2.getStroke(); + VueVARNAGraphics g2D = new SwingGraphics(g2); + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON); + // BH 2019.05.16 *remove* the popup menu? + // this.removeAll(); + super.paintComponent(g2); + renderComponent(g2D, transparentBackground, getScaleFactor()); + if (isFocusOwner()) + { + g2.setStroke(new BasicStroke(1.5f)); + g2.setColor(Color.decode("#C0C0C0")); + g2.drawRect(0, 0, getWidth() - 1, getHeight() - 1); + + } + g2.setStroke(dflt); + /* + * PSExport e = new PSExport(); SecStrProducerGraphics export = new + * SecStrProducerGraphics(e); renderRNA(export, getExtendedRNABBox()); + * try { export.saveToDisk("./out.ps"); } catch + * (ExceptionWritingForbidden e1) { e1.printStackTrace(); } + */ + } + + /** + * Draws current RNA structure in a given Graphics "device". + * + * @param g2D + * A graphical device + * @param transparentBackground + * Whether the background should be transparent, or drawn. + */ + public synchronized void renderComponent(VueVARNAGraphics g2D, + boolean transparentBackground, double scaleFactor) + { + + updateTitleHeight(); + + if (true || !transparentBackground) + { + g2D.setColor(_conf._backgroundColor); + g2D.fillRect(0, 0, getWidth(), getHeight()); + } + else + { + g2D.setColor(new Color(0, 0, 0, 120)); + // BH SwingJS not allowing this TODO -- fix alpha for background color + // super.setBackground(new Color(0, 0, 0, 120)); + } + + if (_debug || _drawBorder) + { + g2D.setColor(Color.BLACK); + g2D.setPlainStroke(); + g2D.drawRect(getLeftOffset(), getTopOffset(), getInnerWidth(), + getInnerHeight()); + + } + + // if (!transparentBackground) { + // super.setBackground(_conf._backgroundColor); + // } else { + // super.setBackground(new Color(0, 0, 0, 120)); + // } + + if (getMinimumSize().height < getSize().height + && getMinimumSize().width < getSize().width) + { + // Draw Title + if (!getTitle().equals("")) + { + g2D.setColor(_conf._titleColor); + g2D.setFont(_conf._titleFont); + g2D.drawStringCentered(getTitle(), this.getWidth() / 2, + this.getHeight() - getTitleHeight() / 2.0); + } + // Draw RNA + renderRNA(g2D, getClip(), true, _conf._autoCenter); + } + if (_selectionRectangle != null) + { + g2D.setColor(Color.BLACK); + g2D.setSelectionStroke(); + g2D.drawRect(_selectionRectangle.x, _selectionRectangle.y, + _selectionRectangle.width, _selectionRectangle.height); + } + if ((_linkOrigin != null) && (_linkDestination != null)) + { + g2D.setColor(_conf._bondColor); + g2D.setPlainStroke(); + g2D.setStrokeThickness(3.0 * scaleFactor); + Point2D.Double linkOrigin = (_linkOrigin); + Point2D.Double linkDestination = (_linkDestination); + g2D.drawLine(linkOrigin.x, linkOrigin.y, linkDestination.x, + linkDestination.y); + for (int i : getSelection().getIndices()) + { + drawBase(g2D, i, _realCoords, _realCenters, + scaleFactor * _RNA.BASE_RADIUS, scaleFactor, true); + } + } + + if (_debug) + { + g2D.setStrokeThickness(3.0 * scaleFactor); + g2D.setColor(Color.black); + Point2D.Double t = this.logicToPanel(_target); + g2D.drawLine(t.x - 3, t.y - 3, t.x + 3, t.y + 3); + g2D.drawLine(t.x - 3, t.y + 3, t.x + 3, t.y - 3); + g2D.setColor(Color.red); + t = this.logicToPanel(_target2); + g2D.drawLine(t.x - 3, t.y - 3, t.x + 3, t.y + 3); + g2D.drawLine(t.x - 3, t.y + 3, t.x + 3, t.y - 3); + } + } + + public void drawRegionHighlightsAnnotation(VueVARNAGraphics g2D, + Point2D.Double[] realCoords, Point2D.Double[] realCenters, + double scaleFactor) + { + g2D.setStrokeThickness(2.0 * scaleFactor); + g2D.setPlainStroke(); + for (HighlightRegionAnnotation r : _RNA.getHighlightRegion()) + { + GeneralPath s = r.getShape(realCoords, realCenters, scaleFactor); + g2D.setColor(r.getFillColor()); + g2D.fill(s); + g2D.setColor(r.getOutlineColor()); + g2D.draw(s); + } + } + + private Rectangle2D.Double getClip() + { + return new Rectangle2D.Double(getLeftOffset(), getTopOffset(), + this.getInnerWidth(), this.getInnerHeight()); + } + + public Rectangle2D.Double getViewClip() + { + return new Rectangle2D.Double(this.getLeftOffset(), this.getTopOffset(), + this.getInnerWidth(), this.getInnerHeight()); + } + + /** + * Returns the color used to draw backbone bounds. + * + * @return The color used to draw backbone bounds + */ + public Color getBackboneColor() + { + return _conf._backboneColor; + } + + /** + * Sets the color to be used for drawing backbone interactions. + * + * @param backbone_color + * The new color for the backbone bounds + */ + public void setBackboneColor(Color backbone_color) + { + _conf._backboneColor = backbone_color; + } + + /** + * Returns the color used to display hydrogen bonds (base pairings) + * + * @return The color of hydrogen bonds + */ + public Color getBondColor() + { + return _conf._bondColor; + } + + /** + * Returns the title of this panel + * + * @return The title + */ + public String getTitle() + { + return _RNA.getName(); + } + + /** + * Sets the new color to be used for hydrogen bonds (base pairings) + * + * @param bond_color + * The new color for hydrogen bonds + */ + public void setDefaultBPColor(Color bond_color) + { + _conf._bondColor = bond_color; + } + + /** + * Sets the size of the border, i.e. the empty space between the end of the + * drawing area and the actual border. + * + * @param b + * The new border size + */ + public void setBorderSize(Dimension b) + { + _border = b; + } + + /** + * Returns the size of the border, i.e. the empty space between the end of the + * drawing area + * + * @return The border size + */ + public Dimension getBorderSize() + { + return _border; + } + + /** + * Sets the RNA to be displayed within this Panel. This method does not use a + * drawing algorithm to reassigns base coordinates, rather assuming that the + * RNA was previously drawn. + * + * @param r + * An already drawn RNA to display in this panel + */ + public synchronized void showRNA(RNA r) + { + fireUINewStructure(r); + _RNA = r; + } + + /** + * Sets the RNA secondary structure to be drawn in this panel, using the + * default layout algorithm. In addition to the raw nucleotides sequence, the + * secondary structure is given in the so-called "Dot-bracket notation" (DBN) + * format. This format is a well-parenthesized word over the alphabet + * '(',')','.'.
+ * Ex:((((((((....))))..(((((...))).))))))
+ * Returns true if the sequence/structure couple could be parsed + * into a valid secondary structure, and false otherwise. + * + * @param seq + * The raw nucleotides sequence + * @param str + * The secondary structure + * @throws ExceptionNonEqualLength + */ + public void drawRNA(String seq, String str) throws ExceptionNonEqualLength + { + drawRNA(seq, str, _RNA.get_drawMode()); + } + + /** + * Sets the RNA secondary structure to be drawn in this panel, using a given + * layout algorithm. + * + * @param r + * The new secondary structure + * @param drawMode + * The drawing algorithm + */ + public void drawRNA(RNA r, int drawMode) + { + r.setDrawMode(drawMode); + drawRNA(r); + } + + /** + * Redraws the current RNA. This reassigns base coordinates to their default + * value using the current drawing algorithm. + */ + + public void drawRNA() + { + try + { + _RNA.drawRNA(_RNA.get_drawMode(), _conf); + } catch (ExceptionNAViewAlgorithm e) + { + errorDialog(e); + e.printStackTrace(); + } + repaint(); + } + + /** + * Sets the RNA secondary structure to be drawn in this panel, using the + * current drawing algorithm. + * + * @param r + * The new secondary structure + */ + public void drawRNA(RNA r) + { + if (r != null) + { + _RNA = r; + drawRNA(); + } + } + + /** + * Sets the RNA secondary structure to be drawn in this panel, using a given + * layout algorithm. In addition to the raw nucleotides sequence, the + * secondary structure is given in the so-called "Dot-bracket notation" (DBN) + * format. This format is a well-parenthesized word over the alphabet + * '(',')','.'.
+ * Ex: ((((((((....))))..(((((...))).))))))
+ * Returns true if the sequence/structure couple could be parsed + * into a valid secondary structure, and false otherwise. + * + * @param seq + * The raw nucleotides sequence + * @param str + * The secondary structure + * @param drawMode + * The drawing algorithm + * @throws ExceptionNonEqualLength + */ + public void drawRNA(String seq, String str, int drawMode) + throws ExceptionNonEqualLength + { + _RNA.setDrawMode(drawMode); + try + { + _RNA.setRNA(seq, str); + drawRNA(); + } catch (ExceptionUnmatchedClosingParentheses e) + { + errorDialog(e); + } catch (ExceptionFileFormatOrSyntax e1) + { + errorDialog(e1); + } + } + + public void drawRNA(Reader r, int drawMode) + throws ExceptionNonEqualLength, ExceptionFileFormatOrSyntax + { + _RNA.setDrawMode(drawMode); + Collection rnas = RNAFactory.loadSecStr(r); + if (rnas.isEmpty()) + { + throw new ExceptionFileFormatOrSyntax( + "No RNA could be parsed from that source."); + } + _RNA = rnas.iterator().next(); + drawRNA(); + } + + /** + * Draws a secondary structure of RNA using the default drawing algorithm and + * displays it, using an interpolated transition between the previous one and + * the new one. Extra bases, resulting from a size difference between the two + * successive RNAs, are assumed to initiate from the middle of the sequence. + * In other words, both prefixes and suffixes of the RNAs are assumed to + * match, and what remains is an insertion. + * + * @param seq + * Sequence + * @param str + * Structure in dot bracket notation + * @throws ExceptionNonEqualLength + * If len(seq)!=len(str) + */ + public void drawRNAInterpolated(String seq, String str) + throws ExceptionNonEqualLength + { + drawRNAInterpolated(seq, str, _RNA.get_drawMode()); + } + + /** + * Draws a secondary structure of RNA using a given algorithm and displays it, + * using an interpolated transition between the previous one and the new one. + * Extra bases, resulting from a size difference between the two successive + * RNAs, are assumed to initiate from the middle of the sequence. In other + * words, both prefixes and suffixes of the RNAs are assumed to match, and + * what remains is an insertion. + * + * @param seq + * Sequence + * @param str + * Structure in dot bracket notation + * @param drawMode + * The drawing algorithm to be used for the initial placement + * @throws ExceptionNonEqualLength + * If len(seq)!=len(str) + */ + public void drawRNAInterpolated(String seq, String str, int drawMode) + { + drawRNAInterpolated(seq, str, drawMode, Mapping.DefaultOutermostMapping( + _RNA.get_listeBases().size(), str.length())); + } + + /** + * Draws a secondary structure of RNA using the default drawing algorithm and + * displays it, using an interpolated transition between the previous one and + * the new one. Here, a mapping between those bases of the new structure and + * the previous one is explicitly provided. + * + * @param seq + * Sequence + * @param str + * Structure in dot bracket notation + * @param m + * A mapping between the currently rendered structure and its + * successor (seq,str) + * @throws ExceptionNonEqualLength + * If len(seq)!=len(str) + */ + public void drawRNAInterpolated(String seq, String str, Mapping m) + { + drawRNAInterpolated(seq, str, _RNA.get_drawMode(), m); + } + + /** + * Draws a secondary structure of RNA using a given drawing algorithm and + * displays it, using an interpolated transition between the previous one and + * the new one. Here, a mapping between those bases of the new structure and + * the previous one is provided. + * + * @param seq + * Sequence + * @param str + * Structure in dot bracket notation + * @param drawMode + * The drawing algorithm to be used for the initial placement + * @param m + * A mapping between the currently rendered structure and its + * successor (seq,str) + */ + public void drawRNAInterpolated(String seq, String str, int drawMode, + Mapping m) + { + RNA target = new RNA(); + try + { + target.setRNA(seq, str); + drawRNAInterpolated(target, drawMode, m); + } catch (ExceptionUnmatchedClosingParentheses e) + { + errorDialog(e); + } catch (ExceptionFileFormatOrSyntax e) + { + errorDialog(e); + } + } + + /** + * Draws a secondary structure of RNA using the default drawing algorithm and + * displays it, using an interpolated transition between the previous one and + * the new one. Here, a mapping between those bases of the new structure and + * the previous one is explicitly provided. + * + * @param target + * Secondary structure + */ + public void drawRNAInterpolated(RNA target) + { + drawRNAInterpolated(target, target.get_drawMode(), + Mapping.DefaultOutermostMapping(_RNA.get_listeBases().size(), + target.getSize())); + } + + /** + * Draws a secondary structure of RNA using the default drawing algorithm and + * displays it, using an interpolated transition between the previous one and + * the new one. Here, a mapping between those bases of the new structure and + * the previous one is explicitly provided. + * + * @param target + * Secondary structure + * @param m + * A mapping between the currently rendered structure and its + * successor (seq,str) + */ + public void drawRNAInterpolated(RNA target, Mapping m) + { + drawRNAInterpolated(target, target.get_drawMode(), m); + } + + /** + * Draws a secondary structure of RNA using a given drawing algorithm and + * displays it, using an interpolated transition between the previous one and + * the new one. Here, a mapping between those bases of the new structure and + * the previous one is provided. + * + * @param target + * Secondary structure of RNA + * @param drawMode + * The drawing algorithm to be used for the initial placement + * @param m + * A mapping between the currently rendered structure and its + * successor (seq,str) + */ + public void drawRNAInterpolated(RNA target, int drawMode, Mapping m) + { + try + { + target.drawRNA(drawMode, _conf); + _conf._drawColorMap = false; + _interpolator.addTarget(target, m); + } catch (ExceptionNAViewAlgorithm e) + { + errorDialog(e); + e.printStackTrace(); + } + } + + /** + * Returns the current algorithm used for drawing the structure + * + * @return The current drawing algorithm + */ + public int getDrawMode() + { + return this._RNA.getDrawMode(); + } + + public void showRNA(RNA t, VARNAConfig cfg) + { + showRNA(t); + if (cfg != null) + { + this.setConfig(cfg); + } + repaint(); + } + + /** + * Checks whether an interpolated transition bewteen two RNAs is occurring. + * + * @return True if an interpolated transition is occurring, false otherwise + */ + + public boolean isInterpolationInProgress() + { + if (_interpolator == null) + { + return false; + } + else + { + return _interpolator.isInterpolationInProgress(); + } + } + + /** + * Simply displays (does not redraw) a secondary structure , using an + * interpolated transition between the previous one and the new one. A default + * mapping between those bases of the new structure and the previous one is + * used. + * + * @param target + * Secondary structure of RNA + */ + public void showRNAInterpolated(RNA target) + { + showRNAInterpolated(target, Mapping.DefaultOutermostMapping( + _RNA.get_listeBases().size(), target.getSize())); + } + + /** + * Simply displays (does not redraw) a secondary structure , using an + * interpolated transition between the previous one and the new one. Here, a + * mapping between bases of the new structure and the previous one is given. + * + * @param target + * Secondary structure of RNA + * @param m + * A mapping between the currently rendered structure and its + * successor (seq,str) + * @throws ExceptionNonEqualLength + * If len(seq)!=len(str) + */ + public void showRNAInterpolated(RNA target, Mapping m) + { + showRNAInterpolated(target, null, m); + } + + public void showRNAInterpolated(RNA target, VARNAConfig cfg, Mapping m) + { + _interpolator.addTarget(target, cfg, m); + } + + /** + * When comparison mode is ON, sets the two RNA secondary structure to be + * drawn in this panel, using a given layout algorithm. In addition to the raw + * nucleotides sequence, the secondary structure is given in the so-called + * "Dot-bracket notation" (DBN) format. This format is a well-parenthesized + * word over the alphabet '(',')','.'.
+ * Ex: ((((((((....))))..(((((...))).))))))
+ * + * @param firstSeq + * The first RNA raw nucleotides sequence + * @param firstStruct + * The first RNA secondary structure + * @param secondSeq + * The second RNA raw nucleotides sequence + * @param secondStruct + * The second RNA secondary structure + * @param drawMode + * The drawing algorithm + */ + public void drawRNA(String firstSeq, String firstStruct, String secondSeq, + String secondStruct, int drawMode) + { + _RNA.setDrawMode(drawMode); + /** + * Checking the sequences and structures validities... + */ + + // This is a comparison, so the two RNA alignment past in parameters + // must + // have the same sequence and structure length. + if (firstSeq.length() == secondSeq.length() + && firstStruct.length() == secondStruct.length()) + { + // First RNA + if (firstSeq.length() != firstStruct.length()) + { + if (_conf._showWarnings) + { + emitWarning("First sequence length " + firstSeq.length() + + " differs from that of it's secondary structure " + + firstStruct.length() + + ". \nAdapting first sequence length ..."); + } + if (firstSeq.length() < firstStruct.length()) + { + while (firstSeq.length() < firstStruct.length()) + { + firstSeq += " "; + } + } + else + { + firstSeq = firstSeq.substring(0, firstStruct.length()); + } + } + + // Second RNA + if (secondSeq.length() != secondStruct.length()) + { + if (_conf._showWarnings) + { + emitWarning("Second sequence length " + secondSeq.length() + + " differs from that of it's secondary structure " + + secondStruct.length() + + ". \nAdapting second sequence length ..."); + } + if (secondSeq.length() < secondStruct.length()) + { + while (secondSeq.length() < secondStruct.length()) + { + secondSeq += " "; + } + } + else + { + secondSeq = secondSeq.substring(0, secondStruct.length()); + } + } + + int RNALength = firstSeq.length(); + String string_superStruct = new String(""); + String string_superSeq = new String(""); + /** + * In this array, we'll have for each indexes of each characters of the + * final super-structure, the RNA number which is own it. + */ + ArrayList array_rnaOwn = new ArrayList<>(); + + /** + * Generating super-structure sequences and structures... + */ + + firstStruct = firstStruct.replace('-', '.'); + secondStruct = secondStruct.replace('-', '.'); + // First of all, we make the structure + for (int i = 0; i < RNALength; i++) + { + // If both characters are the same, so it'll be in the super + // structure + if (firstStruct.charAt(i) == secondStruct.charAt(i)) + { + string_superStruct = string_superStruct + firstStruct.charAt(i); + array_rnaOwn.add(0); + } + // Else if one of the characters is an opening parenthese, so + // it'll be an opening parenthese in the super structure + else if (firstStruct.charAt(i) == '(' + || secondStruct.charAt(i) == '(') + { + string_superStruct = string_superStruct + '('; + array_rnaOwn.add((firstStruct.charAt(i) == '(') ? 1 : 2); + } + // Else if one of the characters is a closing parenthese, so + // it'll be a closing parenthese in the super structure + else if (firstStruct.charAt(i) == ')' + || secondStruct.charAt(i) == ')') + { + string_superStruct = string_superStruct + ')'; + array_rnaOwn.add((firstStruct.charAt(i) == ')') ? 1 : 2); + } + else + { + string_superStruct = string_superStruct + '.'; + array_rnaOwn.add(-1); + } + } + + // Next, we make the sequence taking the characters at the same + // index in the first and second sequence + for (int i = 0; i < RNALength; i++) + { + string_superSeq = string_superSeq + firstSeq.charAt(i) + + secondSeq.charAt(i); + } + + // Now, we need to create the super-structure RNA with the owning + // bases array + // in order to color bases outer depending on the owning statement + // of each bases. + if (!string_superSeq.equals("") && !string_superStruct.equals("")) + { + try + { + _RNA.setRNA(string_superSeq, string_superStruct, array_rnaOwn); + } catch (ExceptionUnmatchedClosingParentheses e) + { + errorDialog(e); + } catch (ExceptionFileFormatOrSyntax e) + { + errorDialog(e); + } + } + else + { + emitWarning("ERROR : The super-structure is NULL."); + } + + switch (_RNA.get_drawMode()) + { + case RNA.DRAW_MODE_RADIATE: + _RNA.drawRNARadiate(_conf); + break; + case RNA.DRAW_MODE_CIRCULAR: + _RNA.drawRNACircle(_conf); + break; + case RNA.DRAW_MODE_LINEAR: + _RNA.drawRNALine(_conf); + break; + case RNA.DRAW_MODE_NAVIEW: + try + { + _RNA.drawRNANAView(_conf); + } catch (ExceptionNAViewAlgorithm e) + { + errorDialog(e); + } + break; + default: + break; + } + + } + } + + /** + * Returns the currently selected base index, obtained through a mouse-left + * click + * + * @return Selected base + * + * public int getSelectedBaseIndex() { return _selectedBase; } + * + * /** Returns the currently selected base, obtained through a + * mouse-left click + * + * @return Selected base + * + * public ModeleBase getSelectedBase() { return + * _RNA.get_listeBases().get(_selectedBase); } + * + * /** Sets the selected base index + * + * @param base + * New selected base index + * + * public void setSelectedBase(int base) { _selectedBase = base; } + */ + + /** + * Returns the coordinates of the currently displayed RNA + * + * @return Coordinates array + */ + public Point2D.Double[] getRealCoords() + { + return _realCoords; + } + + /** + * Sets the coordinates of the currently displayed RNA + * + * @param coords + * New coordinates + */ + public void setRealCoords(Point2D.Double[] coords) + { + _realCoords = coords; + } + + /** + * Returns the popup menu used for user mouse iteractions + * + * @return Popup menu + */ + public VueMenu getPopup() + { + return _popup; + } + + /** + * Sets the color used to display hydrogen bonds (base pairings) + * + * @param bond_color + * The color of hydrogen bonds + */ + public void setBondColor(Color bond_color) + { + _conf._bondColor = bond_color; + } + + /** + * Returns the color used to draw the title + * + * @return The color used to draw the title + */ + public Color getTitleColor() + { + return _conf._titleColor; + } + + /** + * Sets the color used to draw the title + * + * @param title_color + * The new color used to draw the title + */ + public void setTitleColor(Color title_color) + { + _conf._titleColor = title_color; + } + + /** + * Returns the height taken by the title + * + * @return The height taken by the title + */ + private int getTitleHeight() + { + return _titleHeight; + } + + /** + * Sets the height taken by the title + * + * @param title_height + * The height taken by the title + */ + @SuppressWarnings("unused") + private void setTitleHeight(int title_height) + { + _titleHeight = title_height; + } + + /** + * Returns the current state of auto centering mode. + * + * @return True if autocentered, false otherwise + */ + public boolean isAutoCentered() + { + return _conf._autoCenter; + } + + /** + * Sets the current state of auto centering mode. + * + * @param center + * New auto-centered state + */ + public void setAutoCenter(boolean center) + { + _conf._autoCenter = center; + } + + /** + * Returns the font currently used for rendering the title. + * + * @return Current title font + */ + public Font getTitleFont() + { + return _conf._titleFont; + } + + /** + * Sets the font used for rendering the title. + * + * @param font + * New title font + */ + public void setTitleFont(Font font) + { + _conf._titleFont = font; + updateTitleHeight(); + } + + /** + * For the LINE_MODE drawing algorithm, sets the base pair height increment, + * i.e. the vertical distance between two nested arcs. + * + * @return The current base pair increment + */ + public double getBPHeightIncrement() + { + return _RNA._bpHeightIncrement; + } + + /** + * Sets the base pair height increment, i.e. the vertical distance between two + * arcs to be used in LINE_MODE. + * + * @param inc + * New height increment + */ + public void setBPHeightIncrement(double inc) + { + _RNA._bpHeightIncrement = inc; + } + + /** + * Returns the shifting of the origin of the Panel in zoom mode + * + * @return The logical coordinate of the top-left panel point + */ + public Point2D.Double getOffsetPanel() + { + return _offsetPanel; + } + + /** + * Returns the vector bringing the logical coordinate of left-top-most point + * in the panel to the left-top-most point of the RNA. + * + * @return The logical coordinate of the top-left panel point + */ + private Point2D.Double getRNAOffset() + { + return _offsetRNA; + } + + /** + * Returns this panel's UI menu + * + * @return Applet's UI popupmenu + */ + public VueMenu getPopupMenu() + { + return _popup; + } + + /** + * Returns the atomic zoom factor step, or increment. + * + * @return Atomic zoom factor increment + */ + public double getZoomIncrement() + { + return _conf._zoomAmount; + } + + /** + * Sets the atomic zoom factor step, or increment. + * + * @param amount + * Atomic zoom factor increment + */ + public void setZoomIncrement(Object amount) + { + setZoomIncrement(Float.valueOf(amount.toString())); + } + + /** + * Sets the atomic zoom factor step, or increment. + * + * @param amount + * Atomic zoom factor increment + */ + public void setZoomIncrement(double amount) + { + _conf._zoomAmount = amount; + } + + /** + * Returns the current zoom factor + * + * @return Current zoom factor + */ + public double getZoom() + { + return _conf._zoom; + } + + /** + * Sets the current zoom factor + * + * @param _zoom + * New zoom factor + */ + public void setZoom(Object _zoom) + { + double d = Float.valueOf(_zoom.toString()); + if (_conf._zoom != d) + { + _conf._zoom = d; + fireZoomLevelChanged(d); + } + } + + /** + * Returns the translation used for zooming in and out + * + * @return A vector describing the translation + */ + public Point getTranslation() + { + return _translation; + } + + /** + * Sets the translation used for zooming in and out + * + * @param trans + * A vector describing the new translation + */ + public void setTranslation(Point trans) + { + _translation = trans; + checkTranslation(); + fireTranslationChanged(); + } + + /** + * Returns the current RNA model + * + * @return Current RNA model + */ + public RNA getRNA() + { + return _RNA; + } + + /** + * Checks whether the drawn RNA is too large to be displayed, allowing for + * shifting mouse interactions. + * + * @return true if the RNA is too large to be displayed, false otherwise + */ + public boolean isOutOfFrame() + { + return _horsCadre; + } + + /** + * Pops up an error Dialog displaying an exception in an human-readable way. + * + * @param error + * The exception to display within the Dialog + */ + public void errorDialog(Exception error) + { + errorDialog(error, this); + } + + /** + * Pops up an error Dialog displaying an exception in an human-readable way if + * errors are set to be displayed. + * + * @see #setErrorsOn(boolean) + * @param error + * The exception to display within the Dialog + * @param c + * Parent component for the dialog box + */ + public void errorDialog(Exception error, Component c) + { + if (isErrorsOn()) + { + JOptionPane.showMessageDialog(c, error.getMessage(), "VARNA Error", + JOptionPane.ERROR_MESSAGE); + } + } + + /** + * Pops up an error Dialog displaying an exception in an human-readable way. + * + * @param error + * The exception to display within the Dialog + * @param c + * Parent component for the dialog box + */ + public static void errorDialogStatic(Exception error, Component c) + { + if (c != null) + { + JOptionPane.showMessageDialog(c, error.getMessage(), + "VARNA Critical Error", JOptionPane.ERROR_MESSAGE); + } + else + { + System.err.println("Error: " + error.getMessage()); + } + } + + /** + * Displays a warning message through a modal dialog if warnings are set to be + * displayed. + * + * @see #setShowWarnings(boolean) + * @param warning + * A message expliciting the warning + */ + public void emitWarning(String warning) + { + if (_conf._showWarnings) + { + JOptionPane.showMessageDialog(this, warning, "VARNA Warning", + JOptionPane.WARNING_MESSAGE); + } + } + + public static void emitWarningStatic(Exception e, Component c) + { + emitWarningStatic(e.getMessage(), c); + } + + public static void emitWarningStatic(String warning, Component c) + { + if (c != null) + { + JOptionPane.showMessageDialog(c, warning, "VARNA Warning", + JOptionPane.WARNING_MESSAGE); + } + else + { + System.err.println("Error: " + warning); + } + } + + /** + * Toggles modifications on and off + * + * @param modifiable + * Modification status + */ + public void setModifiable(boolean modifiable) + { + _conf._modifiable = modifiable; + } + + /** + * Returns current modification status + * + * @return current modification status + */ + public boolean isModifiable() + { + return _conf._modifiable; + } + + /** + * Resets the visual aspects (Zoom factor, shift) for the Panel. + */ + public void reset() + { + this.setBorderSize(new Dimension(0, 0)); + this.setTranslation(new Point(0, (int) (-getTitleHeight() / 2.0))); + this.setZoom(VARNAConfig.DEFAULT_ZOOM); + this.setZoomIncrement(VARNAConfig.DEFAULT_AMOUNT); + } + + /** + * Returns the color used to draw non-standard bases + * + * @return The color used to draw non-standard bases + */ + public Color getNonStandardBasesColor() + { + return _conf._specialBasesColor; + } + + /** + * Sets the color used to draw non-standard bases + * + * @param basesColor + * The color used to draw non-standard bases + */ + public void setNonStandardBasesColor(Color basesColor) + { + _conf._specialBasesColor = basesColor; + } + + /** + * Checks if the current translation doesn't "kick" the whole RNA out of the + * panel, and corrects the situation if necessary. + */ + public void checkTranslation() + { + // verification pour un zoom < 1 + if (this.getZoom() <= 1) + { + // verification sortie gauche + if (this.getTranslation().x < -(int) ((this.getWidth() + - this.getInnerWidth()) / 2.0)) + { + this.setTranslation(new Point( + -(int) ((this.getWidth() - this.getInnerWidth()) / 2.0), + this.getTranslation().y)); + } + // verification sortie droite + if (this.getTranslation().x > (int) ((this.getWidth() + - this.getInnerWidth()) / 2.0)) + { + this.setTranslation(new Point( + (int) ((this.getWidth() - this.getInnerWidth()) / 2.0), + this.getTranslation().y)); + } + // verification sortie bas + if (this.getTranslation().y > (int) ((this.getHeight() + - getTitleHeight() * 2 - this.getInnerHeight()) / 2.0)) + { + this.setTranslation(new Point(this.getTranslation().x, + (int) ((this.getHeight() - getTitleHeight() * 2 + - this.getInnerHeight()) / 2.0))); + } + // verification sortie haut + if (this.getTranslation().y < -(int) ((this.getHeight() + - this.getInnerHeight()) / 2.0)) + { + this.setTranslation(new Point(this.getTranslation().x, + -(int) ((this.getHeight() - this.getInnerHeight()) / 2.0))); + } + } + else + { + // zoom > 1 + Rectangle r2 = getZoomedInTranslationBox(); + int LBoundX = r2.x; + int UBoundX = r2.x + r2.width; + int LBoundY = r2.y; + int UBoundY = r2.y + r2.height; + if (this.getTranslation().x < LBoundX) + { + this.setTranslation(new Point(LBoundX, getTranslation().y)); + } + else if (this.getTranslation().x > UBoundX) + { + this.setTranslation(new Point(UBoundX, getTranslation().y)); + } + if (this.getTranslation().y < LBoundY) + { + this.setTranslation(new Point(getTranslation().x, LBoundY)); + } + else if (this.getTranslation().y > UBoundY) + { + this.setTranslation(new Point(getTranslation().x, UBoundY)); + } + } + } + + public Rectangle getZoomedInTranslationBox() + { + int LBoundX = -(int) ((this.getInnerWidth()) / 2.0); + int UBoundX = (int) ((this.getInnerWidth()) / 2.0); + int LBoundY = -(int) ((this.getInnerHeight()) / 2.0); + int UBoundY = (int) ((this.getInnerHeight()) / 2.0); + return new Rectangle(LBoundX, LBoundY, UBoundX - LBoundX, + UBoundY - LBoundY); + + } + + /** + * Returns the "real pixels" x-coordinate of the RNA. + * + * @return X-coordinate of the translation + */ + public int getLeftOffset() + { + return _border.width + ((this.getWidth() - 2 * _border.width) + - this.getInnerWidth()) / 2 + _translation.x; + } + + /** + * Returns the "real pixels" width of the drawing surface for our RNA. + * + * @return Width of the drawing surface for our RNA + */ + public int getInnerWidth() + { + // Largeur du dessin + return (int) Math + .round((this.getWidth() - 2 * _border.width) * _conf._zoom); + } + + /** + * Returns the "real pixels" y-coordinate of the RNA. + * + * @return Y-coordinate of the translation + */ + public int getTopOffset() + { + return _border.height + ((this.getHeight() - 2 * _border.height) + - this.getInnerHeight()) / 2 + _translation.y; + } + + /** + * Returns the "real pixels" height of the drawing surface for our RNA. + * + * @return Height of the drawing surface for our RNA + */ + public int getInnerHeight() + { + // Hauteur du dessin + return (int) Math.round((this.getHeight()) * _conf._zoom + - 2 * _border.height - getTitleHeight()); + } + + /** + * Checks if the current mode is the "comparison" mode + * + * @return True if comparison, false otherwise + */ + public boolean isComparisonMode() + { + return _conf._comparisonMode; + } + + /** + * Rotates the RNA coordinates by a certain angle + * + * @param angleDegres + * Rotation angle, in degrees + */ + public void globalRotation(Double angleDegres) + { + _RNA.globalRotation(angleDegres); + fireLayoutChanged(); + repaint(); + } + + /** + * Returns the index of the currently selected base, defaulting to the closest + * base to the last mouse-click. + * + * @return Index of the currently selected base + */ + public Integer getNearestBase() + { + return _nearestBase; + } + + /** + * Sets the index of the currently selected base. + * + * @param base + * Index of the new selected base + */ + public void setNearestBase(Integer base) + { + _nearestBase = base; + } + + /** + * Returns the color used to draw 'Gaps' bases in comparison mode + * + * @return Color used for 'Gaps' + */ + public Color getGapsBasesColor() + { + return _conf._dashBasesColor; + } + + /** + * Sets the color to use for 'Gaps' bases in comparison mode + * + * @param c + * Color used for 'Gaps' + */ + public void setGapsBasesColor(Color c) + { + _conf._dashBasesColor = c; + } + + @SuppressWarnings("unused") + private void imprimer() + { + // PrintPanel canvas; + // canvas = new PrintPanel(); + PrintRequestAttributeSet attributes; + attributes = new HashPrintRequestAttributeSet(); + try + { + PrinterJob job = PrinterJob.getPrinterJob(); + // job.setPrintable(this); + if (job.printDialog(attributes)) + { + job.print(attributes); + } + } catch (PrinterException exception) + { + errorDialog(exception); + } + } + + /** + * Checks whether errors are to be displayed + * + * @return Error display status + */ + public boolean isErrorsOn() + { + return _conf._errorsOn; + } + + /** + * Sets whether errors are to be displayed + * + * @param on + * New error display status + */ + public void setErrorsOn(boolean on) + { + _conf._errorsOn = on; + } + + /** + * Returns the view associated with user interactions + * + * @return A view associated with user interactions + */ + public VueUI getVARNAUI() + { + return _UI; + } + + /** + * Toggles on/off using base inner color for drawing base-pairs + * + * @param on + * True for using base inner color for drawing base-pairs, false for + * classic mode + */ + public void setUseBaseColorsForBPs(boolean on) + { + _conf._useBaseColorsForBPs = on; + } + + /** + * Returns true if current base color is used as inner color for drawing + * base-pairs + * + * @return True for using base inner color for drawing base-pairs, false for + * classic mode + */ + public boolean getUseBaseColorsForBPs() + { + return _conf._useBaseColorsForBPs; + } + + /** + * Toggles on/off using a special color used for drawing "non-standard" bases + * + * @param on + * True for using a special color used for drawing "non-standard" + * bases, false for classic mode + */ + public void setColorNonStandardBases(boolean on) + { + _conf._colorSpecialBases = on; + } + + /** + * Returns true if a special color is used as inner color for non-standard + * base + * + * @return True for using a special color used for drawing "non-standard" + * bases, false for classic mode + */ + public boolean getColorSpecialBases() + { + return _conf._colorSpecialBases; + } + + /** + * Toggles on/off using a special color used for drawing "Gaps" bases in + * comparison mode + * + * @param on + * True for using a special color used for drawing "Gaps" bases in + * comparison mode, false for classic mode + */ + public void setColorGapsBases(boolean on) + { + _conf._colorDashBases = on; + } + + /** + * Returns true if a special color is used for drawing "Gaps" bases in + * comparison mode + * + * @return True for using a special color used for drawing "Gaps" bases in + * comparison mode, false for classic mode + */ + public boolean getColorGapsBases() + { + return _conf._colorDashBases; + } + + /** + * Toggles on/off displaying warnings + * + * @param on + * True to display warnings, false otherwise + */ + public void setShowWarnings(boolean on) + { + _conf._showWarnings = on; + } + + /** + * Get current warning display status + * + * @return True to display warnings, false otherwise + */ + public boolean getShowWarnings() + { + return _conf._showWarnings; + } + + /** + * Toggles on/off displaying non-canonical base-pairs + * + * @param on + * True to display NC base-pairs, false otherwise + */ + public void setShowNonCanonicalBP(boolean on) + { + _conf._drawnNonCanonicalBP = on; + } + + /** + * Return the current display status for non-canonical base-pairs + * + * @return True if NC base-pairs are displayed, false otherwise + */ + public boolean getShowNonCanonicalBP() + { + return _conf._drawnNonCanonicalBP; + } + + /** + * Toggles on/off displaying "non-planar" base-pairs + * + * @param on + * True to display "non-planar" base-pairs, false otherwise + */ + public void setShowNonPlanarBP(boolean on) + { + _conf._drawnNonPlanarBP = on; + } + + /** + * Return the current display status for non-planar base-pairs + * + * @return True if non-planars base-pairs are displayed, false otherwise + */ + public boolean getShowNonPlanarBP() + { + return _conf._drawnNonPlanarBP; + } + + /** + * Sets the base-pair representation style + * + * @param st + * The new base-pair style + */ + public void setBPStyle(VARNAConfig.BP_STYLE st) + { + _conf._mainBPStyle = st; + } + + /** + * Returns the base-pair representation style + * + * @return The current base-pair style + */ + public VARNAConfig.BP_STYLE getBPStyle() + { + return _conf._mainBPStyle; + } + + /** + * Returns the current VARNA Panel configuration. The returned instance should + * not be modified directly, but rather through the getters/setters from the + * VARNAPanel class. + * + * @return Current configuration + */ + public VARNAConfig getConfig() + { + return _conf; + } + + /** + * Sets the background color + * + * @param c + * New background color + */ + @Override + public void setBackground(Color c) + { + if (_conf != null) + { + if (c != null) + { + _conf._backgroundColor = c; + _conf._drawBackground = (!c + .equals(VARNAConfig.DEFAULT_BACKGROUND_COLOR)); + } + else + { + _conf._backgroundColor = VARNAConfig.DEFAULT_BACKGROUND_COLOR; + _conf._drawBackground = false; + } + } + + } + + /** + * Starts highlighting the selected base. + */ + public void highlightSelectedBase(ModeleBase m) + { + ArrayList v = new ArrayList<>(); + int sel = m.getIndex(); + if (sel != -1) + { + v.add(sel); + } + setSelection(v); + } + + /** + * Starts highlighting the selected base. + */ + public void highlightSelectedStem(ModeleBase m) + { + ArrayList v = new ArrayList<>(); + int sel = m.getIndex(); + if (sel != -1) + { + ArrayList r = _RNA.findStem(sel); + v.addAll(r); + } + setSelection(v); + } + + public BaseList getSelection() + { + return _selectedBases; + } + + public ArrayList getSelectionIndices() + { + return _selectedBases.getIndices(); + } + + public void setSelection(ArrayList indices) + { + setSelection(_RNA.getBasesAt(indices)); + } + + public void setSelection(Collection mbs) + { + BaseList bck = new BaseList(_selectedBases); + _selectedBases.clear(); + _selectedBases.addBases(mbs); + _blink.setActive(true); + fireSelectionChanged(bck, _selectedBases); + } + + public ArrayList getBasesInRectangleDiff(Rectangle recIn, + Rectangle recOut) + { + ArrayList result = new ArrayList<>(); + for (int i = 0; i < _realCoords.length; i++) + { + if (recIn.contains(_realCoords[i]) ^ recOut.contains(_realCoords[i])) + { + result.add(i); + } + } + return result; + } + + public ArrayList getBasesInRectangle(Rectangle rec) + { + ArrayList result = new ArrayList<>(); + for (int i = 0; i < _realCoords.length; i++) + { + if (rec.contains(_realCoords[i])) + { + result.add(i); + } + } + return result; + } + + public void setSelectionRectangle(Rectangle rec) + { + ArrayList result = new ArrayList<>(); + if (_selectionRectangle != null) + { + result = getBasesInRectangleDiff(_selectionRectangle, rec); + } + else + { + result = getBasesInRectangle(rec); + } + _selectionRectangle = new Rectangle(rec); + toggleSelection(result); + repaint(); + } + + public void removeSelectionRectangle() + { + _selectionRectangle = null; + } + + public void addToSelection(Collection indices) + { + for (int i : indices) + { + addToSelection(i); + } + } + + public void addToSelection(int i) + { + BaseList bck = new BaseList(_selectedBases); + ModeleBase mb = _RNA.getBaseAt(i); + _selectedBases.addBase(mb); + _blink.setActive(true); + fireSelectionChanged(bck, _selectedBases); + } + + public void removeFromSelection(int i) + { + BaseList bck = new BaseList(_selectedBases); + ModeleBase mb = _RNA.getBaseAt(i); + _selectedBases.removeBase(mb); + if (_selectedBases.size() == 0) + { + _blink.setActive(false); + } + else + { + _blink.setActive(true); + } + fireSelectionChanged(bck, _selectedBases); + } + + public boolean isInSelection(int i) + { + return _selectedBases.contains(_RNA.getBaseAt(i)); + } + + public void toggleSelection(int i) + { + if (isInSelection(i)) + { + removeFromSelection(i); + } + else + { + addToSelection(i); + } + } + + public void toggleSelection(Collection indices) + { + for (int i : indices) + { + toggleSelection(i); + } + } + + /** + * Stops highlighting bases + */ + public void clearSelection() + { + BaseList bck = new BaseList(_selectedBases); + _selectedBases.clear(); + _blink.setActive(false); + repaint(); + fireSelectionChanged(bck, _selectedBases); + } + + public void saveSelection() + { + _backupSelection.clear(); + _backupSelection.addAll(_selectedBases.getBases()); + } + + public void restoreSelection() + { + setSelection(_backupSelection); + } + + /** + * Stops highlighting bases + */ + public void resetAnnotationHighlight() + { + _highlightAnnotation = false; + repaint(); + } + + /** + * Toggles on/off a rectangular outline of the bounding box. + * + * @param on + * True to draw the bounding box, false otherwise + */ + public void drawBBox(boolean on) + { + _drawBBox = on; + } + + /** + * Toggles on/off a rectangular outline of the border. + * + * @param on + * True to draw the bounding box, false otherwise + */ + public void drawBorder(boolean on) + { + _drawBorder = on; + } + + public void setBaseInnerColor(Color c) + { + _RNA.setBaseInnerColor(c); + } + + public void setBaseNumbersColor(Color c) + { + _RNA.setBaseNumbersColor(c); + } + + public void setBaseNameColor(Color c) + { + _RNA.setBaseNameColor(c); + } + + public void setBaseOutlineColor(Color c) + { + _RNA.setBaseOutlineColor(c); + } + + public ArrayList getListeAnnotations() + { + return _RNA.getAnnotations(); + } + + public void resetListeAnnotations() + { + _RNA.clearAnnotations(); + repaint(); + } + + public void addAnnotation(TextAnnotation textAnnotation) + { + _RNA.addAnnotation(textAnnotation); + repaint(); + } + + public boolean removeAnnotation(TextAnnotation textAnnotation) + { + boolean done = _RNA.removeAnnotation(textAnnotation); + repaint(); + return done; + } + + public TextAnnotation get_selectedAnnotation() + { + return _selectedAnnotation; + } + + public void set_selectedAnnotation(TextAnnotation annotation) + { + _selectedAnnotation = annotation; + } + + public void removeSelectedAnnotation() + { + _highlightAnnotation = false; + _selectedAnnotation = null; + } + + public void highlightSelectedAnnotation() + { + _highlightAnnotation = true; + } + + public boolean getFlatExteriorLoop() + { + return _conf._flatExteriorLoop; + } + + public void setFlatExteriorLoop(boolean on) + { + _conf._flatExteriorLoop = on; + } + + public void setLastSelectedPosition(Point2D.Double p) + { + _lastSelectedCoord.x = p.x; + _lastSelectedCoord.y = p.y; + } + + public Point2D.Double getLastSelectedPosition() + { + return _lastSelectedCoord; + } + + public void setSequence(String s) + { + _RNA.setSequence(s); + repaint(); + } + + public void setColorMapVisible(boolean b) + { + _conf._drawColorMap = b; + repaint(); + } + + public boolean getColorMapVisible() + { + return _conf._drawColorMap; + } + + public void removeColorMap() + { + _conf._drawColorMap = false; + repaint(); + } + + public void saveSession(String path) + { + /* + * FileOutputStream fos = null; ObjectOutputStream out = null; try { fos + * = new FileOutputStream(path); out = new ObjectOutputStream(fos); + * out.writeObject(new FullBackup(_conf, _RNA, _conf._title)); + * out.close(); } catch (Exception ex) { ex.printStackTrace(); } + */ + toXML(path); + } + + /** Added for Jalview */ + + public FullBackup loadSession(String path) throws ExceptionLoadingFailed + { + return loadSession(new File(path)); + } + + public FullBackup loadSession(File path) throws ExceptionLoadingFailed + { + + FullBackup bck = importSession(path); + Mapping map = Mapping.DefaultOutermostMapping(getRNA().getSize(), + bck.rna.getSize()); + showRNAInterpolated(bck.rna, map); + _conf = bck.config; + repaint(); + return bck; + } + + public static String VARNA_SESSION_EXTENSION = "varna"; + + public static FullBackup importSession(Object path) // BH was String + throws ExceptionLoadingFailed + { + try + { + FileInputStream fis = (path instanceof File + ? new FileInputStream((File) path) + : new FileInputStream(path.toString())); + // ZipInputStream zis = new + // ZipInputStream(new BufferedInputStream(fis)); + // zis.getNextEntry(); + FullBackup h = importSession(fis, path.toString()); + // zis.close(); + return h; + } catch (FileNotFoundException e) + { + throw (new ExceptionLoadingFailed("File not found.", + path.toString())); + } catch (IOException e) + { + // TODO Auto-generated catch block + throw (new ExceptionLoadingFailed("I/O error while loading session.", + path.toString())); + } + } + + public static FullBackup importSession(InputStream fis, String path) + throws ExceptionLoadingFailed + { + System.setProperty("javax.xml.parsers.SAXParserFactory", + "com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl"); + SAXParserFactory saxFact = javax.xml.parsers.SAXParserFactory + .newInstance(); + saxFact.setValidating(false); + saxFact.setXIncludeAware(false); + saxFact.setNamespaceAware(false); + try + { + SAXParser sp = saxFact.newSAXParser(); + VARNASessionParser sessionData = new VARNASessionParser(); + sp.parse(fis, sessionData); + FullBackup res = new FullBackup(sessionData.getVARNAConfig(), + sessionData.getRNA(), "test"); + return res; + } catch (ParserConfigurationException e) + { + throw new ExceptionLoadingFailed("Bad XML parser configuration", + path); + } catch (SAXException e) + { + throw new ExceptionLoadingFailed("XML parser Exception", path); + } catch (IOException e) + { + throw new ExceptionLoadingFailed("I/O error", path); + } + } + + public void loadFile(File path) + { + loadFile(path, false); + } + + public boolean getDrawBackbone() + { + return _conf._drawBackbone; + } + + public void setDrawBackbone(boolean b) + { + _conf._drawBackbone = b; + } + + public void addHighlightRegion(HighlightRegionAnnotation n) + { + _RNA.addHighlightRegion(n); + } + + public void removeHighlightRegion(HighlightRegionAnnotation n) + { + _RNA.removeHighlightRegion(n); + } + + public void addHighlightRegion(int i, int j) + { + _RNA.addHighlightRegion(i, j); + } + + public void addHighlightRegion(int i, int j, Color fill, Color outline, + double radius) + { + _RNA.addHighlightRegion(i, j, fill, outline, radius); + } + + public void loadRNA(String path) + { + loadRNA(path, false); + } + + public void loadRNA(Object path, boolean interpolate) + { // BH was String + try + { + Collection rnas = (path instanceof File + ? RNAFactory.loadSecStr(new FileReader((File) path)) + : RNAFactory.loadSecStr(path.toString())); + if (rnas.isEmpty()) + { + throw new ExceptionFileFormatOrSyntax( + "No RNA could be parsed from that source."); + } + RNA rna = rnas.iterator().next(); + try + { + rna.drawRNA(_conf); + } catch (ExceptionNAViewAlgorithm e) + { + e.printStackTrace(); + } + if (!interpolate) + { + showRNA(rna); + } + else + { + this.showRNAInterpolated(rna); + } + + } catch (FileNotFoundException e) + { + e.printStackTrace(); + } catch (ExceptionFileFormatOrSyntax e) + { + e.printStackTrace(); + } catch (Exception e) + { + e.printStackTrace(); + } + } + + public void loadFile(File path, boolean interpolate) + { // was String BH StringJS + try + { + loadSession(path); + } catch (Exception e1) + { + loadRNA(path, interpolate); + } + } + + public void setConfig(VARNAConfig cfg) + { + _conf = cfg; + } + + public void toggleDrawOutlineBases() + { + _conf._drawOutlineBases = !_conf._drawOutlineBases; + } + + public void toggleFillBases() + { + _conf._fillBases = !_conf._fillBases; + } + + public void setDrawOutlineBases(boolean drawn) + { + _conf._drawOutlineBases = drawn; + } + + public void setFillBases(boolean drawn) + { + _conf._fillBases = drawn; + } + + public void readValues(Reader r) + { + this._RNA.readValues(r, _conf._cm); + } + + public void addVARNAListener(InterfaceVARNAListener v) + { + _VARNAListeners.add(v); + } + + public void fireLayoutChanged() + { + for (InterfaceVARNAListener v : _VARNAListeners) + { + v.onStructureRedrawn(); + } + } + + public void fireUINewStructure(RNA r) + { + for (InterfaceVARNAListener v : _VARNAListeners) + { + v.onUINewStructure(_conf, r); + } + } + + public void fireZoomLevelChanged(double d) + { + for (InterfaceVARNAListener v : _VARNAListeners) + { + v.onZoomLevelChanged(); + } + } + + public void fireTranslationChanged() + { + for (InterfaceVARNAListener v2 : _VARNAListeners) + { + v2.onTranslationChanged(); + } + } + + public void addSelectionListener(InterfaceVARNASelectionListener v) + { + _selectionListeners.add(v); + } + + public void fireSelectionChanged(BaseList mold, BaseList mnew) + { + BaseList addedBases = mnew.removeAll(mold); + BaseList removedBases = mold.removeAll(mnew); + for (InterfaceVARNASelectionListener v2 : _selectionListeners) + { + v2.onSelectionChanged(mnew, addedBases, removedBases); + } + } + + public void fireHoverChanged(ModeleBase mold, ModeleBase mnew) + { + for (InterfaceVARNASelectionListener v2 : _selectionListeners) + { + v2.onHoverChanged(mold, mnew); + } + } + + public void addRNAListener(InterfaceVARNARNAListener v) + { + _RNAListeners.add(v); + } + + public void addVARNABasesListener(InterfaceVARNABasesListener l) + { + _basesListeners.add(l); + } + + public void fireSequenceChanged(int index, String oldseq, String newseq) + { + for (InterfaceVARNARNAListener v2 : _RNAListeners) + { + v2.onSequenceModified(index, oldseq, newseq); + } + } + + public void fireStructureChanged(Set current, + Set addedBasePairs, Set removedBasePairs) + { + for (InterfaceVARNARNAListener v2 : _RNAListeners) + { + v2.onStructureModified(current, addedBasePairs, removedBasePairs); + } + } + + public void fireLayoutChanged( + Hashtable movedPositions) + { + for (InterfaceVARNARNAListener v2 : _RNAListeners) + { + v2.onRNALayoutChanged(movedPositions); + } + } + + public void fireBaseClicked(ModeleBase mb, MouseEvent me) + { + if (mb != null) + { + for (InterfaceVARNABasesListener v2 : _basesListeners) + { + v2.onBaseClicked(mb, me); + } + } + } + + public double getOrientation() + { + return _RNA.getOrientation(); + } + + public ModeleBase _hoveredBase = null; + + public void setHoverBase(ModeleBase m) + { + if (m != _hoveredBase) + { + ModeleBase bck = _hoveredBase; + _hoveredBase = m; + repaint(); + fireHoverChanged(bck, m); + } + } + + public void toXML(String path) + { + FileOutputStream fis; + try + { + fis = new FileOutputStream(path); + // ZipOutputStream zis = new ZipOutputStream(new + // BufferedOutputStream(fis)); + // ZipEntry entry = new ZipEntry("VARNASession"); + // zis.putNextEntry(entry); + PrintWriter pw = new PrintWriter(fis); + toXML(pw); + pw.flush(); + // zis.closeEntry(); + // zis.close(); + fis.close(); + } catch (FileNotFoundException e) + { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (IOException e) + { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + public void toXML(PrintWriter out) + { + try + { + + // out = new PrintWriter(System.out); + StreamResult streamResult = new StreamResult(out); + SAXTransformerFactory tf = (SAXTransformerFactory) SAXTransformerFactory + .newInstance(); + // SAX2.0 ContentHandler. + TransformerHandler hd = tf.newTransformerHandler(); + Transformer serializer = hd.getTransformer(); + serializer.setOutputProperty(OutputKeys.ENCODING, "ISO-8859-1"); + serializer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, "users.dtd"); + serializer.setOutputProperty(OutputKeys.INDENT, "yes"); + hd.setResult(streamResult); + hd.startDocument(); + toXML(hd); + hd.endDocument(); + } catch (TransformerConfigurationException e) + { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (SAXException e) + { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + } + + public static String XML_ELEMENT_NAME = "VARNASession"; + + public void toXML(TransformerHandler hd) throws SAXException + { + AttributesImpl atts = new AttributesImpl(); + hd.startElement("", "", XML_ELEMENT_NAME, atts); + _RNA.toXML(hd); + _conf.toXML(hd); + hd.endElement("", "", XML_ELEMENT_NAME); + } + + public TextAnnotation getNearestAnnotation(int x, int y) + { + TextAnnotation t = null; + if (getListeAnnotations().size() != 0) + { + double dist = Double.MAX_VALUE; + double d2; + Point2D.Double position; + for (TextAnnotation textAnnot : getListeAnnotations()) + { + // calcul de la distance + position = textAnnot.getCenterPosition(); + position = transformCoord(position); + d2 = Math.sqrt(Math.pow((position.x - x), 2) + + Math.pow((position.y - y), 2)); + // si la valeur est inferieur au minimum actuel + if ((dist > d2) && (d2 < getScaleFactor() + * ControleurClicMovement.MIN_SELECTION_DISTANCE)) + { + t = textAnnot; + dist = d2; + } + } + } + return t; + } + + public ModeleBase getNearestBase(int x, int y, boolean always, + boolean onlyPaired) + { + int i = getNearestBaseIndex(x, y, always, onlyPaired); + if (i == -1) + { + return null; + } + return getRNA().get_listeBases().get(i); + } + + public ModeleBase getNearestBase(int x, int y) + { + return getNearestBase(x, y, false, false); + } + + public int getNearestBaseIndex(int x, int y, boolean always, + boolean onlyPaired) + { + double d2, dist = Double.MAX_VALUE; + int mb = -1; + for (int i = 0; i < getRealCoords().length; i++) + { + if (!onlyPaired || (getRNA().get_listeBases().get(i) + .getElementStructure() != -1)) + { + d2 = Math.sqrt(Math.pow((getRealCoords()[i].x - x), 2) + + Math.pow((getRealCoords()[i].y - y), 2)); + if ((dist > d2) && ((d2 < getScaleFactor() + * ControleurClicMovement.MIN_SELECTION_DISTANCE) || always)) + { + dist = d2; + mb = i; + } + } + } + return mb; + } + + public void globalRescale(double factor) + { + _RNA.rescale(factor); + fireLayoutChanged(); + repaint(); + } + + public void setSpaceBetweenBases(double sp) + { + _conf._spaceBetweenBases = sp; + } + + public double getSpaceBetweenBases() + { + return _conf._spaceBetweenBases; + } }