Newer
Older
/* ComparatorGlue.java
*
* created: Tue Sep 11 2001
*
* This file is part of Artemis
*
* Copyright (C) 2001 Genome Research Limited
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Header: //tmp/pathsoft/artemis/uk/ac/sanger/artemis/components/ComparatorGlue.java,v 1.4 2005-12-02 14:58:57 tjc Exp $
*/
package uk.ac.sanger.artemis.components;
import uk.ac.sanger.artemis.*;
import uk.ac.sanger.artemis.sequence.*;
import uk.ac.sanger.artemis.util.ReadOnlyException;
import uk.ac.sanger.artemis.util.OutOfRangeException;
import java.util.*;
import java.awt.*;
import javax.swing.*;
/**
* This class contains the Event glue needed to combine two FeatureDisplays
* and an AlignmentViewer.
*
* @author Kim Rutherford <kmr@sanger.ac.uk>
* @version $Id: ComparatorGlue.java,v 1.4 2005-12-02 14:58:57 tjc Exp $
**/
public class ComparatorGlue {
/**
* Create a new ComparatorGlue object that glues the given components
* togeather.
**/
public ComparatorGlue (final JFrame parent_frame,
final FeatureDisplay subject_feature_display,
final FeatureDisplay query_feature_display,
final AlignmentViewer alignment_viewer) {
this.parent_frame = parent_frame;
this.subject_feature_display = subject_feature_display;
this.query_feature_display = query_feature_display;
this.alignment_viewer = alignment_viewer;
getSubjectEntryGroup ().addFeatureChangeListener (getSubjectSelection ());
getQueryEntryGroup ().addEntryChangeListener (getQuerySelection ());
addDisplayListeners (subject_feature_display, query_feature_display);
orig_subject_forward_strand =
getSubjectEntryGroup ().getBases ().getForwardStrand ();
orig_query_forward_strand =
getQueryEntryGroup ().getBases ().getForwardStrand ();
makeAlignmentEventListener ();
}
/**
* Wire-up the two FeatureDisplay objects with DisplayAdjustmentListeners.
**/
private void addDisplayListeners (final FeatureDisplay subject_display,
final FeatureDisplay query_display)
{
subject_listener = new DisplayAdjustmentListener()
public void displayAdjustmentValueChanged(DisplayAdjustmentEvent e)
if(e.getType() == DisplayAdjustmentEvent.REV_COMP_EVENT)
getAlignmentViewer().unlockDisplays();
else if(e.getType() == DisplayAdjustmentEvent.CONTIG_REV_COMP_EVENT)
{
getAlignmentViewer().flippingContig(true, e.getStart(), e.getEnd());
getAlignmentViewer().unlockDisplays();
getSubjectDisplay().setFirstBase(e.getStart());
else if(e.getType() == DisplayAdjustmentEvent.CONTIG_REORDER)
{
getAlignmentViewer().reorder(true, e.getStart(), e.getEnd(),
e.getDropPosition());
getAlignmentViewer().unlockDisplays();
if(e.getStart() < e.getDropPosition())
getSubjectDisplay().setFirstBase(e.getStart());
else
getSubjectDisplay().setFirstBase(e.getDropPosition());
return;
}
subject_display.removeDisplayAdjustmentListener(subject_listener);
query_display.removeDisplayAdjustmentListener(query_listener);
query_display.setScaleFactor (e.getScaleFactor ());
if (getAlignmentViewer ().displaysAreLocked () &&
(e.getType () == DisplayAdjustmentEvent.SCROLL_ADJUST_EVENT ||
e.getType () == DisplayAdjustmentEvent.ALL_CHANGE_ADJUST_EVENT)) {
final int difference = e.getStart () - subject_first_base_position;
query_first_base_position =
query_display.getForwardBaseAtLeftEdge () + difference;
query_display.setFirstBase (query_first_base_position);
}
subject_first_base_position = e.getStart ();
subject_display.addDisplayAdjustmentListener (subject_listener);
query_display.addDisplayAdjustmentListener (query_listener);
}
};
query_listener = new DisplayAdjustmentListener ()
{
public void displayAdjustmentValueChanged (DisplayAdjustmentEvent e)
{
if (e.getType () == DisplayAdjustmentEvent.REV_COMP_EVENT)
{
getAlignmentViewer().unlockDisplays();
return;
}
else if (e.getType () == DisplayAdjustmentEvent.CONTIG_REV_COMP_EVENT)
{
getAlignmentViewer().flippingContig(false, e.getStart(), e.getEnd());
getAlignmentViewer().unlockDisplays();
getQueryDisplay().setFirstBase(e.getStart());
else if(e.getType() == DisplayAdjustmentEvent.CONTIG_REORDER)
{
getAlignmentViewer().reorder(false, e.getStart(), e.getEnd(),
e.getDropPosition());
getAlignmentViewer().unlockDisplays();
if(e.getStart() < e.getDropPosition())
getSubjectDisplay().setFirstBase(e.getStart());
else
getSubjectDisplay().setFirstBase(e.getDropPosition());
return;
}
subject_display.removeDisplayAdjustmentListener (subject_listener);
query_display.removeDisplayAdjustmentListener (query_listener);
subject_display.setScaleFactor (e.getScaleFactor ());
if (getAlignmentViewer ().displaysAreLocked () &&
(e.getType () == DisplayAdjustmentEvent.SCROLL_ADJUST_EVENT ||
e.getType () == DisplayAdjustmentEvent.ALL_CHANGE_ADJUST_EVENT))
{
final int difference = e.getStart () - query_first_base_position;
subject_first_base_position =
subject_display.getForwardBaseAtLeftEdge () + difference;
subject_display.setFirstBase (subject_first_base_position);
}
query_first_base_position = e.getStart ();
subject_display.addDisplayAdjustmentListener (subject_listener);
query_display.addDisplayAdjustmentListener (query_listener);
}
};
subject_display.addDisplayAdjustmentListener (subject_listener);
query_display.addDisplayAdjustmentListener (query_listener);
final DisplayAdjustmentListener subject_align_listener =
new DisplayAdjustmentListener ()
{
public void displayAdjustmentValueChanged (DisplayAdjustmentEvent e)
{
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
getAlignmentViewer ().setSubjectSequencePosition (e);
}
};
subject_display.addDisplayAdjustmentListener (subject_align_listener);
final DisplayAdjustmentListener query_align_listener =
new DisplayAdjustmentListener () {
public void displayAdjustmentValueChanged (DisplayAdjustmentEvent e) {
getAlignmentViewer ().setQuerySequencePosition (e);
}
};
query_display.addDisplayAdjustmentListener (query_align_listener);
}
/**
* Make an AlignmentListener which calls alignAt ().
**/
private void makeAlignmentEventListener () {
final AlignmentListener listener =
new AlignmentListener () {
public void alignMatchChosen (AlignmentEvent e) {
alignAt (e.getMatch ());
}
};
getAlignmentViewer ().addAlignmentListener (listener);
}
/**
* Scroll both the subject and query so that they centre on the given
* AlignMatch.
**/
private void alignAt (final AlignMatch align_match) {
getAlignmentViewer ().unlockDisplays ();
getAlignmentViewer ().disableSelection ();
maybeRevCompQuery (align_match);
final int subject_length = getSubjectForwardStrand ().getSequenceLength ();
final int query_length = getQueryForwardStrand ().getSequenceLength ();
int subject_sequence_start =
AlignmentViewer.getRealSubjectSequenceStart (align_match,
subject_length,
getAlignmentViewer ().subjectIsRevComp ());
int subject_sequence_end =
AlignmentViewer.getRealSubjectSequenceEnd (align_match,
subject_length,
getAlignmentViewer ().subjectIsRevComp ());
int query_sequence_start =
AlignmentViewer.getRealQuerySequenceStart (align_match,
query_length,
getAlignmentViewer ().queryIsRevComp ());
int query_sequence_end =
AlignmentViewer.getRealQuerySequenceEnd (align_match,
query_length,
getAlignmentViewer ().queryIsRevComp ());
if (getSubjectDisplay ().isRevCompDisplay ()) {
subject_sequence_start =
getSubjectDisplay ().getSequenceLength () - subject_sequence_start + 1;
subject_sequence_end =
getSubjectDisplay ().getSequenceLength () - subject_sequence_end + 1;
}
if (getQueryDisplay ().isRevCompDisplay ()) {
query_sequence_start =
getQueryDisplay ().getSequenceLength () - query_sequence_start + 1;
query_sequence_end =
getQueryDisplay ().getSequenceLength () - query_sequence_end + 1;
}
final int new_subject_base =
subject_sequence_start +
(subject_sequence_end - subject_sequence_start) / 2;
getSubjectDisplay ().makeBaseVisible (new_subject_base);
try {
final Strand subject_strand;
if (align_match.isRevMatch () ^
!getOrigSubjectForwardStrand ().isForwardStrand ()) {
subject_strand = getSubjectReverseStrand ();
} else {
subject_strand = getSubjectForwardStrand ();
}
final MarkerRange new_subject_marker =
subject_strand.makeMarkerRangeFromRawPositions (subject_sequence_start,
subject_sequence_end);
getSubjectSelection ().setMarkerRange (new_subject_marker);
} catch (OutOfRangeException e) {
throw new Error ("internal error - unexpected exception: " + e);
}
final int new_query_base =
query_sequence_start +
(query_sequence_end - query_sequence_start) / 2;
getQueryDisplay ().makeBaseVisible (new_query_base);
try {
final Strand query_strand;
if (getOrigQueryForwardStrand ().isForwardStrand ()) {
query_strand = getQueryForwardStrand ();
} else {
query_strand = getQueryReverseStrand ();
}
final MarkerRange new_query_marker_range =
query_strand.makeMarkerRangeFromRawPositions (query_sequence_start,
query_sequence_end);
getQuerySelection ().setMarkerRange (new_query_marker_range);
} catch (OutOfRangeException e) {
throw new Error ("internal error - unexpected exception: " + e);
}
getAlignmentViewer ().lockDisplays ();
getAlignmentViewer ().enableSelection ();
}
/**
* Called by alignAt () to reverse and complement the query sequence if the
* given AlignMatch is currently a match from the subject sequence to the
* reverse complement of the query sequence.
**/
private void maybeRevCompQuery (final AlignMatch align_match) {
if (!getAlignmentViewer ().offerToFlip ()) {
return;
}
// true if and only if exactly one of the query and subject is rev-comped
final boolean display_is_rev_comped;
if (getOrigSubjectForwardStrand ().isForwardStrand () ^
getOrigQueryForwardStrand ().isForwardStrand () ^
getSubjectDisplay ().isRevCompDisplay () ^
getQueryDisplay ().isRevCompDisplay ()) {
display_is_rev_comped = true;
} else {
display_is_rev_comped = false;
}
if (align_match.isRevMatch () ^ display_is_rev_comped) {
final YesNoDialog yes_no_dialog =
new YesNoDialog (parent_frame,
"reverse and complement query sequence display?");
if (yes_no_dialog.getResult ()) {
if (getQueryDisplay ().isRevCompDisplay ()) {
getQueryDisplay ().setRevCompDisplay (false);
} else {
getQueryDisplay ().setRevCompDisplay (true);
}
}
}
}
/**
* Send an event to those object listening for it.
* @param listeners A Vector of the objects that the event should be sent
* to.
* @param event The event to send
**/
private void fireAction (final Vector listeners, final EventObject event) {
final Vector targets;
// copied from a book - synchronising the whole method might cause a
// deadlock
synchronized (this) {
targets = (Vector) listeners.clone ();
}
for (int i = 0 ; i < targets.size () ; ++i) {
GotoListener target = (GotoListener) targets.elementAt (i);
if (event instanceof GotoEvent) {
final GotoListener goto_listener = (GotoListener) target;
goto_listener.performGoto ((GotoEvent) event);
} else {
throw new Error ("EntryEdit.fireAction () - unknown event");
}
}
}
/**
* Return the forward Strand of the subject EntryGroup from when the
* Comparator was created.
**/
public Strand getOrigSubjectForwardStrand () {
return orig_subject_forward_strand;
}
/**
* Return the forward Strand of the query EntryGroup from when the
* Comparator was created.
**/
public Strand getOrigQueryForwardStrand () {
return orig_query_forward_strand;
}
/**
* Return the GotoEventSource object used by the subject FeatureDisplay.
**/
public GotoEventSource getSubjectGotoEventSource () {
return getSubjectDisplay ().getGotoEventSource ();
}
/**
* Return the GotoEventSource object used by the query FeatureDisplay.
**/
public GotoEventSource getQueryGotoEventSource () {
return getQueryDisplay ().getGotoEventSource ();
}
/**
* Return the reference of the EntryGroup in view in the subject
* FeatureDisplay.
**/
public EntryGroup getSubjectEntryGroup () {
return getSubjectDisplay ().getEntryGroup ();
}
/**
* Return the reference of the EntryGroup in view in the query
* FeatureDisplay.
**/
public EntryGroup getQueryEntryGroup () {
return getQueryDisplay ().getEntryGroup ();
}
/**
* Return the Selection object used by the subject FeatureDisplay.
**/
public Selection getSubjectSelection () {
return getSubjectDisplay ().getSelection ();
}
/**
* Return the Selection object used by the query FeatureDisplay.
**/
public Selection getQuerySelection () {
return getQueryDisplay ().getSelection ();
}
/**
* Return the AlignmentViewer that was created in the constructor.
**/
private AlignmentViewer getAlignmentViewer () {
return alignment_viewer;
}
/**
* Return the reference of the subject FeatureDisplay.
**/
public FeatureDisplay getSubjectDisplay () {
return subject_feature_display;
}
/**
* Return the reference of the query FeatureDisplay.
**/
public FeatureDisplay getQueryDisplay () {
return query_feature_display;
}
/**
* Return the current forward Strand of the subject EntryGroup.
**/
private Strand getSubjectForwardStrand () {
return getSubjectEntryGroup ().getBases ().getForwardStrand ();
}
/**
* Return the current forward Strand of the query EntryGroup.
**/
private Strand getQueryForwardStrand () {
return getQueryEntryGroup ().getBases ().getForwardStrand ();
}
/**
* Return the current reverse Strand of the subject EntryGroup.
**/
private Strand getSubjectReverseStrand () {
return getSubjectEntryGroup ().getBases ().getReverseStrand ();
}
/**
* Return the current reverse Strand of the query EntryGroup.
**/
private Strand getQueryReverseStrand () {
return getQueryEntryGroup ().getBases ().getReverseStrand ();
}
final private JFrame parent_frame;
final private FeatureDisplay subject_feature_display;
final private FeatureDisplay query_feature_display;
final private AlignmentViewer alignment_viewer;
private int subject_first_base_position = 1;
private int query_first_base_position = 1;
private DisplayAdjustmentListener subject_listener = null;
private DisplayAdjustmentListener query_listener = null;
/**
* The forward Strand of the subject EntryGroup when the Comparator was
* created.
**/
final private Strand orig_subject_forward_strand;
/**
* The forward Strand of the query EntryGroup when the Comparator was
* created.
**/
final private Strand orig_query_forward_strand;
}