/***************************************************************************** # 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 "assemblyView.h" #include "locatedFragment.h" #include "contig.h" #include "consedParameters.h" #include "bIntersect.h" #include "clScaffold.h" #include "rwcstring.h" #include "tag.h" #include "tagTypes.h" const int nPixelWidthOfTagCell = 2; static inline void getPixelXRangeForTagCell( const int nTagCell, int& nPixelXLeft, int& nPixelXRight ) { // note that nTagCell starts at 0 nPixelXLeft = nTagCell * nPixelWidthOfTagCell; nPixelXRight = nPixelXLeft + nPixelWidthOfTagCell - 1; } static inline int nGetTagCellIndexFromPixelX( const int nPixelX ) { return( nPixelX / nPixelWidthOfTagCell ); } static assemblyViewTagTypeAndLine avtalDummy( "", 0 ); bool assemblyView :: bIsThisADesiredTagType( const RWCString& soTagType, int& nLineWithinTagBar ) { avtalDummy.soTagType_ = soTagType; int nIndex = pCP->aAssemblyViewDisplayTheseTagTypes_.indexFast( &avtalDummy ); if ( nIndex == RW_NPOS ) { return( false ); } else { nLineWithinTagBar = pCP->aAssemblyViewDisplayTheseTagTypes_[ nIndex ]->nLine_; return( true ); } } int assemblyView :: nGetTagCellIndexFromContigBase( const int nScaffold, Contig* pContig, const int nUnpadded ) { int nScaffoldPos = pContig->nGetScaffoldPosFromUnpaddedConsPos( nUnpadded ); int nPixelX = nGetPixelXFromScaffoldPos( nScaffold, nScaffoldPos ); int nTagCellIndex = nGetTagCellIndexFromPixelX( nPixelX ); return( nTagCellIndex ); } void assemblyView :: getConsPosRangeOfTagCell( const int nCellIndex, const int nScaffold, Contig* pContig, int& nConsPosLow, int& nConsPosHigh, bool& bProblems ) { // first convert to pixels int nCellPixelXLeft; int nCellPixelXRight; getPixelXRangeForTagCell( nCellIndex, nCellPixelXLeft, nCellPixelXRight ); int nContigPixelXLeft = nGetPixelXFromScaffoldPos( nScaffold, pContig->nClonePosLeft_ ); int nContigPixelXRight = nGetPixelXFromScaffoldPos( nScaffold, pContig->nClonePosRight_ ); int nClonePosLeft; int nClonePosRight; if ( nContigPixelXLeft != nContigPixelXRight ) { // figure out the ratio of pixels per scaffold (clone) positions double dClonePerPixel = ( (double) pContig->nClonePosRight_ - (double) pContig->nClonePosLeft_ ) / ( (double) nContigPixelXRight - (double) nContigPixelXLeft ); // use the point nContigPixelXLeft of pContig->nClonePosLeft_ as the // fixed point to use the ratio above to find any other point nClonePosLeft = ( nCellPixelXLeft - nContigPixelXLeft ) * dClonePerPixel + pContig->nClonePosLeft_; nClonePosRight = ( nCellPixelXRight - nContigPixelXLeft ) * dClonePerPixel + pContig->nClonePosLeft_; } else { // pathological case in which the contig is a tiny 1 pixel sliver. // In this case, we really can't resolve the contig position. nClonePosLeft = pContig->nClonePosLeft_; nClonePosRight = pContig->nClonePosRight_; } int nUnpaddedLeft = pContig->nGetUnpaddedConsPosFromScaffoldPosUnsafe( nClonePosLeft ); int nUnpaddedRight = pContig->nGetUnpaddedConsPosFromScaffoldPosUnsafe( nClonePosRight ); nConsPosLow = pContig->nPaddedIndexFast( nUnpaddedLeft ); nConsPosHigh = pContig->nPaddedIndexFast( nUnpaddedRight ); if ( nConsPosHigh < nConsPosLow ) { // switch them int nTemp = nConsPosHigh; nConsPosHigh = nConsPosLow; nConsPosLow = nTemp; } bProblems = false; } void assemblyView :: getTagCellRangeForTag( Contig* pContig, const int nScaffold, tag* pTag, int& nTagCellStart, int& nTagCellEnd, bool& bNotOnScreen ) { int nUnpaddedConsPosStart = pContig->nUnpaddedIndex( pTag->nPaddedConsPosStart_ ); int nUnpaddedConsPosEnd = pContig->nUnpaddedIndex( pTag->nPaddedConsPosEnd_ ); nTagCellStart = nGetTagCellIndexFromContigBase( nScaffold, pContig, nUnpaddedConsPosStart ); nTagCellEnd = nGetTagCellIndexFromContigBase( nScaffold, pContig, nUnpaddedConsPosEnd ); if ( nTagCellEnd < nTagCellStart ) { int nTemp = nTagCellEnd; nTagCellEnd = nTagCellStart; nTagCellStart = nTemp; } // now the calculated tag cells may be off the screen. So // put them back on it. int nMinTagCell = 0; int nMaxTagCell = nNumberOfColumnsOfTagCells_ - 1; if ( bIntersect( nTagCellStart, nTagCellEnd, nMinTagCell, nMaxTagCell, nTagCellStart, nTagCellEnd ) ) { bNotOnScreen = false; } else { bNotOnScreen = true; } } void assemblyView :: calculateTagLines() { if ( !pCP->bAssemblyViewShowTags_ ) return; nNumberOfColumnsOfTagCells_ = nGetAssemblyViewWindowWidth() / nPixelWidthOfTagCell; aScaffoldRowTagBars_.clearAndDestroy(); for( int nScaffoldRow = 0; nScaffoldRow < nNumberOfScaffoldRows_; ++nScaffoldRow ) { RWCString soName = "assemblyView::aScaffoldRowTagBars_["; soName += RWCString( (long) nScaffoldRow ); soName += "]"; scaffoldLineTagBar* pScaffoldLineTagBar = new RWT2DPtrVector( nNumberOfColumnsOfTagCells_, pCP->nAssemblyViewNumberOfRowsOfTags_, soName ); aScaffoldRowTagBars_.insert( pScaffoldLineTagBar ); } // go through all the tags and see, for each one, whether it is // desired for ( int nScaffold = 0; nScaffold < aScaffolds_.length(); nScaffold++) { clScaffold* pScaffold = aScaffolds_[ nScaffold ]; int nScaffoldRow = pScaffold->nScaffoldRow_; scaffoldLineTagBar* pScaffoldLineTagBar = aScaffoldRowTagBars_[ nScaffoldRow ]; for( int nContig = 0; nContig < pScaffold->aContigs_.length(); ++nContig ) { Contig* pContig = pScaffold->aContigs_[ nContig ]; // go through consensus tags first for( int nConsensusTag = 0; nConsensusTag < pContig->nGetNumberOfTags(); ++nConsensusTag ) { tag* pTag = pContig->pGetTag( nConsensusTag ); int nLineWithinTagBar; if ( !bIsThisADesiredTagType( pTag->soType_, nLineWithinTagBar ) ) continue; // so we need to show this tag // Let's figure out which cells this tag intersects. int nTagCellStart; int nTagCellEnd; bool bNotOnScreen; getTagCellRangeForTag( pContig, nScaffold, pTag, nTagCellStart, nTagCellEnd, bNotOnScreen ); if ( bNotOnScreen ) continue; // check each cell in turn seeing if there are any non-pads // that overlap that cell for( int nCellIndex = nTagCellStart; nCellIndex <= nTagCellEnd; ++nCellIndex ) { arrayOfTags* pArrayOfTags = pScaffoldLineTagBar->pGetElement( nCellIndex, nLineWithinTagBar ); // if there is no array for this cell, create one if ( !pArrayOfTags ) { RWCString soName = "aScaffoldRowTagBars_[ "; soName += RWCString( (long) nScaffoldRow ); soName += " ] at pGetElement( "; soName += RWCString( (long) nCellIndex ); soName += ", "; soName += RWCString( (long) nLineWithinTagBar ); soName += " )"; pArrayOfTags = new RWTPtrOrderedVector( 6, soName ); pScaffoldLineTagBar->pGetElement( nCellIndex, nLineWithinTagBar ) = pArrayOfTags; } // add the tag to each of these cells pArrayOfTags->insert( pTag ); } } // now go through the read tags for( int nRead = 0; nRead < pContig->nGetNumberOfFragsInContig(); ++nRead ) { LocatedFragment* pLocFrag = pContig->pLocatedFragmentGet( nRead ); for( int nReadTag = 0; nReadTag < pLocFrag->nGetNumberOfTags(); ++nReadTag ) { tag* pTag = pLocFrag->pGetTag( nReadTag ); int nLineWithinTagBar; if ( !bIsThisADesiredTagType( pTag->soType_, nLineWithinTagBar ) ) continue; // Let's figure out which cells this tag intersects. To do // this, convert the tag coordinates to unpadded consensus // coordinates. int nTagCellStart; int nTagCellEnd; bool bNotOnScreen; getTagCellRangeForTag( pContig, nScaffold, pTag, nTagCellStart, nTagCellEnd, bNotOnScreen ); if ( bNotOnScreen ) continue; for( int nCellIndex = nTagCellStart; nCellIndex <= nTagCellEnd; ++nCellIndex ) { // what is the range of padded consensus positions // for nCellIndex ? // note that the contig may be complemented in the // scaffold, but we are still interested in getting // the consensus positions in low-to-high order int nCellConsPosLow; int nCellConsPosHigh; bool bProblems; getConsPosRangeOfTagCell( nCellIndex, nScaffold, pContig, nCellConsPosLow, nCellConsPosHigh, bProblems ); assert( !bProblems ); // deal with this later // does this tag have any non-pads within the range // of these consensus positions? int nIntersectConsPosLow; int nIntersectConsPosHigh; if ( !bIntersect( nCellConsPosLow, nCellConsPosHigh, pTag->nPaddedConsPosStart_, pTag->nPaddedConsPosEnd_, nIntersectConsPosLow, nIntersectConsPosHigh ) ) { // something screwed up since this tag cell is in range continue; } bool bStillLooking = true; for( int nConsPos = nIntersectConsPosLow; nConsPos <= nIntersectConsPosHigh && bStillLooking; ++nConsPos ) { if ( !pLocFrag->ntGetFragFromConsPos( nConsPos ).bIsPad() ) { // got a non-pad bStillLooking = false; // add this tag to this cell arrayOfTags* pArrayOfTags = pScaffoldLineTagBar->pGetElement( nCellIndex, nLineWithinTagBar ); // if there is no array for this cell, create one if ( !pArrayOfTags ) { RWCString soName = "aScaffoldRowTagBars_[ "; soName += RWCString( (long) nScaffoldRow ); soName += " ] at pGetElement( "; soName += RWCString( (long) nCellIndex ); soName += ", "; soName += RWCString( (long) nLineWithinTagBar ); soName += " )"; pArrayOfTags = new RWTPtrOrderedVector( 6, soName ); pScaffoldLineTagBar->pGetElement( nCellIndex, nLineWithinTagBar ) = pArrayOfTags; } pArrayOfTags->insert( pTag ); } } } // for( int nCellIndex = nTagCellStart; } // for( int nReadTag = 0; } // for( int nRead = 0; } // for( int nContig = 0; } // for ( int nScaffold = 0; } void assemblyView :: drawTags() { // fixed Nov 2006 if ( !pCP->bAssemblyViewShowTags_ ) return; for( int nScaffoldRow = 0; nScaffoldRow < aScaffoldRowTagBars_.length(); ++nScaffoldRow ) { drawTagsOnOneScaffoldRow( nScaffoldRow ); } } void assemblyView :: drawTagsOnOneScaffoldRow( const int nScaffoldRow ) { scaffoldLineTagBar* pScaffoldLineTagBar = aScaffoldRowTagBars_[ nScaffoldRow ]; for( int nTagLine = 0; nTagLine < pScaffoldLineTagBar->nNumberOfRows_; ++nTagLine ) { for( int nCellIndex = 0; nCellIndex < pScaffoldLineTagBar->nNumberOfColumns_; ++nCellIndex ) { arrayOfTags* pArrayOfTags = pScaffoldLineTagBar->pGetElement( nCellIndex, nTagLine ); if ( !pArrayOfTags ) continue; if ( pArrayOfTags->length() == 0 ) continue; if ( pArrayOfTags->length() > 1 ) { drawTagCell( nScaffoldRow, nTagLine, nCellIndex, tagTypes::pGetTagTypes()->pGetGuiColorTextForTagsOverlap(), true ); } else { tag* pTag = pArrayOfTags->operator[](0); drawTagCell( nScaffoldRow, nTagLine, nCellIndex, tagTypes::pGetTagTypes()->pGetGuiColorTextForTag( pTag ), true ); } } } } void assemblyView :: drawTagCell( const int nScaffoldRow, const int nTagLine, const int nCellIndex, GuiColorText* pGuiColorText, const bool bReverse ) { int nPixelXLeft = nCellIndex * nPixelWidthOfTagCell; int nScaffold = nGetFirstScaffoldOnScaffoldRow( nScaffoldRow ); int nPixelYTop = nGetPixelYOfTagLine( nScaffold, nTagLine ); XFillRectangle( XtDisplay( widDrawingArea_ ), XtWindow( widDrawingArea_ ), ( bReverse ? pGuiColorText->gcGetReverse() : pGuiColorText->gcGet() ), nPixelXLeft, nPixelYTop, nPixelWidthOfTagCell, nHeightOfATagLine ); } void assemblyView :: highlightTags( const int nPixelX, const int nPixelY ) { // fixed Nov 2006 if ( !pCP->bAssemblyViewShowTags_ ) return; int nCursorPixelYTop = nPixelY - pCP->nAssemblyViewCursorSensitivityInPixels_ / 2; int nCursorPixelYBottom = nPixelY + pCP->nAssemblyViewCursorSensitivityInPixels_ / 2; int nCursorPixelXLeft = nPixelX - pCP->nAssemblyViewCursorSensitivityInPixels_ / 2; int nCursorPixelXRight = nPixelX + pCP->nAssemblyViewCursorSensitivityInPixels_ / 2; // save a copy of the currently highlighted tags so // we will know which tags to turn off RWTPtrOrderedVector aOldHighlightedTags( aCurrentlyHighlightedTags_ ); aCurrentlyHighlightedTags_.clear(); bool bFound = false; int nTagLine; int nScaffoldRow; int nTagCellIndex; for( nScaffoldRow = 0; nScaffoldRow < nNumberOfScaffoldRows_; ++nScaffoldRow ) { scaffoldLineTagBar* pScaffoldLineTagBar = aScaffoldRowTagBars_[ nScaffoldRow ]; int nScaffold = nGetFirstScaffoldOnScaffoldRow( nScaffoldRow ); int nPixelYTop = nGetPixelYOfTagLine( nScaffold, 0 ); int nPixelYBottom = nPixelYTop + pCP->nAssemblyViewNumberOfRowsOfTags_ * nHeightOfATagLine - 1; int nIntersectPixelYTop; int nIntersectPixelYBottom; if ( !bIntersect( nPixelYTop, nPixelYBottom, nCursorPixelYTop, nCursorPixelYBottom, nIntersectPixelYTop, nIntersectPixelYBottom ) ) continue; // if reached here, the square of blur intersects the // nScaffoldRow's tag bar // Which line(s) is it on? int nTagLineTop = ( nIntersectPixelYTop - nPixelYTop ) / nHeightOfATagLine; int nTagLineBottom = ( nIntersectPixelYBottom - nPixelYTop ) / nHeightOfATagLine; // which tag cell is it on? int nTagCellIndexLeft = nGetTagCellIndexFromPixelX( nCursorPixelXLeft ); int nTagCellIndexRight = nGetTagCellIndexFromPixelX( nCursorPixelXRight ); // prevent subscript errors: nGetTagCellIndexFromPixelX can // return, if the pixel is at the extreme right or off the screen, // a tag cell that doesn't exist if ( !bIntersect( nTagCellIndexLeft, nTagCellIndexRight, 0, pScaffoldLineTagBar->nNumberOfColumns_ - 1, nTagCellIndexLeft, nTagCellIndexRight ) ) continue; for( int nTagLine = nTagLineTop; nTagLine <= nTagLineBottom; ++nTagLine ) { for( int nTagCellIndex = nTagCellIndexLeft; nTagCellIndex <= nTagCellIndexRight; ++nTagCellIndex ) { arrayOfTags* pArrayOfTags = pScaffoldLineTagBar->pGetElement( nTagCellIndex, nTagLine ); if ( pArrayOfTags ) { // highlight all tags at this location for( int nTag = 0; nTag < pArrayOfTags->length(); ++nTag ) { tag* pTag = (*pArrayOfTags)[ nTag ]; aCurrentlyHighlightedTags_.insert( pTag ); } } } // for( int nTagCellIndex ... } // for( int nTagLine ... } // for( nScaffoldRow = 0; ... // now see which ones we need to highlight and which ones are already // highlighted and which ones we need to turn off highlighting int nTag; for( nTag = 0; nTag < aCurrentlyHighlightedTags_.length(); ++nTag ) { tag* pTag = aCurrentlyHighlightedTags_[ nTag ]; // is this tag already highlighted? if ( aOldHighlightedTags.index( pTag ) == RW_NPOS ) { // not already highlighted--highlight it. highlightTag( pTag, eHIGHLIGHT_ON ); } } for( nTag = 0; nTag < aOldHighlightedTags.length(); ++nTag ) { tag* pTag = aOldHighlightedTags[ nTag ]; // is this tag still highlighted? if ( aCurrentlyHighlightedTags_.index( pTag ) == RW_NPOS ) { // not still highlighted--turn it off highlightTag( pTag, eHIGHLIGHT_OFF ); } } } void assemblyView :: checkIfOnATag( const int nPixelX, const int nPixelY, RWCString& soMessage ) { // fixed Nov 2006 if ( !pCP->bAssemblyViewShowTags_ ) return; RWTPtrOrderedVector aTags; if ( bCheckIfOnATag( nPixelX, nPixelY, &aTags ) ) { for( int nTag = 0; nTag < aTags.length(); ++nTag ) { tag* pTag = aTags[ nTag ]; soMessage += "tag: "; soMessage += pTag->soType_; if ( pTag->bReadTagNotConsensusTag_ ) { soMessage += " on read "; soMessage += pTag->pLocFrag_->soGetName(); } else { Contig* pContig = pTag->pContig_; soMessage += " on cons from "; soMessage += RWCString( (long) pContig->nUnpaddedIndex( pTag->nPaddedConsPosStart_ ) ); soMessage += " to "; soMessage += RWCString( (long) pContig->nUnpaddedIndex( pTag->nPaddedConsPosEnd_ ) ); } } } } bool assemblyView :: bCheckIfOnATag( const int nPixelX, const int nPixelY, RWTPtrOrderedVector* pTagArray ) { int nCursorPixelYTop = nPixelY - pCP->nAssemblyViewCursorSensitivityInPixels_ / 2; int nCursorPixelYBottom = nPixelY + pCP->nAssemblyViewCursorSensitivityInPixels_ / 2; int nCursorPixelXLeft = nPixelX - pCP->nAssemblyViewCursorSensitivityInPixels_ / 2; int nCursorPixelXRight = nPixelX + pCP->nAssemblyViewCursorSensitivityInPixels_ / 2; for( int nScaffoldRow = 0; nScaffoldRow < nNumberOfScaffoldRows_; ++nScaffoldRow ) { int nScaffold = nGetFirstScaffoldOnScaffoldRow( nScaffoldRow ); int nPixelYTop = nGetPixelYOfTagLine( nScaffold, 0 ); int nPixelYBottom = nPixelYTop + pCP->nAssemblyViewNumberOfRowsOfTags_ * nHeightOfATagLine - 1; int nIntersectTop; int nIntersectBottom; if ( !bIntersect( nPixelYTop, nPixelYBottom, nCursorPixelYTop, nCursorPixelYBottom, nIntersectTop, nIntersectBottom ) ) continue; // if reached here, the square of blur intersects a tag bar // the cursor is in a tag region. Which line is it on? int nTagLineTop = ( nIntersectTop - nPixelYTop ) / nHeightOfATagLine; int nTagLineBottom = ( nIntersectBottom - nPixelYTop ) / nHeightOfATagLine; // which tag cell is it on? int nTagCellIndexLeft = nGetTagCellIndexFromPixelX( nCursorPixelXLeft ); int nTagCellIndexRight = nGetTagCellIndexFromPixelX( nCursorPixelXRight); // It is possible (especially at the extreme right end of the screen) // for the pCP->nAssemblyViewCursorSensitivityInPixels_ to extend // the area to make nGetTagCellIndexFromPixel return a tag cell index // that doesn't exist, causing a subscript error. Guard against that: scaffoldLineTagBar* pScaffoldLineTagBar = aScaffoldRowTagBars_[ nScaffoldRow ]; if ( !bIntersect( nTagCellIndexLeft, nTagCellIndexRight, 0, pScaffoldLineTagBar->nNumberOfColumns_ - 1, nTagCellIndexLeft, nTagCellIndexRight ) ) continue; for( int nTagLine = nTagLineTop; nTagLine <= nTagLineBottom; ++nTagLine ) { for( int nTagCellIndex = nTagCellIndexLeft; nTagCellIndex <= nTagCellIndexRight; ++nTagCellIndex ) { arrayOfTags* pArrayOfTags = pScaffoldLineTagBar->pGetElement( nTagCellIndex, nTagLine ); if ( pArrayOfTags ) { // display all of the tags at this location for( int nTag = 0; nTag < pArrayOfTags->length(); ++nTag ) { tag* pTag = (*pArrayOfTags)[ nTag ]; pTagArray->insert( pTag ); } } } } } // for( int nScaffoldRow = 0 return( pTagArray->length() > 0 ); } void assemblyView :: highlightTag( tag* pTag, const eHighlightType eHighlight ) { // this tag might be a read tag, in which case we only want // to highlight the locations in which the read doesn't have pads // draw this directly *and* put it into the array so that if there // is a refresh event, the correct color will be drawn. Maybe // not--maybe only put it into the array if the user clicks on it. int nLineWithinTagBar; if ( !bIsThisADesiredTagType( pTag->soType_, nLineWithinTagBar ) ) { return; } Contig* pContig = pTag->pGetContig(); // we also need to know the scaffold and scaffold line of this contig int nScaffold = nGetScaffoldForContig( pContig ); int nScaffoldRow = aScaffolds_[ nScaffold ]->nScaffoldRow_; int nTagCellStart; int nTagCellEnd; bool bNotOnScreen; getTagCellRangeForTag( pContig, nScaffold, pTag, nTagCellStart, nTagCellEnd, bNotOnScreen ); if ( bNotOnScreen ) return; for( int nCellIndex = nTagCellStart; nCellIndex <= nTagCellEnd; ++nCellIndex ) { // always draw in this tag cell if this is a consensus tag // If it is a read tag, then might not draw in it if // all the read bases in this tag cell are pads. bool bDrawInThisTagCell = true; if ( pTag->bReadTagNotConsensusTag_ ) { int nCellConsPosLow; int nCellConsPosHigh; bool bProblems; getConsPosRangeOfTagCell( nCellIndex, nScaffold, pContig, nCellConsPosLow, nCellConsPosHigh, bProblems ); assert( !bProblems ); int nIntersectConsPosLow; int nIntersectConsPosHigh; if ( !bIntersect( nCellConsPosLow, nCellConsPosHigh, pTag->nPaddedConsPosStart_, pTag->nPaddedConsPosEnd_, nIntersectConsPosLow, nIntersectConsPosHigh ) ) { // the tag doesn't lie in this cell (something screwed up) continue; } bDrawInThisTagCell = false; bool bStillLooking = true; for( int nConsPos = nIntersectConsPosLow; nConsPos <= nIntersectConsPosHigh; ++nConsPos ) { if ( !pTag->pLocFrag_->ntGetFragFromConsPos( nConsPos ).bIsPad() ) { // found a non-pad. Get out of this loop and draw // the yellow tag cell. bStillLooking = false; bDrawInThisTagCell = true; } } } if ( bDrawInThisTagCell ) { GuiColorText* pGuiColorText; if ( eHighlight == eHIGHLIGHT_ON ) pGuiColorText = pGctHighlight_; else if ( eHighlight == eHIGHLIGHT_OFF ) { // let's see if the cell should really be colored purple // instead of the color of the tag: scaffoldLineTagBar* pScaffoldLineTagBar = aScaffoldRowTagBars_[ nScaffoldRow ]; arrayOfTags* pArrayOfTags = pScaffoldLineTagBar->pGetElement( nCellIndex, nLineWithinTagBar ); bool bPurple = false; if ( pArrayOfTags ) { if ( pArrayOfTags->length() > 1 ) { bPurple = true; } } if ( bPurple ) { pGuiColorText = tagTypes::pGetTagTypes()->pGetGuiColorTextForTagsOverlap(); } else { pGuiColorText = tagTypes::pGetTagTypes()->pGetGuiColorTextForTag( pTag ); } } else assert( false ); drawTagCell( nScaffoldRow, nLineWithinTagBar, nCellIndex, pGuiColorText, ( eHighlight == eHIGHLIGHT_ON ? false : true ) ) ; // reverse gc } } }