/***************************************************************************** # Copyright (C) 1994-2008 by David Gordon. # All rights reserved. # # This software is part of a beta-test version of the Consed/Autofinish # package. It should not be redistributed or # used for any commercial purpose, including commercially funded # sequencing, without written permission from the author and the # University of Washington. # # This software is provided ``AS IS'' and any express or implied # warranties, including, but not limited to, the implied warranties of # merchantability and fitness for a particular purpose, are disclaimed. # In no event shall the authors or the University of Washington be # liable for any direct, indirect, incidental, special, exemplary, or # consequential damages (including, but not limited to, procurement of # substitute goods or services; loss of use, data, or profits; or # business interruption) however caused and on any theory of liability, # whether in contract, strict liability, or tort (including negligence # or otherwise) arising in any way out of the use of this software, even # if advised of the possibility of such damage. # # Building Consed from source is error prone and not simple which is # why I provide executables. Due to time limitations I cannot # provide any assistance in building Consed. Even if you do not # modify the source, you may introduce errors due to using a # different version of the compiler, a different version of motif, # different versions of other libraries than I used, etc. For this # reason, if you discover Consed bugs, I can only offer help with # those bugs if you first reproduce those bugs with an executable # provided by me--not an executable you have built. # # Modifying Consed is also difficult. Although Consed is modular, # some modules are used by many other modules. Thus making a change # in one place can have unforeseen effects on many other features. # It may takes months for you to notice these other side-effects # which may not seen connected at all. It is not feasable for me to # provide help with modifying Consed sources because of the # potentially huge amount of time involved. # #*****************************************************************************/ #include "tedwin.h" #include "teditor.h" #include "guiapp.h" #include "mbt_errors.h" #include "editOverstrike.h" #include "editInsertColOfPads.h" #include "guiWhatToDoWithSelection.h" #include "editMakeHighQuality.h" #include "editMakeHighQualityAndChangeConsensus.h" #include "editMakeLowQuality.h" #include "editMakeLowQualityToLeft.h" #include "editMakeLowQualityToRight.h" #include "editChangeToNs.h" #include "editChangeToNsToLeft.h" #include "editChangeToNsToRight.h" #include "consedParameters.h" #include "tagTypes.h" #include "colormode.h" #include "guiGetTagType.h" #include "bGuiGetAnswerYesNo.h" #include "editAddReadTag.h" #include "editChangeToXs.h" #include "popupInfoMessage.h" #include "guiteditor.h" TedWin :: TedWin( Teditor* pTeditor, // pointer to parent const int nInitialBasePos, // base position LocatedFragment* pLocatedFragment, const int nPositionOnTeditor, const bool bAddToScrollingWindow ) : pTeditor_(pTeditor), pLocatedFragment_( pLocatedFragment ), bJustCreatedEditAction_(false) { bool bShowObject = !bAddToScrollingWindow; bool bShowABICalledBasesLine; if ( bAddToScrollingWindow ) bShowABICalledBasesLine = false; else bShowABICalledBasesLine = consedParameters::pGetConsedParameters()->bShowABIBasesInTraceWindow_; // create your compainion gui object pGuiTedWin_ = new GuiTedWin(this, nPositionOnTeditor, bAddToScrollingWindow, bShowABICalledBasesLine, bShowObject, // phred bShowObject, // consensus true, // editable read bShowObject, // consensus positions bShowObject // scrollbar ); // Note: don't add this TedWin to the list until the GuiTedWin has // been created. the GuiTedWin ctor references all existing // GuiTedWin's and it will thus try to reference the one it // is supposed to be creating. // add the TedWin to the dynamic array of pointers // you keep for the purpose of refreshes, etc. pTeditor_->addNewTedWinToTeditorList( this ); // set up the slider's initial configuration. pGuiTedWin_->guiTedWinResetSlider(0, // initial point position 0, // minimum point position // maximum point position nGetNumberOfPoints(), // number of points displayed at once pGuiTedWin_->nGetTraceWindowPointsWide() ); // don't do this if adding to scrolling window // since it will be done by GuiTedWin::alignTraceToMaster (July, 2004) if (!bAddToScrollingWindow ) { // we want to put the cursor in the middle of the window. // So figure out how many bases wide the screen is. int nPointsAcrossHalfOfScreen = pGuiTedWin_->nGetTraceWindowPointsWide() / 2; int nPointInMiddleOfScreen = pLocatedFragment_->nGetPointPosByConsPos( nInitialBasePos ); int nPointAtLeftHandOfScreen = nPointInMiddleOfScreen - nPointsAcrossHalfOfScreen; // now let's try to find a base that is at or just after this // point position int nConsPosMin = pLocatedFragment_->nGetAlignStart(); int nFoundConsPos; bool bFound = false; for( int nConsPos = nInitialBasePos; nConsPos >= nConsPosMin && !bFound; --nConsPos ) { if ( pLocatedFragment_->nGetPointPosByConsPos( nConsPos ) < nPointAtLeftHandOfScreen ) { nFoundConsPos = nConsPos + 1; bFound = true; } } if ( !bFound ) { // how could this occur? If the point positions are all // greater than this nFoundConsPos = nConsPosMin; } // set the initial slider pos in terms of (aligned) consensus position // put the clicked upon base a bit inside the window scrollToConsPos( nFoundConsPos ); } updateReadSense(); pContigWinGet()->drawSequencingDirectionArrow( pLocatedFragment_ ); } // TedWin ctor TedWin :: ~TedWin() { // delete your companion object delete pGuiTedWin_; pContigWinGet()->drawSequencingDirectionArrow( pLocatedFragment_ ); } // uses the contigwin function GetColorAndBaseForRead to get the same // color as in the contig window GuiColorText* TedWin :: pGetGuiColorTextForSameAsContigWin( int nConsensusPosition) { GuiColorText *pGuiColorText; char cTempBase; pContigWinGet()->GetColorAndBaseForRead(pLocatedFragment_, nConsensusPosition, pGuiColorText, cTempBase ); return( pGuiColorText ); } GuiColorText* TedWin :: pGetGuiColorTextForCalledBase( char cBase ) { cBase = toupper( cBase ); switch( cBase ) { case 'A' : return( pGuiTedWin_->pGetGuiColorTextA() ); case 'C' : return( pGuiTedWin_->pGetGuiColorTextC() ); case 'G' : return( pGuiTedWin_->pGetGuiColorTextG() ); case 'T' : return( pGuiTedWin_->pGetGuiColorTextT() ); case 'N' : return( pGuiTedWin_->pGetGuiColorTextN() ); case '*' : return( pGuiTedWin_->pGetGuiColorTextPad() ); default : { // I've seen 'K' before--DG return( pGuiTedWin_->pGetGuiColorTextN() ); } } } // passed the (fragment relative and necessarily unpadded) index of // the originally called base, returns the char to draw and its // GuiColorText void TedWin :: getCalledBaseAndColor(const int nFragPos, // padded or unpadded // depending on whether pSeqPhredCalledBases_ is null or not bool& bIsPad, char& cBase, GuiColorText*& pGuiColorText, int& nPointPos, const eTeditorType eTeditorTypee) { if (eTeditorTypee == eABICalledBase ) { Ntide& nt = pTraceFileGet()->ntideABICalledGet(nFragPos); bIsPad = nt.bIsPad(); cBase = nt.cGetBase(); pGuiColorText = pGetGuiColorTextForCalledBase( nt ); nPointPos = pTraceFileGet()->seqABICalledBases_.nGetPointPos( nFragPos ); } else { Ntide& nt = pLocFragGet()->ntideGetPhredCalledBase(nFragPos); bIsPad = nt.bIsPad(); pGuiColorText = pGetGuiColorTextForCalledBase( nt ); cBase = toupper( nt.cGetBase() ); nPointPos = pLocFragGet()->nGetPointPosOfPhredCalledBase( nFragPos ); } } // passed the consensus relative index of the fragment base, // return it's char and GuiColorText void TedWin :: getFragBaseAndColor(int nConsensusPos, Ntide& nt, GuiColorText*& pGuiColorText) { nt = pLocatedFragment_->ntGetFragFromConsPos( nConsensusPos ); pGuiColorText = pGetGuiColorTextForSameAsContigWin( nConsensusPos ); nt.setBase( toupper( nt.cGetBaseUpperOrLower() ) ); } // passed the consensus relative index of the fragment base, // return it's char and highlighted GuiColorText void TedWin :: getHighlightedBaseAndColor(int nConsensusPos, Ntide& nt, GuiColorText*& pGuiColorText) { nt = pLocatedFragment_->ntGetFragFromConsPos( nConsensusPos ); // all highlighted bases use the same GuiColorText pGuiColorText = pGuiTedWin_->pGetGuiColorTextHighlightedA(); nt.setBase( toupper( nt.cGetBaseUpperOrLower() ) ); } // passed starting and stopping positions in terms of indices into // array of originally called bases, draws those bases on the TedWin // in appropriate place and color. void TedWin :: drawCalledBases(const int nCalledPosMin, const int nCalledPosMax, const eTeditorType eTeditorTypee) { // perhaps we aren't showing the ABI calls if ( eTeditorTypee == eABICalledBase && !pGuiTedWin_->bShowABICalledBases_ ) return; bool bLeftMostBase = true; for (int nCalledPos = nCalledPosMin; nCalledPos <= nCalledPosMax; nCalledPos++) { char cBase; GuiColorText* pGuiColorText; int nPointPos; bool bIsPad; getCalledBaseAndColor(nCalledPos, bIsPad, cBase, pGuiColorText, nPointPos, eTeditorTypee); if ( !bIsPad ) { pGuiTedWin_->guiDrawBaseAtPeakPosition( eTeditorTypee, nPointPos, cBase, pGuiColorText, bLeftMostBase ); bLeftMostBase = false; } } } // same as above but figure positions for yourself void TedWin :: drawCalledBases( const eTeditorType eTeditorTypee) { // perhaps we aren't showing the ABI calls if ( eTeditorTypee == eABICalledBase && !pGuiTedWin_->bShowABICalledBases_ ) return; pGuiTedWin_->guiClearWindow( eTeditorTypee ); // clear drawing area int nCalledPosMin, nCalledPosMax; bool bError; if (eTeditorTypee == eABICalledBase ) { pTraceFileGet()->getRangeOfABICalledPositions( pGuiTedWin_->nGetLeftEdgePointPosition(), pGuiTedWin_->nGetRightEdgePointPosition(), nCalledPosMin, nCalledPosMax, bError ); } else { pLocFragGet()->getRangeOfPhredCalledPositions( pGuiTedWin_->nGetLeftEdgePointPosition(), pGuiTedWin_->nGetRightEdgePointPosition(), nCalledPosMin, nCalledPosMax, bError ); } // there are no called bases on the screen if (bError) return; drawCalledBases(nCalledPosMin, nCalledPosMax, eTeditorTypee); } // passed the starting and stopping positions in terms of consensus // position, draws the consensus bases on the TedWin in appropriate // place and color void TedWin :: drawConsensusBases(const int nConsPosMin, const int nConsPosMax) { pGuiTedWin_->guiClearWindow( eConsensusBase ); // clear drawing area // loop through all consensus positions visible in the TedWin for(int nConsensusPos = nConsPosMin; nConsensusPos <= nConsPosMax; ++nConsensusPos ) { // pick up the char representation of the base and it's color char cBase; GuiColorText* pGuiColorText; pContigWinGet()->GetColorAndBaseForConsensus( nConsensusPos, pGuiColorText, cBase ); // draw it in the appropriate window pGuiTedWin_->guiDrawBaseAtSavedPixelPosition(eConsensusBase, nConsensusPos, cBase, pGuiColorText); } // loop through all visible consensus positions // now draw the tags // This is really, really inefficient. Each consensus calls this. // but I can't figure out a simple, bug-free method of calling // it once for all reads. It needs to be called whenever: the window // is resized, the window is scrolled, the master trace is changed, // the horizontal magnification is changed, the color mode is changed, // the user has changed which tags are displayed or whether all // tags are changed, and probably in other situations that I don't // remember. So simplest to just call it whenever we are printing the // tags. DG, 2005. pTeditor_->loadConsensusGuiColorTextArray( nConsPosMin, nConsPosMax); for( int nConsPos= nConsPosMin; nConsPos <= nConsPosMax; ++nConsPos) { if ( !pTeditor_->aConsensusGuiColorTextArray_[ nConsPos ] ) continue; // no tag at this position pGuiTedWin_->guiDrawHalfCharacterTagAtSavedPixelPosition( eConsensusBase, nConsPos, pTeditor_->aConsensusGuiColorTextArray_[ nConsPos ] ); // but now we have overwritten the base, so we should fix it char cBase; GuiColorText* pGuiColorText; pContigWinGet()->GetColorAndBaseForConsensus( nConsPos, pGuiColorText, cBase ); pGuiTedWin_->guiDrawBaseWithoutBackgroundAtSavedPixelPosition( eConsensusBase, nConsPos, cBase, pGuiColorText ); } // now draw separator line pGuiTedWin_->guiDrawConsSepLine(); // draw the cursor if visible drawCursor(true); } // same as above but figure positions for yourself void TedWin :: drawConsensusBases() { if (bScrolledOffScreen() ) return; int nConsPosMin, nConsPosMax; pGuiTedWin_->getSavedRangeOfConsensusPositions( nConsPosMin, nConsPosMax ); // and call above version drawConsensusBases(nConsPosMin, nConsPosMax); } // passed the starting and stopping positions in terms of consensus // position, draws the fragment bases on the TedWin in appropriate // place and color void TedWin :: drawFragmentBases(const int nConsPosMin, const int nConsPosMax) { if ( pContigWinGet()->bMustLoadGuiColorTextArrayForTags() ) loadGuiColorTextArrayForTags( nConsPosMin, nConsPosMax ); pGuiTedWin_->guiClearWindow( eFragmentBase ); // clear drawing area // loop through all consensus positions visible in the TedWin for(int nConsensusPos = nConsPosMin; nConsensusPos <= nConsPosMax; ++nConsensusPos ) { // pick up the char representation of the base and it's color Ntide nt; GuiColorText* pGuiColorText; getFragBaseAndColor(nConsensusPos, nt, pGuiColorText ); char cBase = nt.cGetBaseUpperOrLower(); // draw it in the appropriate window pGuiTedWin_->guiDrawBaseAtSavedPixelPosition(eFragmentBase, nConsensusPos, cBase, pGuiColorText ); if ( bMustLoadGuiColorTextArrayForTags() ) { GuiColorText* pGuiColorTextForTag = pGetGuiColorTextForTag( nConsensusPos ); if (pGuiColorTextForTag ) { pGuiTedWin_->guiDrawHalfCharacterTagAtSavedPixelPosition( eFragmentBase, nConsensusPos, pGuiColorTextForTag ); pGuiTedWin_->guiDrawBaseWithoutBackgroundAtSavedPixelPosition( eFragmentBase, nConsensusPos, cBase, pGuiColorText ); } } } // loop through all visible fragment positions // draw the cursor if visible drawCursor(true); drawHighlightedRegion(); } // same as above but figure positions for yourself void TedWin :: drawFragmentBases() { if (bScrolledOffScreen() ) return; int nConsPosMin, nConsPosMax; pGuiTedWin_->getSavedRangeOfConsensusPositions( nConsPosMin, nConsPosMax ); // and call above version drawFragmentBases(nConsPosMin, nConsPosMax); } GuiColorText* TedWin :: pGetGuiColorTextForTag( const int nConsPos ) { return( aGuiColorTextArray_[ nConsPos - nLeftMostConsPos_ ] ); } void TedWin :: loadGuiColorTextArrayForTags( const int nConsPosMin, const int nConsPosMax ) { nLeftMostConsPos_ = nConsPosMin; aGuiColorTextArray_.resize( nConsPosMax - nConsPosMin + 1 ); for( int nConsPos = nConsPosMin; nConsPos <= nConsPosMax; ++nConsPos ) { aGuiColorTextArray_[ nConsPos - nConsPosMin ] = 0; } for( int nTag = 0; nTag < pLocatedFragment_->nGetNumberOfTags(); ++nTag ) { tag* pTag = pLocatedFragment_->pGetTag( nTag ); if ( !tagTypes::pGetTagTypes()->bCurrentlyShowAllTagTypes_ ) { if ( tagTypes::pGetTagTypes()->bAreTagsOfThisTypeHidden( pTag->soType_ ) ) continue; } int nDrawTagConsPosMin; int nDrawTagConsPosMax; if (pTag->bTagIsOnScreen( nConsPosMin, nConsPosMax, nDrawTagConsPosMin, nDrawTagConsPosMax ) ) { GuiColorText* pGctToUse = tagTypes::pGetTagTypes()->pGetGuiColorTextForTag( pTag ); for( int nConsPos = nDrawTagConsPosMin; nConsPos <= nDrawTagConsPosMax; ++nConsPos ) { if ( aGuiColorTextArray_[ nConsPos - nConsPosMin ] ) aGuiColorTextArray_[ nConsPos - nConsPosMin ] = tagTypes::pGetTagTypes()->pGetGuiColorTextForTagsOverlap(); else aGuiColorTextArray_[ nConsPos - nConsPosMin ] = tagTypes::pGetTagTypes()->pGetGuiColorTextForTag( pTag ); } } // if (bTagIsOnScreen ... } // for (nTag = 0 ... } void TedWin :: drawTraces() { if (bScrolledOffScreen() ) return; bool bDrawDashed = ( pLocFragGet()->soChemistry_ == "solexa" ? true : false ); GuiTedWin::maybeChangeTracesDashedOrNot( bDrawDashed ); pGuiTedWin_->clearTracesWindow(); pGuiTedWin_->drawTrace( 'A' ); pGuiTedWin_->drawTrace( 'C' ); pGuiTedWin_->drawTrace( 'G' ); pGuiTedWin_->drawTrace( 'T' ); } // passed a consensus position, will scroll the TedWin to the // appropriate point position. if the consensus position is // outside the range of the fragment scrolls to the end i.e. // as close as it can get. this relies on the Fragment // member fun to translate from consensus pos to point pos. void TedWin :: scrollToConsPos(const int nRequestedConsPos) { // you can't always get what you want int nGrantedConsPos = nRequestedConsPos; // is the fragment aligned at the passes consensus position? // if not, scroll as far as you can and stop i.e. show trace endpoint if (nGrantedConsPos < pLocatedFragment_->nGetAlignStart()) { nGrantedConsPos = pLocatedFragment_->nGetAlignStart(); } else if (nGrantedConsPos > pLocatedFragment_->nGetAlignEnd()) { nGrantedConsPos = pLocatedFragment_->nGetAlignEnd(); } // now certain base is ok. at what point does that base start? // Why is there the +1? The reason is that the left point boundary // of a base is the mid-point between the two bases. // setBasePixelPositions (below) calls // pLocatedFragment_->getRangeOfConsensusPositions to get the // left-most base position displayed and thus set // nLeftEdgePointPosition_. getRangeOfConsensusPositions calls // Sequence::getIndexRangeFromPointPositions which works as // follows: if the left-most position lies right on the dividing // line, it assigns that point to the base on the left of the // dividing line. Thus we start out by wanting to scroll to // nRequestedConsPos, but afterwards GuiTedWin::nLeftMostConsPos_ // is set to nRequestedConsPos - 1. This caused problems for // scrolling by one base at a time. int nNewScrollBarPosition = pLocatedFragment_->nGetLeftPointBoundaryForBase( nGrantedConsPos ) + 1; // go there pGuiTedWin_->setLeftEdgePointPosition( nNewScrollBarPosition ); pGuiTedWin_->setScrollBarPosition( nNewScrollBarPosition ); setBasePixelPositions(); } // PURPOSE: to allow a controlling routine to scroll the traces // user can see the scroll (not just scroll without visible effect) void TedWin :: scrollToConsPosAndRefresh( const int nConsPos ) { scrollToConsPos( nConsPos ); // this is needed even if the traces are locked together // Otherwise the master won't scroll until it gets a refresh. // (Just drawing master trace.) drawBasesAndTraces( false ); if ( pTeditorGet()->bTedWinsScrollTogether() ) { pTeditorGet()->setGuiTedWinScrollMaster( pGetGuiTedWin() ); // fixes seg fault, Feb 2003, DG when scrolling off window if ( pTeditorGet()->pGuiTeditorGet()->bShowTracesInScrollingWindow_ ) pGuiTedWin_->alignScrollingWindowConsensusToThisTrace(); pTeditorGet()->alignAllTracesToMaster(); pTeditorGet()->refreshAllTedWins( false ); } } // accepts new value for scroll bar position in points, moves // slider, redraws everything void TedWin :: userMovedScrollBar( const int nNewScrollBarPointPosition ) { // sets member data to reflect new point position scrollTedWin( nNewScrollBarPointPosition ); if ( pTeditorGet()->bTedWinsScrollTogether() ) { pTeditorGet()->setGuiTedWinScrollMaster( pGetGuiTedWin() ); pTeditorGet()->alignAllTracesToMaster(); pTeditorGet()->refreshAllTedWins( false ); } } // accepts new value for scroll bar position in points, moves // slider, redraws everything // PURPOSE: when user moves the scroll bar, or when the contig is // complemented, to bring you to the associated location void TedWin :: scrollTedWin( const int nNewScrollBarPointPosition ) { // sets member data to reflect new point position pGuiTedWin_->setLeftEdgePointPosition( nNewScrollBarPointPosition ); if (bScrolledOffScreen() ) { clearTedWin(); return; } pGuiTedWin_->setScrollBarPosition( nNewScrollBarPointPosition ); setBasePixelPositions(); // redraws, reflecting the new pos (now stored in member data) drawBasesAndTraces( false ); } // the mother of all TedWin refresh routines. void TedWin :: drawBasesAndTraces( const bool bRecalculatePositions ) { if (bScrolledOffScreen() ) return; drawTraces(); // draws all trace points currently visible drawVerticalLineThroughTraces(); // from the point position of the edges of the traces visible in // the TedWin, determine what consensus positions are visible. // this information is needed to draw the consensus and fragment // bases as well as the scale int nConsPosMin, nConsPosMax; bool bError; pLocatedFragment_->getRangeOfConsensusPositions( pGuiTedWin_->nGetLeftEdgePointPosition(), pGuiTedWin_->nGetRightEdgePointPosition(), nConsPosMin, nConsPosMax, bError ); if (bError) { // case in which there are traces beyond the end of the read // Thus erase all read information lines--phd, abi, con, edt lines pGuiTedWin_->guiClearWindow( eScaleWindow ); if ( pGuiTedWin_->bShowConsensusLine_ ) pGuiTedWin_->guiClearWindow( eConsensusBase ); pGuiTedWin_->guiClearWindow( eFragmentBase ); if ( pGuiTedWin_->bShowPhredCalledBasesLine_ ) pGuiTedWin_->guiClearWindow( ePhredCalledBase ); if ( pGuiTedWin_->bShowABICalledBases_ ) pGuiTedWin_->guiClearWindow( eABICalledBase ); return; } if ( pGuiTedWin_->bShowPhredCalledBasesLine_ ) drawCalledBases( ePhredCalledBase ); if ( pGuiTedWin_->bShowABICalledBases_ ) drawCalledBases( eABICalledBase ); if ( bRecalculatePositions ) setBasePixelPositions(); // the following 3 routines depend on the saved pixel positions // They know what the saved range of consensus positions is--they // should use that and not rely on the getRangeOfConsensusPositions // above. drawScale( false, pGuiTedWin_->bShowConsensusPositionsLine_ ); // there was a bug in which the consensus was redrawn with // many different reads since bShowConsensusLine_ was changed // to true for each read the cursor was set on but never back to false if ( pTeditorGet()->pGuiTeditor_->bShowTracesInScrollingWindow_ ) { if ( pTeditorGet()->pGetGuiTedWinScrollMaster() == pGuiTedWin_ ) { pTeditorGet()->drawScaleAndConsensusForShowAllTraces(); drawConsensusBases(); } } else if ( pGuiTedWin_->bShowConsensusLine_ ) { drawConsensusBases( ); } drawFragmentBases( ); } // special case of refresh - after complementation of // the Fragment and TraceFile to which object corresponds, // scrolling is required to put the same dna in view at // its new position void TedWin :: refreshAfterCompContig() { // what is your current right edge position? this, complemented, // will become your new left edge positon. int nNewLeftEdgePointPos = pGuiTedWin_->nGetRightEdgePointPosition(); complementPointPosition(nNewLeftEdgePointPos); // make sure we didn't scroll past end if (nNewLeftEdgePointPos < 0 ) { nNewLeftEdgePointPos = 0; } else { // trickier at end. int nMaxAllowedPointPos = (nGetNumberOfPoints() - 1) // last point - (pGuiTedWin_->nGetTraceWindowPointsWide() - 1); if (nNewLeftEdgePointPos > nMaxAllowedPointPos) { nNewLeftEdgePointPos = nMaxAllowedPointPos; } } // scroll to the newly calculated position scrollTedWin(nNewLeftEdgePointPos); // the read sense is flipped by complementation updateReadSense(); } void TedWin :: updateReadSense() { if (pLocatedFragment_->bComp()) { pGuiTedWin_->setReadSenseReverse(); } else { pGuiTedWin_->setReadSenseForward(); } } void TedWin :: continueHighlight( const int nConsPos ) { // only redraw if there is a change in the selection if ( ConsEd::pGetConsEd()->pGetSelection()->nExtendSelection( nConsPos ) != ERR_NO_NEED_TO_EXTEND ) { drawFragmentBases(); drawHighlightedRegion(); } } void TedWin :: startHighlight( const int nConsPos ) { ConsEd::pGetConsEd()->pGetSelection()->startSelection(pLocatedFragment_, 0, // not a contig // selection nConsPos ); drawFragmentBases(); drawHighlightedRegion(); } void TedWin :: drawHighlightedRegion() { int nLeftHighlightConsPos; int nRightHighlightConsPos; LocatedFragment* pLocatedFragment; bool bSelectionActive; Contig* pDummyContig; ConsEd::pGetConsEd()->pGetSelection()->getSelection( nLeftHighlightConsPos, nRightHighlightConsPos, pLocatedFragment, pDummyContig, bSelectionActive ); if (!bSelectionActive ) return; if (pLocFragGet() == pLocatedFragment ) { int nConsPosMinDisplayed; int nConsPosMaxDisplayed; // check that the highlighted region is visible before we try to display // it pGuiTedWin_->getSavedRangeOfConsensusPositions( nConsPosMinDisplayed, nConsPosMaxDisplayed ); if ( nRightHighlightConsPos < nConsPosMinDisplayed ) return; if ( nConsPosMaxDisplayed < nLeftHighlightConsPos ) return; if ( nLeftHighlightConsPos < nConsPosMinDisplayed ) nLeftHighlightConsPos = nConsPosMinDisplayed; if ( nConsPosMaxDisplayed < nRightHighlightConsPos ) nRightHighlightConsPos = nConsPosMaxDisplayed; pGuiTedWin_->guiHighlightBackground( nLeftHighlightConsPos, nRightHighlightConsPos ); drawHighlightedBases( nLeftHighlightConsPos, nRightHighlightConsPos ); } } // highlights the region of the editable bases line by telling GuiTedWin // to redraw void TedWin :: drawHighlightedBases(const int nConsensusPositionLeft, const int nConsensusPositionRight) { for( int nConsensusPos = nConsensusPositionLeft; nConsensusPos <= nConsensusPositionRight; ++nConsensusPos ) { Ntide nt; GuiColorText *pGuiColorText; getHighlightedBaseAndColor(nConsensusPos, nt, pGuiColorText ); char cBase = nt.cGetBaseUpperOrLower(); pGuiTedWin_->guiDrawBaseAtSavedPixelPosition( eFragmentBase, nConsensusPos, cBase, pGuiColorText); } } void TedWin :: highlightFinished() { int nConsensusPosLeft; int nConsensusPosRight; LocatedFragment* pLocatedFragment; bool bSelectionActive; Contig* pDummyContig; // notice that the pLocatedFragment comes from the selection--not from // the TedWin. But the contig comes from the teditor. This is a bug // waiting to happen. Fixed with assert below--DG 971007 ConsEd::pGetConsEd()->pGetSelection()->getSelection(nConsensusPosLeft, nConsensusPosRight, pLocatedFragment, pDummyContig, bSelectionActive); assert( bSelectionActive ); assert( pLocatedFragment == pLocFragGet() ); etypeWhatToDoWithSelection eAction; RWCString soTagComment = ""; askUserWhatToDoWithSelection( eAction, soTagComment ); RWCString soTagType; EditAction* pEditAction; int nConsensusStartPosition; switch( eAction ) { case eMakeHighQuality: pEditAction = new editMakeHighQuality( pLocatedFragment, nConsensusPosLeft, nConsensusPosRight ); break; case eMakeHighQualityAndChangeConsensus: pEditAction = new editMakeHighQualityAndChangeConsensus( pLocatedFragment, nConsensusPosLeft, nConsensusPosRight); break; case eMakeLowQuality: pEditAction = new editMakeLowQuality( pLocatedFragment, nConsensusPosLeft, nConsensusPosRight ); break; case eMakeLowQualityToLeft: nConsensusStartPosition = MAX(nConsensusPosLeft, nConsensusPosRight); pEditAction = new editMakeLowQualityToLeft( pLocatedFragment, nConsensusStartPosition ); break; case eMakeLowQualityToRight: nConsensusStartPosition = MIN(nConsensusPosLeft, nConsensusPosRight); pEditAction = new editMakeLowQualityToRight( pLocatedFragment, nConsensusStartPosition ); break; case eChangeToNs: pEditAction = new editChangeToNs( pLocatedFragment, nConsensusPosLeft, nConsensusPosRight ); break; case eChangeToNsToLeft: nConsensusStartPosition = MAX(nConsensusPosLeft, nConsensusPosRight); pEditAction = new editChangeToNsToLeft( pLocatedFragment, nConsensusStartPosition ); break; case eChangeToNsToRight: nConsensusStartPosition = MIN( nConsensusPosLeft, nConsensusPosRight ); pEditAction = new editChangeToNsToRight( pLocatedFragment, nConsensusStartPosition ); break; case eChangeToXsToLeft: nConsensusStartPosition = MAX( nConsensusPosLeft, nConsensusPosRight ); pEditAction = new editChangeToXs( pLocatedFragment, pLocatedFragment->nGetAlignStart(), nConsensusStartPosition, 'l' ); break; case eChangeToXsToRight: nConsensusStartPosition = MIN( nConsensusPosLeft, nConsensusPosRight ); pEditAction = new editChangeToXs( pLocatedFragment, nConsensusStartPosition, pLocatedFragment->nGetAlignEnd(), 'r' ); break; case eAddTag: // there is plenty of additional information that must be // gathered from the user here. The user has an opportunity to // cancel at every point, and thus there must be a way to // exit from this case. The method is provided by the // goto dismiss_label that goes to the dismiss case and // cleans up. { bool bUserPushedCancel; guiGetTagType* pGuiGetTagType = new guiGetTagType(); RWCString soTemp; pGuiGetTagType->popupBoxAndWaitForUserToSelectTagType( soTagType, bUserPushedCancel, true, // only tags that can be // created by swiping. // exclude edit and overlap tags tagType::read, true, // bAllowUserToEnterComment soTagComment, soTemp ); delete pGuiGetTagType; if ( bUserPushedCancel ) { eAction = eDismiss; goto dismiss_label; } tag* pTag = tagTypes::pGetTagTypes()->pCreateReadTag( soTagType, soTagComment, nConsensusPosLeft, nConsensusPosRight, pLocatedFragment, true, // bWriteToPhdFileNotAceFile // read tags added by user swiping // must go into phd file to be saved // through re-assembly bUserPushedCancel ); if (bUserPushedCancel ) { delete pTag; eAction = eDismiss; goto dismiss_label; } pEditAction = new editAddReadTag( pTag ); if ( ConsEd::pGetConsEd()->pGetSelection()->bUserMovedPointerToEdgeOfWindow_ ) { popupInfoMessage( pTeditor_->pGuiTeditorGet()->widGetGuiTeditorShell(), "Were you trying to create a tag that extends beyond the portion of the read visible on the screen? If so, this is how you do that: point to the tag you just created in the Traces Window, and click the right mouse button. This will popup a box describing the tag you just created. It will specify the Start Unpadded Consensus Position and the End Unpadded Consensus Position. You can change those values simply by clicking on them and typing over them. Then click the \'Save Changes\' button." ); } } break; case eDismiss: dismiss_label: { // clear selection and unhighlight the region ConsEd::pGetConsEd()->pGetSelection()->unsetSelection(); drawFragmentBases(); return; } } // set the flag indicating that this window was the guy // who created the edit action, so activate his undo button // and deactivate all others when the setUndoButtonState message // comes back bJustCreatedEditAction_ = true; // the edit action, once formed, goes all the way up to // the consed. any in-between objects will get notified // on the way back down by the refresh message (if the edit // completes successfully ConsEd::pGetConsEd()->doEditAction( pEditAction, true ); // clear selection ConsEd::pGetConsEd()->pGetSelection()->unsetSelection(); drawFragmentBases(); } void TedWin :: userPressedHotKey( const etypeWhatToDoWithSelection eAction ) { EditCursor* pEditCursor = pContigWinGet()->pGetEditCursor(); // is it valid? if (! pEditCursor->bCursorValid()) { GuiApp :: popupErrorMessage( "You must first set the cursor on the read you want to edit." ); return; } // is it on a located fragment, and if so, on this located frag? if (! pEditCursor->bCursorOnFrag()) { GuiApp :: popupErrorMessage( "The cursor must be on the read for you to edit the read." ); return; } if (pEditCursor->pLocFragGet() != pLocatedFragment_) { GuiApp :: popupErrorMessage( "The cursor must be set on the read you want to edit." ); return; } if ( bScrolledOffScreen()) { GuiApp :: popupErrorMessage( "Please put the cursor where you want to edit." ); return; } int nConsPos = pEditCursor->nConsPosGet(); EditAction* pEditAction; if ( eAction == eChangeToNsToRight ) pEditAction = new editChangeToNsToRight( pLocatedFragment_, nConsPos ); else if (eAction == eChangeToNsToLeft ) { pEditAction = new editChangeToNsToLeft( pLocatedFragment_, nConsPos ); } else if (eAction == eMakeLowQualityToLeft ) { pEditAction = new editMakeLowQualityToLeft( pLocatedFragment_, nConsPos ); } else if ( eAction == eMakeLowQualityToRight ) { pEditAction = new editMakeLowQualityToRight( pLocatedFragment_, nConsPos ); } else if ( eAction == eAddPolymorphismTag ) { tag* pTag = new tag( pLocatedFragment_, NULL, "polymorphism", nConsPos, nConsPos, true, // bWriteToPhdFileNotAceFile_ // read tag created by user pushing // polymorphism hot key goes into phd file soEmptyString, // soComment "consed", soEmptyString, // current date false ); // no NoTrans pEditAction = new editAddReadTag( pTag ); } else { return; } // set the flag indicating that this window was the guy // who created the edit action, so activate his undo button // and deactivate all others when the setUndoButtonState message // comes back bJustCreatedEditAction_ = true; // the edit action, once formed, goes all the way up to // the consed. any in-between objects will get notified // on the way back down by the refresh message (if the edit // completes successfully ConsEd::pGetConsEd()->doEditAction( pEditAction, true ); } void TedWin :: setFragCursor(const int nConsPos ) { // set the cursor by telling your parent contig win. // let it be responsible for all refreshes, etc. pContigWinGet()->moveCursorToFragPos(nConsPos,pLocatedFragment_); pTeditorGet()->drawTracesOfAllTedWins(); pTeditorGet()->drawVerticalLineThroughTracesOfAllTedWins( nConsPos ); } void TedWin :: setConsCursor(const int nConsPos ) { // set the cursor by telling your parent contig win. // let it be responsible for all refreshes, etc. pContigWinGet()->moveCursorToConsPos(nConsPos); } void TedWin :: drawScale(const int nConsPosMin, const int nConsPosMax, const bool bDrawInShowAllTracesConsensusWindow, const bool bDrawConsensusPositions ) { // clear the scale window if ( bDrawInShowAllTracesConsensusWindow ) pGuiTedWin_->guiClearWindow( eShowAllTracesScaleWindow ); else pGuiTedWin_->guiClearWindow( eScaleWindow ); // pGuiTedWin_->calculateBaselineForReadAndConsensusNumbers(); // always draw the line above the tick marks and the line that // separates consensus bases from fragment bases pGuiTedWin_->guiDrawScaleLine( bDrawInShowAllTracesConsensusWindow ); for(int nConsPos = nConsPosMin; nConsPos <= nConsPosMax; ++nConsPos ) { int nFragPosToDraw; int nConsPosToDraw; if ( ! consedParameters::pGetConsedParameters()->bCountPads_ ) { int nOrientedUnpaddedFragPos = pLocatedFragment_->nOrientedUnpaddedFragPosFromConsPos( nConsPos ); int nUnpaddedConsPos = pGetContig()->nUnpaddedIndex( nConsPos ); nFragPosToDraw = nOrientedUnpaddedFragPos; nConsPosToDraw = nUnpaddedConsPos; } else { int nOrientedPaddedFragPos = pLocatedFragment_->nOrientedFragPosFromConsPos( nConsPos); nFragPosToDraw = nOrientedPaddedFragPos; nConsPosToDraw = nConsPos; } // only draw number if room, otherwise draw every fifth if ( (! pGetContig()->ntGetCons(nConsPos).bIsPad()) || (consedParameters::pGetConsedParameters()->bCountPads_ ) ) { bool bDrawBigTick = ( ( nConsPosToDraw % 5 ) == 0 ); pGuiTedWin_->guiDrawScaleTick( nConsPos, bDrawBigTick, bDrawInShowAllTracesConsensusWindow ); if ( (nConsPosToDraw % 5) == 0 ) { if ( bDrawConsensusPositions ) pGuiTedWin_->guiDrawScaleNumber( nConsPosToDraw, nConsPos, eConsensusPosition, bDrawInShowAllTracesConsensusWindow ); if ( !bDrawInShowAllTracesConsensusWindow ) pGuiTedWin_->guiDrawScaleNumber( nFragPosToDraw, nConsPos, eFragmentPosition, bDrawInShowAllTracesConsensusWindow ); } } } } // same as above but calculate your own consensus range void TedWin :: drawScale( const bool bDrawInShowAllTracesConsensusWindow, const bool bDrawConsensusPositions ) { if (bScrolledOffScreen() ) return; int nConsPosMin, nConsPosMax; pGuiTedWin_->getSavedRangeOfConsensusPositions( nConsPosMin, nConsPosMax ); // and call above version drawScale(nConsPosMin, nConsPosMax, bDrawInShowAllTracesConsensusWindow, bDrawConsensusPositions ); } // get pointer to the ContigWin that created you from your parent Teditor ContigWin* TedWin :: pContigWinGet() { return pTeditor_->pContigWinGet(); } // if passed true, draw the cursor at the current position // if passed false, draw the normal (non-cursor) background again // checks first to see if cursor is valid and in view void TedWin :: drawCursor(const bool bMakeVisible) { // get the pointer from the ContigWin EditCursor* pEditCursor = pContigWinGet()->pGetEditCursor(); // is it valid? if (! pEditCursor->bCursorValid()) return; // is it on a located fragment, and if so, on this located frag? if (! pEditCursor->bCursorOnFrag()) return; if (pEditCursor->pLocFragGet() != pLocatedFragment_) // wrong fragment return; if ( bScrolledOffScreen()) return; // is the cursor within the range of consensus positions // currently displayed in this TedWin? int nConsPosMin, nConsPosMax; pGuiTedWin_->getSavedRangeOfConsensusPositions( nConsPosMin, nConsPosMax ); if ((pEditCursor->nConsPosGet() < nConsPosMin) || (pEditCursor->nConsPosGet() > nConsPosMax)) { // no, not within range return; } // draw cursor on the fragment Ntide nt = pLocatedFragment_->ntGetFragFromConsPos(pEditCursor->nConsPosGet()); char cBase = nt.cGetBaseUpperOrLower(); // figure it's appropriate graphics context GuiColorText* pGuiColorText; if (bMakeVisible && pEditCursor->bGetBlinkState()) { // drawing cursor, and blink state is on // so use cursor graphics context pGuiColorText = pGuiTedWin_->pGetGuiColorTextForConsensusCursor(); // draw the fragment base pGuiTedWin_->guiDrawBaseAtSavedPixelPosition(eFragmentBase, pEditCursor->nConsPosGet(), cBase, pGuiColorText ); } else { pGuiColorText = pGetGuiColorTextForSameAsContigWin(pEditCursor->nConsPosGet()); pGuiTedWin_->guiDrawBaseAtSavedPixelPosition(eFragmentBase, pEditCursor->nConsPosGet(), cBase, pGuiColorText ); if (bMustLoadGuiColorTextArrayForTags() ) { // it is possible this is called from drawConsensusBases // after scrolling and the array hasn't yet been set loadGuiColorTextArrayForTags( nConsPosMin, nConsPosMax ); GuiColorText* pGuiColorTextForTag = pGetGuiColorTextForTag( pEditCursor->nConsPosGet() ); if ( pGuiColorTextForTag ) { pGuiTedWin_->guiDrawHalfCharacterTagAtSavedPixelPosition( eFragmentBase, pEditCursor->nConsPosGet(), pGuiColorTextForTag ); pGuiTedWin_->guiDrawBaseWithoutBackgroundAtSavedPixelPosition( eFragmentBase, pEditCursor->nConsPosGet(), cBase, pGuiColorText ); } } } // if (bMakeVisible && pEditCursor->bGetBlnkState() ) else } // gets an overstrike edit event message from the Gui, passes // it along to the ConsEd after consulting the EditCursor // (and not the event's x,y coords) to see where it should go void TedWin :: userOverstruckNtide(const char c) { // pick up the particulars of where from to overstrike // from the edit cursor (via the contigwin) Contig* pContig = pContigWinGet()->pGetEditCursor()->pGetContig(); LocatedFragment* pLocFrag = pContigWinGet()->pGetEditCursor()->pLocFragGet(); int nConsPos = pContigWinGet()->pGetEditCursor()->nConsPosGet(); // The user can put the cursor on a read that doesn't have the // fragment up. This would cause the fragment data structure to // not match the phd file, and thus cause problems. So don't allow // editing of reads if the traces have not been brought up. if (pLocFrag != pLocFragGet() ) { GuiApp::popupErrorMessage( "use mouse button 1 to set cursor in trace window before trying to overstrike a base" ); return; } char cLower = tolower( c ); if ( cLower != 'a' && cLower != 'c' && cLower != 'g' && cLower != 't' && cLower != 'x' && cLower != 'n' && cLower != '*' && pCP->bWarnUserAboutAmbiguityCodes_ ) { RWCString soMessage = "You typed ambiguity code "; soMessage += c; soMessage += " Are you sure? (Note: if you answer \"yes\" you will not receive this message again this consed session.)"; if ( bGuiGetAnswerYesNo( soMessage ) ) { pCP->bWarnUserAboutAmbiguityCodes_ = false; } else { return; } } // the cursor may be on the correct read, but may be off screen // Don't allow editing in this way--the user must see the peak to // overstrike. bool bCursorVisible = false; if ( ! bScrolledOffScreen() ) { int nConsPosMin; int nConsPosMax; pGetGuiTedWin()->getSavedRangeOfConsensusPositions( nConsPosMin, nConsPosMax ); if (nConsPosMin <= nConsPos && nConsPos <= nConsPosMax ) bCursorVisible = true; } if ( !bCursorVisible ) { GuiApp::popupErrorMessage( "use mouse button 1 to set cursor in trace window before trying to overstrike a base" ); return; } bool bMakeHighQuality = false; if (isalpha( c ) && isupper( c ) ) { bMakeHighQuality = true; if ( consedParameters::pGetConsedParameters()->bWarnUserAboutOverstrikingWithUppercase_ ) { bMakeHighQuality = bGuiGetAnswerYesNo( "You have overstruck a base with an uppercase letter. \nThis means the new base will be made high quality for purposes of reassembly. \nNormally we suggest that you make it low quality. \nAre you sure you want to make it high quality?" ); if ( bMakeHighQuality ) { bool bWarnNextTime = bGuiGetAnswerYesNo( "Do you want this warning next time?" ); consedParameters::pGetConsedParameters()->bWarnUserAboutOverstrikingWithUppercase_ = bWarnNextTime; } } } // cursor on consensus or fragment? Couldn't be consensus. DG 8/01 assert( !pContigWinGet()->pGetEditCursor()->bCursorOnCons()); int nOldPointPos = pLocFrag->nGetPointPosByConsPos( nConsPos ); Quality ucQuality = ( bMakeHighQuality ) ? ucQualityHighEdited : ucQualityLowEdited; // form the new ntide Ntide ntNew(tolower(c), // passed char, // internally, all chars should be lowercase ucQuality ); // form the edit action EditOverstrike* pEdOv = new EditOverstrike(pContigWinGet()->pGetEditCursor()->pLocFragGet(), nConsPos, // position ALWAYS supplied ntNew); // newly formed ntide // set the flag indicating that this window was the guy // who created the edit action, so activate his undo button // and deactivate all others when the setUndoButtonState message // comes back bJustCreatedEditAction_ = true; // tell the ConsEd ConsEd::pGetConsEd()->doEditAction(pEdOv, true ); pContigWinGet()->moveCursorToNextReadPos( pLocFrag ); } // gets an "insert-column-of-pads" message from the Gui, passes // it along to the ConsEd after consulting the EditCursor // (and not the event's x,y coords) to see where it should go void TedWin :: insertColumnOfPads() { int nConsPos = pContigWinGet()->pGetEditCursor()->nConsPosGet(); EditInsertColOfPads* pEdColPads = new EditInsertColOfPads(pGetContig(), // ALWAYS needs contig nConsPos ); // set the flag indicating that this window was the guy // who created the edit action, so activate his undo button // and deactivate all others when the setUndoButtonState message // comes back bJustCreatedEditAction_ = true; // tell the ConsEd ConsEd::pGetConsEd()->doEditAction(pEdColPads, true); } // set the Undo button to active or inactive according to whether // or not this TedWin initiated the last edit. this is indicated // by flag bJustCreatedEditAction_ in the TedWin. The flag is // set when the edit action is initiated, cleared when the button // actually gets activated. That way when _another_ window initiates // an edit action, this one's button gets deactivated. void TedWin :: setUndoButtonState() { if (bJustCreatedEditAction_) { pGuiTedWin_->activateUndoButton(); // activate the button bJustCreatedEditAction_ = false; } else { pGuiTedWin_->deactivateUndoButton(); } } void TedWin :: askUserWhatToDoWithSelection( etypeWhatToDoWithSelection& eWhatToDoWithSelection, RWCString& soTagComment ) { guiWhatToDoWithSelection* pGuiWhatToDoWithSelection = new guiWhatToDoWithSelection(); pGuiWhatToDoWithSelection->popupAndGetAnswer( eWhatToDoWithSelection, soTagComment ); delete pGuiWhatToDoWithSelection; } void TedWin :: setBasePixelPositions() { pGuiTedWin_->clearBasePixelPositions(); int nConsPosMin; int nConsPosMax; bool bError; pLocatedFragment_->getRangeOfConsensusPositions( pGuiTedWin_->nGetLeftEdgePointPosition(), pGuiTedWin_->nGetRightEdgePointPosition(), nConsPosMin, nConsPosMax, bError ); if (bError) return; pGuiTedWin_->setLeftMostConsPos( nConsPosMin ); for( int nConsPos = nConsPosMin; nConsPos <= nConsPosMax; ++nConsPos ) { int nPointPosition = pLocatedFragment_->nGetPointPosByConsPos( nConsPos ); pGuiTedWin_->guiSetBasePixelPosition( nConsPos, nPointPosition ); } } bool TedWin :: bScrolledOffScreen() { // if the window is off the left of the trace, don't draw anything // if the window is off the right of the trace, don't draw anything if (pGuiTedWin_->nGetRightEdgePointPosition() < 0 ) return( true ); if ( nGetNumberOfPoints() - 1 < pGuiTedWin_->nGetLeftEdgePointPosition()) return (true ); return( false ); } void TedWin :: clearTedWin() { if ( pGuiTedWin_->bShowABICalledBases_ ) pGuiTedWin_->guiClearWindow( eABICalledBase ); if ( pGuiTedWin_->bShowPhredCalledBasesLine_ ) pGuiTedWin_->guiClearWindow( ePhredCalledBase ); if ( pGuiTedWin_->bShowConsensusLine_ ) pGuiTedWin_->guiClearWindow( eConsensusBase ); pGuiTedWin_->guiClearWindow( eFragmentBase ); pGuiTedWin_->guiClearWindow( eScaleWindow ); pGuiTedWin_->clearTracesWindow(); } void TedWin :: userChangedHorizontalMagnification() { pGuiTedWin_->resizeSlider(); setBasePixelPositions(); drawBasesAndTraces( false ); if ( pTeditorGet()->bTedWinsScrollTogether() ) { pTeditorGet()->setGuiTedWinScrollMaster( pGetGuiTedWin() ); pTeditorGet()->alignAllTracesToMaster(); pTeditorGet()->refreshAllTedWins( false ); } } bool TedWin :: bMustLoadGuiColorTextArrayForTags() { return( pContigWinGet()->bMustLoadGuiColorTextArrayForTags() ); } void TedWin :: popupTags( const int nPixelX ) { int nConsPos = pGuiTedWin_->nConsPosFromPixelX( nPixelX ); int nNumberOfTagsPoppedUp = 0; for( int n = 0; n < pLocatedFragment_->nGetNumberOfTags(); ++n ) { tag* pTag = pLocatedFragment_->pGetTag( n ); if (pTag->bTouchesThisConsPos( nConsPos ) ) { pTag->popupTagInfoForOneTag( nNumberOfTagsPoppedUp, (void*) pTeditor_->pGuiTeditorGet(), false ); // bIsGuiContigWin ++nNumberOfTagsPoppedUp; } } } void TedWin :: drawVerticalLineThroughTraces( const int nConsPos ) { // now we may not be the read that the cursor is on // That's ok. We will draw the vertical line through the corresponding // peak anyway. if ( ( pLocatedFragment_->nGetAlignStart() <= nConsPos ) && ( nConsPos <= pLocatedFragment_->nGetAlignEnd() ) ) { int nPointPos = pLocatedFragment_->nGetPointPosByConsPos( nConsPos ); if ( ( pGuiTedWin_->nGetLeftEdgePointPosition() <= nPointPos ) && ( nPointPos <= pGuiTedWin_->nGetRightEdgePointPosition() ) ) { pGuiTedWin_->guiDrawVerticalLineThroughTraces( nPointPos ); } } } void TedWin :: drawVerticalLineThroughTraces() { // now draw vertical line through traces where the cursor is EditCursor* pEditCursor = pContigWinGet()->pGetEditCursor(); // is it valid? if ( pEditCursor->bCursorValid()) { int nConsPosOfCursor = pEditCursor->nConsPosGet(); drawVerticalLineThroughTraces( nConsPosOfCursor ); } } void TedWin :: userPushedArrowKey( const bool bLeftArrowNotRightArrow ) { EditCursor* pEditCursor = pContigWinGet()->pGetEditCursor(); if ( ! pEditCursor->bCursorValid() ) return; if ( ! pEditCursor->bCursorOnFrag() ) return; if ( pEditCursor->pLocFragGet() != pLocatedFragment_ ) return; int nConsPos = pEditCursor->nConsPosGet() + ( bLeftArrowNotRightArrow ? -1 : 1 ); if ( nConsPos < pLocatedFragment_->nGetAlignStart() || pLocatedFragment_->nGetAlignEnd() < nConsPos ) { GuiApp::beep(); return; } setFragCursor( nConsPos ); int nConsPosMin, nConsPosMax; pGuiTedWin_->getSavedRangeOfConsensusPositions( nConsPosMin, nConsPosMax ); if ( nConsPos <= nConsPosMin || nConsPosMax <= nConsPos ) { scrollToConsPosAndRefresh( nConsPos - nOffsetToPutBaseInTheMiddle ); } } bool TedWin :: bCursorVisible() { // I don't find this useful because the cursor can be just barely visible, // and this still returns true int nConsPosMin, nConsPosMax; pGuiTedWin_->getSavedRangeOfConsensusPositions( nConsPosMin, nConsPosMax ); int nConsPosOfCursor = pContigWinGet()->pGetEditCursor()->nConsPosGet(); if ( nConsPosMin <= nConsPosOfCursor && nConsPosOfCursor <= nConsPosMax ) return( true ); else return( false ); } void TedWin :: userPressedUserDefinedKey( const RWCString& soProgram, const RWCString& soArgument, const RWCString& soTagToApply ) { // pick up the particulars of where the cursor is // from the edit cursor (via the contigwin) LocatedFragment* pLocFrag = pContigWinGet()->pGetEditCursor()->pLocFragGet(); int nConsPos = pContigWinGet()->pGetEditCursor()->nConsPosGet(); // The user can put the cursor on a read that doesn't have the // fragment up. This would cause the fragment data structure to // not match the phd file, and thus cause problems. So don't allow // editing of reads if the traces have not been brought up. if (pLocFrag != pLocFragGet() ) { GuiApp::popupErrorMessage( "use mouse button 1 to set cursor in trace window before striking this key" ); return; } // the cursor may be on the correct read, but may be off screen // Don't allow editing in this way--the user must see the peak to // overstrike. bool bCursorVisible = false; if ( ! bScrolledOffScreen() ) { int nConsPosMin; int nConsPosMax; pGetGuiTedWin()->getSavedRangeOfConsensusPositions( nConsPosMin, nConsPosMax ); if (nConsPosMin <= nConsPos && nConsPos <= nConsPosMax ) bCursorVisible = true; } if ( !bCursorVisible ) { GuiApp::popupErrorMessage( "use mouse button 1 to set cursor in trace window before trying to overstrike a base" ); return; } if ( soTagToApply != "none" && !tagTypes::pGetTagTypes()->bIsAValidTagType( soTagToApply ) ) { PANIC_OST( ost ) << "unrecognized tag type for user defined key: \"" << soTagToApply << "\"" << endl; ost << "See Info/Show Current Consed Resources:\nconsed.tagsToApplyWithUserDefinedKeys" << ends; InputDataError ide( ost.str() ); throw ide; } int nUnpaddedSeqPosInDirectionOfSequencing = pLocFrag->nOrientedUnpaddedFragPosFromConsPos( nConsPos ); int nUnpadded = pLocFrag->pContig_->nUnpaddedIndex( nConsPos ); char cBase = pLocFrag->ntGetFragFromConsPos( nConsPos ).cGetBase(); int nQuality = pLocFrag->ntGetFragFromConsPos( nConsPos ).qualGetQuality(); RWCString soCommandLine = soProgram + " " + soArgument + " " + pLocFrag->soGetName() + " " + RWCString( (long) nUnpaddedSeqPosInDirectionOfSequencing ) + " " + pLocFrag->pContig_->soGetName() + " " + RWCString( (long) nUnpadded ) + " " + RWCString( (long) nConsPos ) + " " + RWCString( cBase ) + " " + RWCString( (long) nQuality ) + " " + ConsEd::pGetAssembly()->filGetAceFileFullPathname() + " " + "tr.window"; int nReturnStatus = system( soCommandLine.data() ); if ( nReturnStatus != 0 ) { PANIC_OST( ost ) << "unable to run command " << soCommandLine << " because of return status " << nReturnStatus << ends; SysRequestFailed srf( ost.str() ); srf.includeErrnoDescription(); throw srf; } if ( soTagToApply != "none" ) { tag* pTag = new tag( pLocFrag, NULL, soTagToApply, nConsPos, nConsPos, true, // bWriteToPhdFileNotAceFile_ // read tag created by user pushing // polymorphism hot key goes into phd file soEmptyString, // soComment "consed", soEmptyString, // current date false ); // no NoTrans EditAction* pEditAction = new editAddReadTag( pTag ); ConsEd::pGetConsEd()->doEditAction( pEditAction, true ); } } // what happens when scrolling timer expires void TedWin :: automaticScrollingTimer() { automaticallyScroll(); int nConsPosLeftMost; int nConsPosRightMost; pGuiTedWin_->getSavedRangeOfConsensusPositions( nConsPosLeftMost, nConsPosRightMost ); if ( pGuiTedWin_->bAutomaticallyScrollLeftNotRight_ ) { continueHighlight( nConsPosLeftMost ); } else { continueHighlight( nConsPosRightMost ); } } void TedWin :: automaticallyScroll() { int nConsPosLeftMost; int nConsPosRightMost; pGuiTedWin_->getSavedRangeOfConsensusPositions( nConsPosLeftMost, nConsPosRightMost ); if ( pGuiTedWin_->bAutomaticallyScrollLeftNotRight_ ) { nConsPosLeftMost -= pCP->nWhenUserScrollsOffWindowBasesToScrollEachTime_; if ( nConsPosLeftMost < pLocatedFragment_->nGetAlignStart() ) { GuiApp::beep(); return; } } else { nConsPosRightMost += pCP->nWhenUserScrollsOffWindowBasesToScrollEachTime_; nConsPosLeftMost += pCP->nWhenUserScrollsOffWindowBasesToScrollEachTime_; if ( nConsPosRightMost > pLocatedFragment_->nGetAlignEnd() ) { GuiApp::beep(); return; } } scrollToConsPosAndRefresh( nConsPosLeftMost ); } // when bringing up all traces, to set the location of the master // trace. (All other traces are then aligned to it.) void TedWin :: scrollToConsPosInCenter( const int nConsPosInCenter ) { // we want to put the cursor in the middle of the window. // So figure out how many bases wide the screen is. int nPointsAcrossHalfOfScreen = pGuiTedWin_->nGetTraceWindowPointsWide() / 2; int nPointInMiddleOfScreen = pLocatedFragment_->nGetPointPosByConsPos( nConsPosInCenter ); int nPointAtLeftHandOfScreen = nPointInMiddleOfScreen - nPointsAcrossHalfOfScreen; // now let's try to find a base that is at or just after this // point position int nConsPosMin = pLocatedFragment_->nGetAlignStart(); int nFoundConsPos; bool bFound = false; for( int nConsPos = nConsPosInCenter; nConsPos >= nConsPosMin && !bFound; --nConsPos ) { if ( pLocatedFragment_->nGetPointPosByConsPos( nConsPos ) < nPointAtLeftHandOfScreen ) { nFoundConsPos = nConsPos + 1; bFound = true; } } if ( !bFound ) { // how could this occur? If the point positions are all // greater than this nFoundConsPos = nConsPosMin; } // set the initial slider pos in terms of (aligned) consensus position // put the clicked upon base a bit inside the window scrollToConsPos( nFoundConsPos ); }