001/*
002 * Copyright (c) 2004-2010 The Regents of the University of California.
003 * All rights reserved.
004 *
005 * '$Author: welker $'
006 * '$Date: 2010-05-06 05:21:26 +0000 (Thu, 06 May 2010) $' 
007 * '$Revision: 24234 $'
008 * 
009 * Permission is hereby granted, without written agreement and without
010 * license or royalty fees, to use, copy, modify, and distribute this
011 * software and its documentation for any purpose, provided that the above
012 * copyright notice and the following two paragraphs appear in all copies
013 * of this software.
014 *
015 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
016 * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
017 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
018 * THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
019 * SUCH DAMAGE.
020 *
021 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
022 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
023 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
024 * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
025 * CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
026 * ENHANCEMENTS, OR MODIFICATIONS.
027 *
028 */
029
030package org.sdm.spa.actors.piw.viz;
031
032import java.awt.AlphaComposite;
033import java.awt.Color;
034import java.awt.Component;
035import java.awt.Dimension;
036import java.awt.Font;
037import java.awt.Graphics2D;
038import java.awt.event.ActionEvent;
039import java.awt.event.ActionListener;
040import java.awt.event.ComponentAdapter;
041import java.awt.event.ComponentEvent;
042
043import diva.canvas.CompositeFigure;
044import diva.canvas.FigureLayer;
045import diva.canvas.GraphicsPane;
046import diva.canvas.JCanvas;
047import diva.canvas.toolbox.BasicRectangle;
048import diva.canvas.toolbox.LabelFigure;
049
050public class DetailPanel extends JCanvas {
051
052        private static final long serialVersionUID = 3257288028421894961L;
053        private int _startViewPort;
054        private int _sizeViewPort;
055
056        private final SequenceCollection _sequenceCollection;
057        private final SiteCollection _siteCollection;
058
059        public DetailPanel(SequenceCollection sequenceCollection,
060                        SiteCollection siteCollection, ActionListener listenerViewPortSize) {
061
062                // Set default view port parameters.
063                _sizeViewPort = 100;
064                _startViewPort = 0;
065
066                this._sequenceCollection = sequenceCollection;
067                this._siteCollection = siteCollection;
068
069                this.addComponentListener(new ListenerComponent(listenerViewPortSize));
070        }
071
072        public void drawSequences() {
073                drawSequences(_startViewPort);
074        }
075
076        public void drawSequences(int startViewPort) {
077                this._startViewPort = startViewPort;
078
079                this.clear();
080
081                FigureLayer layer = ((GraphicsPane) this.getCanvasPane())
082                                .getForegroundLayer();
083
084                // Draw consensus sequence.
085                SequenceFigure sequenceFigure = new SequenceFigure(new Sequence("",
086                                "consensus", _sequenceCollection.getConsensus(),
087                                new TranscriptionFactorBindingSite[] {}), _startViewPort,
088                                _sizeViewPort, _sequenceCollection.getConsensus());
089
090                sequenceFigure.translate(0, 50);
091                layer.add(sequenceFigure);
092
093                for (int i = 0; i < _sequenceCollection.size(); i++) {
094                        Sequence sequence = _sequenceCollection.getSequence(i);
095
096                        sequenceFigure = new SequenceFigure(sequence, _startViewPort,
097                                        _sizeViewPort, _sequenceCollection.getConsensus());
098
099                        // Draw the sequence.
100                        sequenceFigure.translate(0, (i + 2) * 50);
101                        layer.add(sequenceFigure);
102                }
103
104                // Set preferred size.
105                this.setPreferredSize(new Dimension(_sizeViewPort + 200,
106                                (_sequenceCollection.size() + 2) * 50));
107        }
108
109        public void clear() {
110                ((GraphicsPane) this.getCanvasPane()).getForegroundLayer().clear();
111        }
112
113        private class ListenerComponent extends ComponentAdapter {
114                private final ActionListener _listener;
115
116                protected ListenerComponent(ActionListener listener) {
117                        _listener = listener;
118                }
119
120                public void componentResized(ComponentEvent e) {
121                        Component component = e.getComponent();
122
123                        _sizeViewPort = (component.getWidth() - 200) / 7;
124
125                        if (null != _listener) {
126                                _listener.actionPerformed(new ActionEvent(this, _sizeViewPort,
127                                                ""));
128                        }
129                }
130        }
131
132        private class SequenceFigure extends CompositeFigure {
133
134                public SequenceFigure(Sequence sequence, int startViewPort,
135                                int sizeViewPort, String strConsensus) {
136
137                        // Add the gene ID label.
138                        LabelFigure label = new LabelFigure(sequence.geneID, "SansSerif",
139                                        Font.ITALIC, 14);
140                        label.translate(20, 0);
141                        this.add(label);
142
143                        CompositeFigure compositeFigure = new CompositeFigure();
144                        shadeConsensus(compositeFigure, startViewPort, sizeViewPort,
145                                        strConsensus);
146
147                        // Draw all the transcription factor binding sites.
148                        for (int i = 0; i < sequence.arrTFBSs.length; i++) {
149
150                                final TranscriptionFactorBindingSite tfbs = sequence.arrTFBSs[i];
151                                final SiteCollection.Site site = _siteCollection
152                                                .getSite(tfbs.name);
153
154                                // If not visible, then don't paint.
155                                if (!site.selected) {
156                                        continue;
157                                }
158
159                                // Count of non-hyphens.
160                                int count = 0;
161                                for (int j = sequence.getActualIndex(Math.abs(tfbs.location));; j++) {
162                                        // If we're past the end of the sequence, then stop.
163                                        if (j >= sequence.alignedSequence.length()
164                                                        + sequence.offset) {
165                                                break;
166                                        }
167
168                                        // If we're past the end of the viewport, then stop.
169                                        if (j >= startViewPort + sizeViewPort) {
170                                                break;
171                                        }
172
173                                        // If we see a gap, then go on to the next one.
174                                        if ('-' == sequence.alignedSequence.charAt(j
175                                                        - sequence.offset)) {
176                                                continue;
177                                        }
178
179                                        count++;
180
181                                        // If we're in the view port, then add.
182                                        if (j >= startViewPort) {
183                                                compositeFigure.add(new BasicRectangle(
184                                                                (j - startViewPort) * 7, -10, 7, 15) {
185                                                        public void paint(Graphics2D g) {
186                                                                AlphaComposite c = AlphaComposite.getInstance(
187                                                                                AlphaComposite.SRC_OVER, 0.2f);
188                                                                g.setComposite(c);
189                                                                g.setPaint(site.color);
190                                                                g.fill(this.getShape());
191                                                                g.setComposite(AlphaComposite.SrcOver);
192                                                        }
193                                                });
194                                        }
195
196                                        if (10 == count) {
197                                                break;
198                                        }
199                                }
200                        }
201
202                        // Draw the actual sequence.
203                        compositeFigure
204                                        .add(new LabelFigure(sequence.subsequence(startViewPort,
205                                                        sizeViewPort), "Monospaced", Font.PLAIN, 12));
206
207                        // Add that composite figure to this.
208                        compositeFigure.translate(150, 0);
209                        this.add(compositeFigure);
210                }
211
212                private void shadeConsensus(CompositeFigure compositeFigure,
213                                int startViewPort, int sizeViewPort, String strConsensus) {
214
215                        if (startViewPort >= strConsensus.length()) {
216                                return;
217                        }
218
219                        strConsensus = strConsensus.substring(startViewPort);
220                        int i = 0;
221                        while (i < sizeViewPort && 0 < strConsensus.length()) {
222                                // If not consensus, then jump ahead.
223                                if ('-' == strConsensus.charAt(0)) {
224                                        String next = strConsensus.replaceFirst("-+", "");
225                                        i += strConsensus.length() - next.length();
226                                        strConsensus = next;
227                                        continue;
228                                }
229
230                                // If the consensus sequence isn't long enough, then don't
231                                // shade.
232                                String oldconsensus = strConsensus;
233                                int oldi = i;
234                                strConsensus = strConsensus.replaceFirst("[^-]+", "");
235                                int length = oldconsensus.length() - strConsensus.length();
236                                i += length;
237
238                                if (length < _sequenceCollection.getMinimumConsensusLength()) {
239                                        continue;
240                                }
241
242                                if (i >= sizeViewPort) {
243                                        length = sizeViewPort - oldi;
244                                }
245
246                                compositeFigure.add(new BasicRectangle(oldi * 7, -10,
247                                                7 * length, 15) {
248                                        public void paint(Graphics2D g) {
249                                                AlphaComposite c = AlphaComposite.getInstance(
250                                                                AlphaComposite.SRC_OVER, 0.3f);
251                                                g.setComposite(c);
252                                                g.setPaint(new Color(175, 175, 175));
253                                                g.fill(this.getShape());
254                                                g.setComposite(AlphaComposite.SrcOver);
255                                        }
256                                });
257                        }
258                }
259
260        }
261}