/***************************************************************************** # 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 #include #include #include #include #include #include #include "guiDisplayDigest.h" #include "guiFindRestrictionEnzymeSites.h" #include #include #include "guicolortext.h" #include "hp_exception_kludge.h" #include "waitUntilDialogIsVisible.h" #include "handleWindowManagerDelete2.h" #include "digestForOneEnzyme.h" #include #include #include "contigEnd.h" #include "consed.h" #include "contigwin.h" #include "popupErrorMessage2.h" #include #include "consedParameters.h" #include "guicolortext.h" #include "colorDefaults.h" #include "visibleLineForRestrictionFragments.h" #include "popupErrorMessage.h" #include "guiDigestProblemNavigator.h" #include "clScaffold.h" #include "textbox.h" #include #include #include "assemblyView.h" const int nGelScrollBarIncrementInPixels = 20; const int nHalfHeightOfCursorIndicator = 6; static char szNumber[100]; const int nHugeRestrictionFragment = 100000000; static void cbGuiShowDocumentationForRestrictionDigest( Widget wid, XtPointer pClientData, XtPointer pCallData ) { guiDisplayDigest* pDisplayDigest = (guiDisplayDigest*) pClientData; TRY_CATCH_WRAPPER( pDisplayDigest->showDocumentationForRestrictionDigest() ); } static void cbUserPushedShowProblems( Widget wid, XtPointer pClientData, XtPointer pCallData ) { guiDisplayDigest* pDisplayDigest = (guiDisplayDigest*) pClientData; TRY_CATCH_WRAPPER( pDisplayDigest->userPushedShowProblems() ); } static void cbComplVector( Widget wid, XtPointer pClientData, XtPointer pCallData ) { guiDisplayDigest* pDisplayDigest = (guiDisplayDigest*) pClientData; TRY_CATCH_WRAPPER( pDisplayDigest->userPushedComplVector() ); } static void cbInput( Widget wid, XtPointer pClientData, XtPointer pCallData ) { guiDisplayDigest* pDisplayDigest = (guiDisplayDigest*) pClientData; TRY_CATCH_WRAPPER( pDisplayDigest->userClicked( pCallData ) ); } static void pointerMotionEventHandler( Widget wid, XtPointer pClientData, XEvent* pEvent, Boolean* ) { int nPixelX = pEvent->xmotion.x; int nPixelY = pEvent->xmotion.y; guiDisplayDigest* pDisplayDigest = (guiDisplayDigest*) pClientData; TRY_CATCH_WRAPPER( pDisplayDigest->pointerMoved( nPixelX, nPixelY ) ); } static void cbUserPushedZoomInOrOut( Widget wid, XtPointer pClientData, XtPointer pCallData ) { guiDisplayDigest* pDisplayRes = (guiDisplayDigest*) pClientData; TRY_CATCH_WRAPPER( pDisplayRes->userPushedZoomInOrOut( wid ) ); } static void cbUserPushedShowTextOutput( Widget wid, XtPointer pClientData, XtPointer pCallData ) { guiDisplayDigest* pDisplayRes = (guiDisplayDigest*) pClientData; TRY_CATCH_WRAPPER( pDisplayRes->showTextOutput() ); } static void cbUserChangedEnzyme( Widget wid, XtPointer pClientData, XtPointer pCallData ) { guiDisplayDigest* pDisplayRes = (guiDisplayDigest*) pClientData; TRY_CATCH_WRAPPER( pDisplayRes->userChangedEnzyme( wid ) ); } static void cbUserPushedGotoRightEnd( Widget wid, XtPointer pClientData, XtPointer pCallData ) { guiDisplayDigest* pDisplayRes = ( guiDisplayDigest* ) pClientData; TRY_CATCH_WRAPPER( pDisplayRes->gotoEnd( nRightGap ) ); } static void cbUserPushedGotoLeftEnd( Widget wid, XtPointer pClientData, XtPointer pCallData ) { guiDisplayDigest* pDisplayRes = ( guiDisplayDigest* ) pClientData; TRY_CATCH_WRAPPER( pDisplayRes->gotoEnd( nLeftGap ) ); } static void cbGelScrollBar( Widget wid, XtPointer pClientData, XtPointer pCallData ) { guiDisplayDigest* pDisplayRes = ( guiDisplayDigest* ) pClientData; XmScrollBarCallbackStruct* pCbStruct = (XmScrollBarCallbackStruct*) pCallData; TRY_CATCH_WRAPPER( pDisplayRes->gelScrollBarMoved( pCbStruct->value ) ); } static void cbGelWindowExpose( Widget wid, XtPointer pClientData, XtPointer pCallData ) { guiDisplayDigest* pDisplay = ( guiDisplayDigest* ) pClientData; TRY_CATCH_WRAPPER( pDisplay->displayGelWindow(); ); } static void cbUserPushedDismiss( Widget wid, XtPointer pClientData, XtPointer pCallData ) { guiDisplayDigest* pDisplay = ( guiDisplayDigest* ) pClientData; TRY_CATCH_WRAPPER( delete pDisplay ); } static void cbSortChanged( Widget wid, XtPointer pClientData, XtPointer pCallData ) { guiDisplayDigest* pDisplay = ( guiDisplayDigest* ) pClientData; TRY_CATCH_WRAPPER( pDisplay->sortChanged() ); } const int nGelWindowPosition = 50; guiDisplayDigest :: guiDisplayDigest() : fPixelsPerGelUnit_( 0.3 ), nGelPositionAtTopOfGelWindow_( 0 ), bWindowVisible_( false ), pTempMarkedActualRestrictionFragment_( NULL ), pTempMarkedPredictedRestrictionFragment_( NULL ), pPermMarkedActualRestrictionFragment_( NULL ), pPermMarkedPredictedRestrictionFragment_( NULL ), bFlipVectorFromTheDefault_( false ) { aVisibleLinesForPredictedFragments_.soName_ = "guiDisplayDigest::aVisibleLinesForPredictedFragments_"; aVisibleLinesForActualFragments_.soName_ = "guiDisplayDigest::aVisibleLinesForActualFragments_"; aDigests_.soName_ = "guiDisplayDigest::aDigest_"; } // why didn't I use the array aDigests_ which contains the // enzyme name and bases instead of passing aSelectedEnzymeNames and // aSelectedEnzymeBases and then later having to search to find // the corresponding element of aDigests_ ? void guiDisplayDigest :: createWindow( const RWTValOrderedVector& aSelectedEnzymeNames, const RWTValOrderedVector& aSelectedEnzymeBases, const bool bUseUserDefinedContigMap, const RWCString soUserEnteredContigMap, const int nStartUnpaddedConsPos, const int nEndUnpaddedConsPos ) { aSelectedEnzymeNames_ = aSelectedEnzymeNames; aSelectedEnzymeBases_ = aSelectedEnzymeBases; bUseUserDefinedContigMap_ = bUseUserDefinedContigMap; soUserEnteredContigMap_ = soUserEnteredContigMap; nStartUnpaddedConsPos_ = nStartUnpaddedConsPos; nEndUnpaddedConsPos_ = nEndUnpaddedConsPos; setMinGelPosition(); widPopupShell_ = XtVaCreatePopupShell( "guiDisplayDigest", topLevelShellWidgetClass, GuiApp::pGetGuiApp()->widGetTopLevel(), XmNtitle, "Display Digests", XmNtransient, False, XmNdeleteResponse, XmDO_NOTHING, NULL ); handleWindowManagerDelete2( widPopupShell_, cbUserPushedDismiss, this ); // the immediate child of the application shell is a main window (so // there can be a menu bar) Widget widMainWin = XtVaCreateManagedWidget( "mainwin", xmMainWindowWidgetClass, widPopupShell_, XmNancestorSensitive, True, NULL ); // put menu bar on the main window int nArgs = 0; Arg aArg[30]; Widget widMenuBar = XmCreateMenuBar( widMainWin, "menubar", aArg, nArgs ); XtManageChild( widMenuBar ); // create help menu button nArgs = 0; Widget widHelpMenu = XmCreatePulldownMenu( widMenuBar, "Help", aArg, nArgs ); nArgs = 0; XtSetArg( aArg[ nArgs ], XmNsubMenuId, widHelpMenu ); ++nArgs; Widget widHelpCascade = XmCreateCascadeButton( widMenuBar, "Help", aArg, nArgs ); XtManageChild( widHelpCascade ); XtVaSetValues( widMenuBar, XmNmenuHelpWidget, widHelpCascade, NULL ); // now add help menu item Widget widShowDocumentation = XtVaCreateManagedWidget( "Show Documentation for Restriction Digest", xmPushButtonWidgetClass, widHelpMenu, NULL ); XtAddCallback( widShowDocumentation, XmNactivateCallback, cbGuiShowDocumentationForRestrictionDigest, this ); widForm_ = XtVaCreateManagedWidget( "form", xmFormWidgetClass, widMainWin, XmNancestorSensitive, True, NULL ); // build from bottom up widDismiss_ = XtVaCreateManagedWidget( "Dismiss", xmPushButtonWidgetClass, widForm_, XmNbottomAttachment, XmATTACH_FORM, XmNbottomOffset, 10, XmNleftAttachment, XmATTACH_POSITION, XmNleftPosition, 45, XmNrightAttachment, XmATTACH_POSITION, XmNrightPosition, 55, NULL ); XtAddCallback( widDismiss_, XmNactivateCallback, (XtCallbackProc ) cbUserPushedDismiss, this ); Widget widAttachWidgetAboveToThis = widDismiss_; // create the options menu. This is done by creating // a pulldown menu, adding push buttons (menu items) to it, // and finally creating an options menu and linking it to // the pulldown menu. Widget widPullDownMenu = XmCreatePulldownMenu( widForm_, "option_pulldown", NULL, 0 ); for( int nEnzyme = 0; nEnzyme < aSelectedEnzymeNames_.length(); ++nEnzyme ) { Widget widPushButton = XtVaCreateManagedWidget( aSelectedEnzymeNames_[ nEnzyme ].data(), xmPushButtonWidgetClass, widPullDownMenu, NULL ); aEnzymeWidgets_.insert( widPushButton ); XtAddCallback( widPushButton, XmNactivateCallback, (XtCallbackProc ) cbUserChangedEnzyme, this ); } XmString xms = XmStringCreateLocalized( "Select Enzyme:" ); XtSetArg( aArg[ nArgs ], XmNlabelString, xms ); ++nArgs; XtSetArg( aArg[ nArgs ], XmNsubMenuId, widPullDownMenu ); ++nArgs; XtSetArg( aArg[ nArgs ], XmNleftAttachment, XmATTACH_FORM ); ++nArgs; XtSetArg( aArg[ nArgs ], XmNbottomAttachment, XmATTACH_WIDGET ); ++nArgs; XtSetArg( aArg[ nArgs ], XmNbottomWidget, widAttachWidgetAboveToThis ); ++nArgs; widEnzymeOptionsMenu_ = XmCreateOptionMenu( widForm_, "Select Enzyme:", aArg, nArgs ); XtManageChild( widEnzymeOptionsMenu_ ); widCurrentlyDisplayedEnzymeBases_ = XtVaCreateManagedWidget( "enzyme bases", xmTextFieldWidgetClass, widForm_, XmNtraversalOn, False, XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET, XmNbottomWidget, widEnzymeOptionsMenu_, XmNleftAttachment, XmATTACH_WIDGET, XmNleftWidget, widEnzymeOptionsMenu_, XmNleftOffset, 10, XmNcolumns, 8, XmNcursorPositionVisible, False, XmNeditable, False, NULL ); widAttachWidgetAboveToThis = widEnzymeOptionsMenu_; Widget widContigMapLabel = XtVaCreateManagedWidget( "Contig Map:", xmLabelWidgetClass, widForm_, XmNleftAttachment, XmATTACH_WIDGET, XmNleftWidget, widCurrentlyDisplayedEnzymeBases_, XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET, XmNbottomWidget, widEnzymeOptionsMenu_, XmNleftOffset, 20, NULL ); widContigMap_ = XtVaCreateManagedWidget( "contig map", xmTextFieldWidgetClass, widForm_, XmNtraversalOn, False, XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET, XmNbottomWidget, widEnzymeOptionsMenu_, XmNleftAttachment, XmATTACH_WIDGET, XmNleftWidget, widContigMapLabel, XmNleftOffset, 10, XmNrightAttachment, XmATTACH_FORM, XmNrightOffset, 10, XmNcursorPositionVisible, False, XmNeditable, False, XmNvalue, ConsEd::pGetAssembly()->soGetContigMap().data(), NULL ); Widget widLabel1 = XtVaCreateManagedWidget( "Go to:", xmLabelWidgetClass, widForm_, XmNleftAttachment, XmATTACH_FORM, XmNbottomAttachment, XmATTACH_WIDGET, XmNbottomWidget, widAttachWidgetAboveToThis, NULL ); widGotoLeft_ = XtVaCreateManagedWidget( "Left End", xmPushButtonWidgetClass, widForm_, XmNleftAttachment, XmATTACH_WIDGET, XmNleftWidget, widLabel1, XmNbottomAttachment, XmATTACH_WIDGET, XmNbottomWidget, widAttachWidgetAboveToThis, NULL ); XtAddCallback( widGotoLeft_, XmNactivateCallback, cbUserPushedGotoLeftEnd, this ); widGotoRight_ = XtVaCreateManagedWidget( "Right End", xmPushButtonWidgetClass, widForm_, XmNleftAttachment, XmATTACH_WIDGET, XmNleftWidget, widGotoLeft_, XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET, XmNbottomWidget, widGotoLeft_, XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET, XmNtopWidget, widGotoLeft_, NULL ); XtAddCallback( widGotoRight_, XmNactivateCallback, cbUserPushedGotoRightEnd, this ); widShowTextOutput_ = XtVaCreateManagedWidget( "Text Output", xmPushButtonWidgetClass, widForm_, XmNleftAttachment, XmATTACH_WIDGET, XmNleftWidget, widGotoRight_, XmNleftOffset, 20, XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET, XmNbottomWidget, widGotoRight_, XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET, XmNtopWidget, widGotoRight_, NULL ); XtAddCallback( widShowTextOutput_, XmNactivateCallback, cbUserPushedShowTextOutput, this ); widComplVector_ = XtVaCreateManagedWidget( "compl vector", xmPushButtonWidgetClass, widForm_, XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET, XmNtopWidget, widShowTextOutput_, XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET, XmNbottomWidget, widShowTextOutput_, XmNleftAttachment, XmATTACH_WIDGET, XmNleftWidget, widShowTextOutput_, XmNleftOffset, 20, XmNtraversalOn, False, NULL ); XtAddCallback( widComplVector_, XmNactivateCallback, cbComplVector, this ); widZoomIn_ = XtVaCreateManagedWidget( "Zoom In", xmPushButtonWidgetClass, widForm_, XmNleftAttachment, XmATTACH_WIDGET, XmNleftWidget, widComplVector_, XmNleftOffset, 20, XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET, XmNbottomWidget, widGotoLeft_, XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET, XmNtopWidget, widGotoLeft_, NULL ); XtAddCallback( widZoomIn_, XmNactivateCallback, cbUserPushedZoomInOrOut, this ); widZoomOut_ = XtVaCreateManagedWidget( "Zoom Out", xmPushButtonWidgetClass, widForm_, XmNleftAttachment, XmATTACH_WIDGET, XmNleftWidget, widZoomIn_, XmNleftOffset, 10, XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET, XmNbottomWidget, widZoomIn_, XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET, XmNtopWidget, widZoomIn_, NULL ); XtAddCallback( widZoomOut_, XmNactivateCallback, cbUserPushedZoomInOrOut, this ); widZoomOriginal_ = XtVaCreateManagedWidget( "Zoom Orig", xmPushButtonWidgetClass, widForm_, XmNleftAttachment, XmATTACH_WIDGET, XmNleftWidget, widZoomOut_, XmNleftOffset, 10, XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET, XmNbottomWidget, widZoomOut_, XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET, XmNtopWidget, widZoomOut_, NULL ); XtAddCallback( widZoomOriginal_, XmNactivateCallback, cbUserPushedZoomInOrOut, this ); widShowProblems_ = XtVaCreateManagedWidget( "Show Problems", xmPushButtonWidgetClass, widForm_, XmNleftAttachment, XmATTACH_WIDGET, XmNleftWidget, widZoomOriginal_, XmNleftOffset, 10, XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET, XmNbottomWidget, widZoomOriginal_, XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET, XmNtopWidget, widZoomOriginal_, NULL ); XtAddCallback( widShowProblems_, XmNactivateCallback, cbUserPushedShowProblems, this ); widAttachWidgetAboveToThis = widGotoLeft_; // Radio box Widget widLabel2 = XtVaCreateManagedWidget( "Sort by:", xmLabelWidgetClass, widForm_, XmNleftAttachment, XmATTACH_FORM, XmNbottomAttachment, XmATTACH_WIDGET, XmNbottomWidget, widAttachWidgetAboveToThis, NULL ); Dimension dimWidth; XtVaGetValues( widLabel2, XmNwidth, &dimWidth, NULL ); Dimension dimSpacing; XtVaGetValues( widForm_, XmNhorizontalSpacing, &dimSpacing, NULL ); Widget widSortByRadioBox = XmCreateRadioBox( widForm_, "sortByRadio", NULL, 0 ); XtVaSetValues( widSortByRadioBox, XmNtraversalOn, True, XmNbottomAttachment, XmATTACH_WIDGET, XmNbottomWidget, widAttachWidgetAboveToThis, XmNleftAttachment, XmATTACH_FORM, XmNleftOffset, dimWidth + dimSpacing, XmNorientation, XmHORIZONTAL, NULL ); Widget widSortBySize = XtVaCreateManagedWidget( "size", xmToggleButtonWidgetClass, widSortByRadioBox, XmNset, True, // default NULL ); widSortByPosition_ = XtVaCreateManagedWidget( "position", xmToggleButtonWidgetClass, widSortByRadioBox, XmNset, False, NULL ); XtAddCallback( widSortByPosition_, XmNvalueChangedCallback, cbSortChanged, this ); XtManageChild( widSortByRadioBox ); XtVaSetValues( widLabel2, XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET, XmNtopWidget, widSortByRadioBox, XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET, XmNbottomWidget, widSortByRadioBox, NULL ); widAttachWidgetAboveToThis = widSortByRadioBox; // end Radio Box nArgs = 0; XtSetArg( aArg[nArgs], XmNtopAttachment, XmATTACH_FORM ); nArgs++; XtSetArg( aArg[nArgs], XmNleftAttachment, XmATTACH_FORM ); nArgs++; XtSetArg( aArg[nArgs], XmNbottomAttachment, XmATTACH_WIDGET ); nArgs++; XtSetArg( aArg[nArgs], XmNbottomWidget, widAttachWidgetAboveToThis ); ++nArgs; XtSetArg( aArg[nArgs], XmNbottomOffset, 20 ); ++nArgs; XtSetArg( aArg[nArgs], XmNrightAttachment, XmATTACH_POSITION ); nArgs++; XtSetArg( aArg[nArgs], XmNrightPosition, nGelWindowPosition ); nArgs++; XtSetArg(aArg[nArgs], XmNscrollBarDisplayPolicy, XmAS_NEEDED); nArgs++; // XtSetArg(aArg[nArgs], XmNscrollingPolicy, XmAUTOMATIC); nArgs++; XtSetArg(aArg[nArgs], XmNlistVisibleItemCount, 20 ); nArgs++; XtSetArg(aArg[nArgs], XmNcolumns, 100 ); nArgs++; XtSetArg(aArg[nArgs], XmNtraversalOn, False); nArgs++; XtSetArg(aArg[nArgs], XmNselectionPolicy, XmSINGLE_SELECT ); ++nArgs; XtSetArg(aArg[nArgs], XmNmarginHeight, 0 ); ++nArgs; XtSetArg(aArg[nArgs], XmNmarginWidth, 0 ); ++nArgs; // XtSetArg(aArg[nArgs], XmNtextColumns, (short) 20 ); ++nArgs; XtSetArg( aArg[ nArgs ], XmNlistVisibleItemCount, pCP->nRestrictionDigestInitialWindowSizeInTextRows_ ); ++nArgs; widTextSelectionBox_ = XmCreateSelectionBox( widForm_, "text", aArg, nArgs ); XtManageChild( widTextSelectionBox_ ); XtUnmanageChild( XmSelectionBoxGetChild( widTextSelectionBox_, XmDIALOG_TEXT )); XtUnmanageChild( XmSelectionBoxGetChild( widTextSelectionBox_, XmDIALOG_SELECTION_LABEL)); XtUnmanageChild( XmSelectionBoxGetChild( widTextSelectionBox_, XmDIALOG_OK_BUTTON )); XtUnmanageChild( XmSelectionBoxGetChild( widTextSelectionBox_, XmDIALOG_CANCEL_BUTTON )); XtUnmanageChild( XmSelectionBoxGetChild( widTextSelectionBox_, XmDIALOG_HELP_BUTTON )); // commented out because it was already null // XtUnmanageChild( XmSelectionBoxGetChild( widTextSelectionBox_, XmDIALOG_WORK_AREA )); XtUnmanageChild( XmSelectionBoxGetChild( widTextSelectionBox_, XmDIALOG_SEPARATOR )); XtUnmanageChild( XmSelectionBoxGetChild( widTextSelectionBox_, XmDIALOG_LIST_LABEL )); widTextList_ = XmSelectionBoxGetChild( widTextSelectionBox_, XmDIALOG_LIST ); nArgs = 0; XtSetArg( aArg[nArgs], XmNtopAttachment, XmATTACH_FORM ); nArgs++; XtSetArg( aArg[nArgs], XmNrightAttachment, XmATTACH_FORM ); nArgs++; XtSetArg( aArg[nArgs], XmNbottomAttachment, XmATTACH_WIDGET ); nArgs++; XtSetArg( aArg[nArgs], XmNbottomWidget, widAttachWidgetAboveToThis ); ++nArgs; XtSetArg( aArg[nArgs], XmNbottomOffset, 20 ); ++nArgs; XtSetArg( aArg[nArgs], XmNleftAttachment, XmATTACH_POSITION ); nArgs++; XtSetArg( aArg[nArgs], XmNleftPosition, nGelWindowPosition ); nArgs++; widGelScrollingWindow_ = XmCreateScrolledWindow( widForm_, "text", aArg, nArgs ); XtManageChild( widGelScrollingWindow_ ); nArgs = 0; XtSetArg( aArg[nArgs], XmNorientation, XmVERTICAL ); nArgs++; widGelScrollBar_ = XmCreateScrollBar( widGelScrollingWindow_, "scrollbar", aArg, nArgs ); XtManageChild( widGelScrollBar_ ); XtAddCallback( widGelScrollBar_, XmNvalueChangedCallback, cbGelScrollBar, this ); XtAddCallback( widGelScrollBar_, XmNdragCallback, cbGelScrollBar, this ); const int nNumbersInScale = 6; nArgs = 0; XtSetArg( aArg[nArgs], XmNwidth, nGetLeftEndScaleNumber2() + nNumbersInScale * GuiApp::nGetFontWidth() ); nArgs++; widGelWindow_ = XmCreateDrawingArea( widGelScrollingWindow_, "gel", aArg, nArgs ); XtManageChild( widGelWindow_ ); XtAddCallback( widGelWindow_, XmNexposeCallback, cbGelWindowExpose, this ); XtAddEventHandler( widGelWindow_, PointerMotionMask, False, (XtEventHandler) pointerMotionEventHandler, this ); XtAddCallback( widGelWindow_, XmNinputCallback, (XtCallbackProc ) cbInput, this ); XtPopup( widPopupShell_, XtGrabNone ); bWindowVisible_ = true; // cannot update displays since pCurrentlyDisplayedDigest_ // has // not yet been set. In fact, none of the digestForOneEnzyme are // as yet created. } void guiDisplayDigest :: updateDisplays() { waitUntilDialogIsVisible( widPopupShell_ ); updateTextDisplay(); } void guiDisplayDigest :: updateTextDisplay() { arrayOfRestrictionFragments* pPredictedFragmentsArray = pGetPredictedFragmentsArray(); XmStringTable ppXtString = (XmStringTable) XtMalloc( pPredictedFragmentsArray->length() * sizeof( XmString ) ); int nPredictedFragment; for( nPredictedFragment = 0; nPredictedFragment < pPredictedFragmentsArray->length(); ++nPredictedFragment ) { restrictionFragment* pResFrag = (*pPredictedFragmentsArray)[ nPredictedFragment ]; RWCString soStringToDisplay( (size_t) 200 ); // types of predicted fragments: // entirely within contig // entirely within vector // partly within contig and unknown other end // partly within vector and unknown other end // partly within contig and partly within vector pResFrag->getDescriptionLine( soStringToDisplay ); ppXtString[ nPredictedFragment ] = XmStringCreateLocalized( soStringToDisplay.data() ); } // for( int nPredictedFragment = 0; nPredictedFragment < ... XtVaSetValues( widTextList_, XmNitems, ppXtString, XmNitemCount, pPredictedFragmentsArray->length(), NULL ); for( nPredictedFragment = 0; nPredictedFragment < pPredictedFragmentsArray->length(); ++nPredictedFragment ) { XmStringFree( ppXtString[ nPredictedFragment ] ); } XtFree( (char*) ppXtString ); } const int nNumberOfVectorPoints = 3; XPoint xp[ nNumberOfVectorPoints ]; const int nVectorVHalfWidth = 3; const int nVectorVHeight = 4; const char szG[] = "g"; void guiDisplayDigest :: drawLineForPredictedFragment( visibleLineForRestrictionFragments* pVis ) { XDrawLine( XtDisplay( widGelWindow_ ), XtWindow( widGelWindow_ ), pVis->pGetGuiColorText()->gcGet(), nGetPredictedFragmentLeftEndOnGel(), pVis->nMiddlePixel_, nGetPredictedFragmentRightEndOnGel(), pVis->nMiddlePixel_ ); if ( pVis->bAllFragmentsAreVector() ) { int nMiddle = ( nGetPredictedFragmentLeftEndOnGel() + nGetPredictedFragmentRightEndOnGel() ) / 2; xp[0].x = nMiddle - nVectorVHalfWidth; xp[0].y = pVis->nMiddlePixel_ - nVectorVHeight; xp[1].x = nMiddle; xp[1].y = pVis->nMiddlePixel_; xp[2].x = nMiddle + nVectorVHalfWidth; xp[2].y = pVis->nMiddlePixel_ - nVectorVHeight; XDrawLines( XtDisplay( widGelWindow_ ), XtWindow( widGelWindow_ ), pVis->pGetGuiColorText()->gcGet(), xp, nNumberOfVectorPoints, CoordModeOrigin ); } if ( pVis->bSomeFragmentIsGapSpanning() ) { // I'm putting the char a little to the left of middle // so it won't overlap the v for vector fragments int nMiddleLeft = nGetPredictedFragmentLeftEndOnGel() + 0.33333 * ( nGetPredictedFragmentRightEndOnGel() - nGetPredictedFragmentLeftEndOnGel() ); XDrawString( XtDisplay( widGelWindow_ ), XtWindow( widGelWindow_ ), pVis->pGetGuiColorText()->gcGet(), nMiddleLeft, pVis->nMiddlePixel_, szG, 1 ); } } void guiDisplayDigest :: drawLineForActualFragment( visibleLineForRestrictionFragments* pVis ) { XDrawLine( XtDisplay( widGelWindow_ ), XtWindow( widGelWindow_ ), pVis->pGetGuiColorText()->gcGet(), nGetActualFragmentLeftEndOnGel(), pVis->nMiddlePixel_, nGetActualFragmentRightEndOnGel(), pVis->nMiddlePixel_ ); } void guiDisplayDigest :: gelScrollBarMoved( const int nNewScrollBarPosition ) { nGelPositionAtTopOfGelWindow_ = nNewScrollBarPosition; displayGelWindow(); } void guiDisplayDigest :: clearGelWindow() { XClearArea( XtDisplay( widGelWindow_ ), XtWindow( widGelWindow_ ), 0, 0, 0, 0, false ); } guiDisplayDigest :: ~guiDisplayDigest() { if ( bWindowVisible_ ) { XtRemoveCallback( widGelWindow_, XmNexposeCallback, cbGelWindowExpose, this ); XtRemoveEventHandler( widGelWindow_, PointerMotionMask, False, (XtEventHandler) pointerMotionEventHandler, this ); XtPopdown( widPopupShell_ ); XtDestroyWidget( widPopupShell_ ); } aDigests_.clearAndDestroy(); int nIndex; if ( ( nIndex = ConsEd::pGetConsEd()->aGuiDisplayDigest_.index( this ) ) != RW_NPOS ) { ConsEd::pGetConsEd()->aGuiDisplayDigest_.removeAt( nIndex ); } } void guiDisplayDigest :: changeCurrentlyDisplayedDigest( digestForOneEnzyme* pNewDigest ) { pCurrentlyDisplayedDigest_ = pNewDigest; // nothing should be marked any longer pTempMarkedActualRestrictionFragment_ = NULL; pTempMarkedPredictedRestrictionFragment_ = NULL; pPermMarkedActualRestrictionFragment_ = NULL; pPermMarkedPredictedRestrictionFragment_ = NULL; XtVaSetValues( widCurrentlyDisplayedEnzymeBases_, XmNvalue, pCurrentlyDisplayedDigest_->soEnzymeBases_.data(), NULL ); calculateInitialZoomFactor(); setScrollBar(); nGelPositionAtTopOfGelWindow_ = nGetMinGelPosition(); XtVaSetValues( widGelScrollBar_, XmNvalue, nGelPositionAtTopOfGelWindow_, NULL ); updateTextDisplay(); displayGelWindow(); tellAssemblyView(); } void guiDisplayDigest :: setScrollBar() { int nIncrementInGelUnits = nGelScrollBarIncrementInPixels / fPixelsPerGelUnit_; int nGelUnitsDisplayedAtOnce = nGetGelWindowPixelHeight() / fPixelsPerGelUnit_; XtVaSetValues( widGelScrollBar_, XmNmaximum, nGetMaxGelPosition(), XmNminimum, nGetMinGelPosition(), XmNincrement, nIncrementInGelUnits, XmNsliderSize, nGelUnitsDisplayedAtOnce - 1, XmNpageIncrement, nGelUnitsDisplayedAtOnce, NULL ); } int guiDisplayDigest :: nGetGelWindowPixelHeight() { Dimension nHeight; XtVaGetValues( widGelWindow_, XmNheight, &nHeight, NULL ); return( nHeight ); } void guiDisplayDigest :: gotoEnd( const int nWhichEnd ) { // first get which item in the list the user selected int nRestrictionFragmentIndex; int* pPositionList; int nNumberOfSelectedItems; if ( XmListGetSelectedPos( widTextList_, &pPositionList, &nNumberOfSelectedItems ) ) { assert( nNumberOfSelectedItems == 1 ); nRestrictionFragmentIndex = pPositionList[0] - 1; // motif index // starts at 1 } else { popupErrorMessage2( widPopupShell_, "you must first select a fragment" ); return; } arrayOfRestrictionFragments* pPredictedFragmentArray = pGetPredictedFragmentsArray(); restrictionFragment* pResFrag = (*pPredictedFragmentArray)[ nRestrictionFragmentIndex ]; Contig* pContig; int nUnpadded; if ( nWhichEnd == nLeftGap ) { if ( pResFrag->fragLeft_ != restrictionFragment::IN_CONTIG ) { popupErrorMessage2( widPopupShell_, "The left end of the selected fragment is not in a contig.\nYou can only select go to a contig position." ); return; } pContig = pResFrag->pLeftContig_; nUnpadded = pResFrag->nUnpaddedLeft_; } else if ( nWhichEnd == nRightGap ) { if ( pResFrag->fragRight_ != restrictionFragment::IN_CONTIG ) { popupErrorMessage2( widPopupShell_, "The right end of the selected fragment is not in a contig.\nYou can only select go to a contig position." ); return; } pContig = pResFrag->pRightContig_; nUnpadded = pResFrag->nUnpaddedRight_; } else assert( false ); int nConsPos = pContig->nPaddedIndexFast( nUnpadded ); ContigWin* pContigWin = ConsEd::pGetConsEd()->pScrollExistingContigWinOrMakeNewContigWin( pContig, nConsPos ); pContigWin->moveCursorToConsPos( nConsPos ); // raise the window pContigWin->raiseWindow(); } const int nAsciiSize = 256; void guiDisplayDigest :: doSearch() { for( int nEnzyme = 0; nEnzyme < aSelectedEnzymeBases_.length(); ++nEnzyme ) { // find corresponding digestforOneEnzyme digestForOneEnzyme* pDigest = NULL; for( int nDigest = 0; nDigest < aDigests_.length(); ++nDigest ) { if ( aDigests_[ nDigest ]->soEnzymeName_ == aSelectedEnzymeNames_[ nEnzyme ] ) { pDigest = aDigests_[ nDigest ]; break; } } assert( pDigest ); assert( pDigest->soEnzymeBases_ == aSelectedEnzymeBases_[ nEnzyme ] ); // work out a match table that includes any ambiguity codes RWTPtrOrderedVector aIndexedByEnzymeBases( pDigest->soEnzymeBases_.length() ); aIndexedByEnzymeBases.soName_ = "aIndexedByEnzymeBases"; aIndexedByEnzymeBases.soName_ += " "; aIndexedByEnzymeBases.soName_ += aSelectedEnzymeNames_[ nEnzyme ]; for( int nEnzymeBase = 0; nEnzymeBase < pDigest->soEnzymeBases_.length(); ++nEnzymeBase ) { char cBase = pDigest->soEnzymeBases_[ nEnzymeBase ]; // a 256-byte lookup table that translates ambiguity codes // to yes/no depending a match to acgt unsigned char* pUC = (unsigned char*) malloc( sizeof(unsigned char) * nAsciiSize ); unsigned char ucDefaultValue; if ( cBase == 'n' ) { ucDefaultValue = 1; for( int n = 0; n < nAsciiSize; ++n ) pUC[n] = 1; } else { for( int n = 0; n < nAsciiSize; ++n ) pUC[n] = 0; if ( cBase == 'a' || cBase == 'c' || cBase == 'g' || cBase == 't' ) pUC[ cBase ] = 1; else if ( cBase == 'r' ) { pUC[ 'a' ] = 1; pUC[ 'g' ] = 1; } else if ( cBase == 'y' ) { pUC[ 'c' ] = 1; pUC[ 't' ] = 1; } else if ( cBase == 'm' ) { pUC[ 'a' ] = 1; pUC[ 'c' ] = 1; } else if ( cBase == 'k' ) { pUC[ 'g' ] = 1; pUC[ 't' ] = 1; } else if ( cBase == 's' ) { pUC[ 'c' ] = 1; pUC[ 'g' ] = 1; } else if ( cBase == 'w' ) { pUC[ 'a' ] = 1; pUC[ 't' ] = 1; } else if ( cBase == 'd' ) { pUC[ 'a' ] = 1; pUC[ 'g' ] = 1; pUC[ 't' ] = 1; } else if ( cBase == 'h' ) { pUC[ 'a' ] = 1; pUC[ 'c' ] = 1; pUC[ 't' ] = 1; } else if ( cBase == 'b' ) { pUC[ 'c' ] = 1; pUC[ 'g' ] = 1; pUC[ 't' ] = 1; } else if ( cBase == 'v' ) { pUC[ 'a' ] = 1; pUC[ 'c' ] = 1; pUC[ 'g' ] = 1; } } aIndexedByEnzymeBases.insert( pUC ); } // for( int nEnzymeBase = 0; ... pDigest->aPredictedResFragsBySize_.clear(); int nPositionOrderOfFragment = 0; if ( bUseUserDefinedContigMap_ ) { RWTPtrOrderedVector aScaffoldArray; RWCString soErrorMessage; ConsEd::pGetAssembly()->createScaffoldsFromUserContigMap( soUserEnteredContigMap_, nStartUnpaddedConsPos_, nEndUnpaddedConsPos_, &aScaffoldArray, soErrorMessage ); for( int nScaffold = 0; nScaffold < aScaffoldArray.length(); ++nScaffold ) { clScaffold* pScaffold = aScaffoldArray[ nScaffold ]; ConsEd::pGetAssembly()->getRestrictionFragmentsForOneScaffold( aIndexedByEnzymeBases, pDigest->aPredictedRestrictionFragmentsNotEndingAtVectorInsertJunction_, pDigest->aPredictedInsertRestrictionFragmentsEndingAtVectorInsertJunction_, pScaffold, nPositionOrderOfFragment ); cerr << "# of predicted fragments = " << pDigest->aPredictedRestrictionFragmentsNotEndingAtVectorInsertJunction_.length() << " and " << pDigest->aPredictedInsertRestrictionFragmentsEndingAtVectorInsertJunction_.length() << endl; } aScaffoldArray.clearAndDestroy(); } // if ( bJustPartNotWholeCloneDigest_ ) { else { for( int nScaffold = 0; nScaffold < ConsEd::pGetAssembly()->aHeadsOfScaffoldsOfContigs_.length(); ++nScaffold ) { clScaffold* pScaffold = ConsEd::pGetAssembly()->pCreateScaffold( nScaffold ); ConsEd::pGetAssembly()->getRestrictionFragmentsForOneScaffold( aIndexedByEnzymeBases, pDigest->aPredictedRestrictionFragmentsNotEndingAtVectorInsertJunction_, pDigest->aPredictedInsertRestrictionFragmentsEndingAtVectorInsertJunction_, pScaffold, nPositionOrderOfFragment ); delete pScaffold; } } getVectorFragments( aIndexedByEnzymeBases, pDigest->aPredictedRestrictionFragmentsNotEndingAtVectorInsertJunction_, pDigest->aPredictedVectorRestrictionFragmentsEndingAtVectorInsertJunction_, nPositionOrderOfFragment, pDigest->bNoCutSitesInVector_ ); if ( pDigest->bNoCutSitesInVector_ ) { cerr << "enzyme " << pDigest->soEnzymeName_ << " does not cut vector" << endl; } // for( int nFrag = 0; // nFrag < pDigest->aPredictedVectorRestrictionFragmentsEndingAtVectorInsertJunction_.length(); // ++nFrag ) { // restrictionFragment* pRes = // pDigest->aPredictedVectorRestrictionFragmentsEndingAtVectorInsertJunction_[ nFrag ]; // RWCString soMessage; // pRes->getDescriptionLine( soMessage ); // cerr << "partial vector fragment: " << soMessage << " for enzyme: " // << pDigest->soEnzymeName_ << endl; // } // now we need to put together the restriction fragments that end // at the vector-insert junction pDigest->processingAfterFindingAllPartialFragments( bFlipVectorFromTheDefault_ ); } // for( int nEnzyme = 0 ... // I put this here instead of in createWindow since there is no // point in assemblyView trying to display anything until here. // This needs to come before changeCurrentlyDisplayedDigest since // the latter calls tellAssemblyView which calls drawEverything // which will only draw cut sites if // ConsEd::pGetConsEd()->pGuiDisplayDigest_ is set. ConsEd::pGetConsEd()->aGuiDisplayDigest_.insert( this ); // start display with the 0th enzyme changeCurrentlyDisplayedDigest( aDigests_[0] ); // updateDisplays(); don't think I need this here... } void guiDisplayDigest :: getVectorFragments( RWTPtrOrderedVector& aIndexedByEnzymeBases, RWTPtrOrderedVector& aRestrictionFragments, RWTPtrOrderedVector& aRestrictionFragmentsEndingAtAVectorInsertJunction, int& nPositionOrderOfFragment, bool& bNoCutSitesInVector ) { RWTValOrderedVector aCutSites; for( int nVectorBase = 0; nVectorBase < ( (int) soVectorSequence_.length() - (int) aIndexedByEnzymeBases.length() + 1 ); ++nVectorBase ) { bool bMatch = true; for( int nEnzymeBase = 0; nEnzymeBase < aIndexedByEnzymeBases.length(); ++nEnzymeBase ) { char cVectorBase = soVectorSequence_[ nVectorBase + nEnzymeBase ]; if ( ! ( aIndexedByEnzymeBases[ nEnzymeBase ] )[ cVectorBase ] ) { bMatch = false; break; } } if ( bMatch ) { // found a perfect match aCutSites.insert( nVectorBase ); } } if ( aCutSites.length() == 0 ) bNoCutSitesInVector = true; else bNoCutSitesInVector = false; for( int nCutSite = 0; nCutSite < aCutSites.length(); ++nCutSite ) { restrictionFragment* pRes = new restrictionFragment( restrictionFragment::PREDICTED_FRAGMENT ); pRes->bVectorFragment_ = true; pRes->nPositionOrder_ = nPositionOrderOfFragment; ++nPositionOrderOfFragment; if ( nCutSite == 0 ) { pRes->fragLeft_ = restrictionFragment::AT_VECTOR_INSERT_JUNCTION; pRes->nUnpaddedLeft_ = 1; pRes->nSize_ = aCutSites[ nCutSite ]; aRestrictionFragmentsEndingAtAVectorInsertJunction.insert( pRes ); } else { pRes->fragLeft_ = restrictionFragment::IN_VECTOR; pRes->nUnpaddedLeft_ = aCutSites[ nCutSite - 1]; pRes->nSize_ = aCutSites[ nCutSite ] - aCutSites[ nCutSite - 1]; aRestrictionFragments.insert( pRes ); } pRes->fragRight_ = restrictionFragment::IN_VECTOR; pRes->nUnpaddedRight_ = aCutSites[ nCutSite ]; } // deal with last fragment, keeping in mind that there may be no // cut sites at all in the vector restrictionFragment* pRes = new restrictionFragment( restrictionFragment::PREDICTED_FRAGMENT ); pRes->bVectorFragment_ = true; aRestrictionFragmentsEndingAtAVectorInsertJunction.insert( pRes ); pRes->nPositionOrder_ = nPositionOrderOfFragment; ++nPositionOrderOfFragment; if ( aCutSites.length() == 0 ) { pRes->fragLeft_ = restrictionFragment::AT_VECTOR_INSERT_JUNCTION; pRes->nUnpaddedLeft_ = 1; pRes->nSize_ = soVectorSequence_.length(); } else { pRes->fragLeft_ = restrictionFragment::IN_VECTOR; pRes->nUnpaddedLeft_ = aCutSites[ aCutSites.length() - 1 ]; pRes->nSize_ = soVectorSequence_.length() - aCutSites[ aCutSites.length() - 1 ]; } pRes->fragRight_ = restrictionFragment::AT_VECTOR_INSERT_JUNCTION; pRes->nUnpaddedRight_ = soVectorSequence_.length() - 1; } void guiDisplayDigest :: userChangedEnzyme( Widget wid ) { // find which enzyme the user changed to: int nIndex = aEnzymeWidgets_.index( wid ); assert( nIndex != RW_NPOS ); changeCurrentlyDisplayedDigest( aDigests_[ nIndex ] ); } void guiDisplayDigest :: displayGelWindow() { // handle case in which the window just came up and the fragments // have not yet been created if ( !pCurrentlyDisplayedDigest_ ) return; clearGelWindow(); drawTitles(); // store target positions for determining where the cursor is aVisibleLinesForPredictedFragments_.clear(); int nMinGelPosition = nGetGelPositionAtTopOfGelWindow(); int nMaxGelPosition = nGetGelPositionAtBottomOfGelWindow(); int nLastPixelY = -666; for( int nPredicted = 0; nPredicted < pCurrentlyDisplayedDigest_->aPredictedResFragsBySize_.length(); ++nPredicted ) { restrictionFragment* pFrag = pCurrentlyDisplayedDigest_->aPredictedResFragsBySize_[ nPredicted ]; if ( pFrag->fPositionOnGel_ < nMinGelPosition ) continue; if ( pFrag->fPositionOnGel_ > nMaxGelPosition ) break; // store target positions for determining where the cursor is int nPixelY = nGetPixelYFromGelPosition( pFrag->fPositionOnGel_ ); if ( nLastPixelY != nPixelY ) { nLastPixelY = nPixelY; aVisibleLinesForPredictedFragments_.insert( visibleLineForRestrictionFragments( nPixelY, pFrag, restrictionFragment::PREDICTED_FRAGMENT ) ); } else { visibleLineForRestrictionFragments& vis = aVisibleLinesForPredictedFragments_[ aVisibleLinesForPredictedFragments_.length() - 1 ]; vis.aFragmentsAtSamePixel_.insert( pFrag ); } } // store target positions for determining where the cursor is aVisibleLinesForActualFragments_.clear(); nLastPixelY = -666; for( int nActual = 0; nActual < pCurrentlyDisplayedDigest_-> aActualRestrictionFragments_.length(); ++nActual ) { restrictionFragment* pActualFrag = pCurrentlyDisplayedDigest_->aActualRestrictionFragments_[ nActual ]; if ( pActualFrag->fPositionOnGel_ < nMinGelPosition ) continue; if ( pActualFrag->fPositionOnGel_ > nMaxGelPosition ) break; // store targets positions for determining where the cursor is int nPixelY = nGetPixelYFromGelPosition( pActualFrag->fPositionOnGel_ ); if ( nLastPixelY != nPixelY ) { nLastPixelY = nPixelY; aVisibleLinesForActualFragments_.insert( visibleLineForRestrictionFragments( nPixelY, pActualFrag, restrictionFragment::ACTUAL_FRAGMENT ) ); } else { visibleLineForRestrictionFragments& vis = aVisibleLinesForActualFragments_[ aVisibleLinesForActualFragments_.length() - 1 ]; vis.aFragmentsAtSamePixel_.insert( pActualFrag ); } } expandVisibleLines(); int nVisible; for( nVisible = 0; nVisible < aVisibleLinesForPredictedFragments_.length(); ++nVisible ) { drawLineForPredictedFragment( &( aVisibleLinesForPredictedFragments_[ nVisible ] ) ); } for( nVisible = 0; nVisible < aVisibleLinesForActualFragments_.length(); ++nVisible ) { drawLineForActualFragment( &( aVisibleLinesForActualFragments_[ nVisible ] ) ); } drawGelWindowScale(); drawTempVisibleLines(); drawPermVisibleLines(); } void guiDisplayDigest :: userPushedZoomInOrOut( Widget wid ) { if ( wid == widZoomIn_ ) { // if zooming in, try to keep whatever is in the middle, still in // the middle int nGelPositionInMiddle = ( nGelPositionAtTopOfGelWindow_ + nGetGelPositionAtBottomOfGelWindow() ) / 2; fPixelsPerGelUnit_ *= pCP->dRestrictionDigestZoomFactor_; int nPixelOfMiddle = nGetGelWindowPixelHeight() / 2; nGelPositionAtTopOfGelWindow_ = nGelPositionInMiddle - nPixelOfMiddle / fPixelsPerGelUnit_; if ( nGelPositionAtTopOfGelWindow_ < 0 ) { RWCString soError = "nGelPositionAtTopOfGelWindow_ = " + RWCString( (long) nGelPositionAtTopOfGelWindow_ ) + " nGelPositionInMiddle = " + RWCString( (long) nGelPositionInMiddle ); THROW_ERROR2( soError ); } // if nGelPositionAtTopOfGelWindow_ is changed, then // XmNvalue of the scrollbar must be changed also. Otherwise, // the next time the user moves the scrollbar, it will move // from its previous position and give a value that is // way off from what is currently being displayed. XtVaSetValues( widGelScrollBar_, XmNvalue, nGelPositionAtTopOfGelWindow_, NULL ); } else if ( wid == widZoomOut_ ) { fPixelsPerGelUnit_ /= pCP->dRestrictionDigestZoomFactor_; } else if ( wid == widZoomOriginal_ ) { calculateInitialZoomFactor(); } else assert( false ); adjustScrollBarWhenZoom(); displayGelWindow(); } void guiDisplayDigest :: adjustScrollBarWhenZoom() { int nGelUnitsPerScrollBarClick = (float) nGelScrollBarIncrementInPixels / fPixelsPerGelUnit_; int nGelUnitsDisplayedAtOnce = nGetGelWindowPixelHeight() / fPixelsPerGelUnit_; XtVaSetValues( widGelScrollBar_, XmNincrement, nGelUnitsPerScrollBarClick, XmNsliderSize, nGelUnitsDisplayedAtOnce - 1, XmNpageIncrement, nGelUnitsDisplayedAtOnce, NULL ); } void guiDisplayDigest :: drawGelWindowScale() { drawScaleLine(); // now draw the scale ticks for sizes int nMinFragSizeInWindow; if ( ! ConsEd::bCouldGetFragmentSizeFromGelPosition( nGetGelPositionAtBottomOfGelWindow(), nMinFragSizeInWindow ) ) return; // find bases of bottom-most tick. Do this by "rounding" // nMinFragSizeInWindow up to the nearest multiple of a power of // ten. // bottom of window // bottom tick mark // 151 200? 1000? 10000? 100000? // 251 300? 1000? 10000? 100000? // 351 400? 1000? 10000? 100000? // 451 500? 1000? 10000? 100000? // 551 600? 1000? 10000? 100000? // 661 700? 1000? 10000? 100000? // 991 1000? 10000? 100000? // 1000 1000? 10000? 100000? // 1001 2000? 10000? 100000? int nPowerOfTen; int nMultipleOfPowerOfTen; int nPixelOfScaleTick; if ( !bCouldGetBottomScaleTickFragmentSize( nPowerOfTen, nMultipleOfPowerOfTen, nPixelOfScaleTick ) ) return; if ( nPixelOfScaleTick < 0 ) return; int nFragmentSize = nPowerOfTen * nMultipleOfPowerOfTen; drawScaleTickForFragmentSize( nFragmentSize ); while( bCouldGetNextFragmentSizeScaleTick( nPowerOfTen, nMultipleOfPowerOfTen, nPixelOfScaleTick ) ) { if ( nPixelOfScaleTick < 0 ) return; drawScaleTickForFragmentSize( nPowerOfTen * nMultipleOfPowerOfTen ); } } void guiDisplayDigest :: drawScaleLine() { XDrawLine( XtDisplay( widGelWindow_ ), XtWindow( widGelWindow_ ), GuiApp::pGetGuiApp()->pColorOfRestrictionDigestScale_->gcGet(), nGetGelScaleCenter(), 0, nGetGelScaleCenter(), nGetGelWindowPixelHeight() ); } void guiDisplayDigest :: drawScaleTickForFragmentSize( const int nBases ) { int nGelPosition = ConsEd::fGetPositionOnGelFromRestrictionFragmentSize( nBases ); int nPixelY = nGetPixelYFromGelPosition( nGelPosition ); XDrawLine( XtDisplay( widGelWindow_ ), XtWindow( widGelWindow_ ), GuiApp::pGetGuiApp()->pColorOfRestrictionDigestScale_->gcGet(), nGetGelScaleCenter(), nPixelY, nGetRightEndGelScaleTick(), nPixelY ); int nLength = sprintf( szNumber, "%d", nBases ); nPixelY += (GuiApp::nGetFontAscent() / 2 ); XDrawString( XtDisplay( widGelWindow_ ), XtWindow( widGelWindow_ ), GuiApp::pGetGuiApp()->pColorOfRestrictionDigestScale_->gcGet(), nGetLeftEndScaleNumber2(), nPixelY, szNumber, nLength ); } int guiDisplayDigest :: nGetGelPositionAtBottomOfGelWindow() { int nPixelAtBottom = nGetGelWindowPixelHeight(); int nWindowHeightInGelUnits = nGetGelWindowPixelHeight() / fPixelsPerGelUnit_; return( nWindowHeightInGelUnits + nGelPositionAtTopOfGelWindow_ ); } bool guiDisplayDigest :: bCouldGetBottomScaleTickFragmentSize( int& nPowerOfTen, int& nMultipleOfPowerOfTen, int& nPixelOfBottomScaleTick ) { // Near the bottom of the screen, see what nGetFontAscent in pixels // translates to in bases. Use this (rounded to a power of 10) as the // initial scale increment size. int nMinFragSizeInWindow; if ( ! ConsEd::bCouldGetFragmentSizeFromGelPosition( nGetGelPositionAtBottomOfGelWindow(), nMinFragSizeInWindow ) ) return( false ); int nNextClosestFragSizeInWindow; if ( ! bCouldGetFragmentSizeFromPixelY( nGetGelWindowPixelHeight() - GuiApp::nGetFontAscent(), nNextClosestFragSizeInWindow ) ) return( false ); int nMinFragSizeDifference = nNextClosestFragSizeInWindow - nMinFragSizeInWindow; // pathological case if ( nMinFragSizeDifference <= 1 ) { nPowerOfTen = 1; } else { // normal case nPowerOfTen = 1; while( nPowerOfTen < nMinFragSizeDifference ) { nPowerOfTen *= 10; } assert( nPowerOfTen >= nMinFragSizeDifference ); assert( nPowerOfTen/10 < nMinFragSizeDifference ); } // round up nMultipleOfPowerOfTen = ( nMinFragSizeInWindow + nPowerOfTen - 1 ) / nPowerOfTen; nPixelOfBottomScaleTick = nGetPixelYFromRestrictionFragmentSize( nPowerOfTen * nMultipleOfPowerOfTen ); return( true ); } bool guiDisplayDigest :: bCouldGetNextFragmentSizeScaleTick( int& nPowerOfTenOfPreviousScaleTick, int& nMultipleOfPowerOfTen, int& nPixelOfPreviousScaleTick ) { // let's try the obvious--just increment the nMultipleOfPowerOfTen int nFragmentSizeOfNextScaleTick = ( nMultipleOfPowerOfTen + 1 ) * nPowerOfTenOfPreviousScaleTick; int nPixelOfNextScaleTick = nGetPixelYFromRestrictionFragmentSize( nFragmentSizeOfNextScaleTick ); if ( nPixelOfNextScaleTick < 0 ) return( false ); if ( ABS( nPixelOfPreviousScaleTick - nPixelOfNextScaleTick ) >= GuiApp::nGetFontAscent() ) { nPixelOfPreviousScaleTick = nPixelOfNextScaleTick; nMultipleOfPowerOfTen += 1; return( true ); } // try jumping to the next power of ten while( nPowerOfTenOfPreviousScaleTick < nHugeRestrictionFragment ) { nPowerOfTenOfPreviousScaleTick *= 10; // we must have a nMultipleOfPowerOfTen that is large // enough so that the next tick is at least nFragmentSizeOfNextScaleTick nMultipleOfPowerOfTen = ( nFragmentSizeOfNextScaleTick + nPowerOfTenOfPreviousScaleTick - 1 ) / nPowerOfTenOfPreviousScaleTick; nPixelOfNextScaleTick = nGetPixelYFromRestrictionFragmentSize( nPowerOfTenOfPreviousScaleTick * nMultipleOfPowerOfTen ); if ( nPixelOfNextScaleTick < 0 ) return( false ); if ( ABS( nPixelOfPreviousScaleTick - nPixelOfNextScaleTick ) >= GuiApp::nGetFontAscent() ) { nPixelOfPreviousScaleTick = nPixelOfNextScaleTick; return( true ); } } return( false ); } bool guiDisplayDigest :: bCouldGetFragmentSizeFromPixelY( const int nPixelY, int& nFragSize ) { float fGelPosition = fGetGelPositionFromPixelY( nPixelY ); if ( ConsEd::bCouldGetFragmentSizeFromGelPosition( fGelPosition, nFragSize ) ) return( true ); else return( false ); } void guiDisplayDigest :: calculateInitialZoomFactor() { // figure out the 10th percentile fragment size int n10PercentilePosition = pCurrentlyDisplayedDigest_->aActualRestrictionFragments_.length() * 0.9; if ( n10PercentilePosition >= pCurrentlyDisplayedDigest_->aActualRestrictionFragments_.length() ) return; int n10PercentileFragSize = pCurrentlyDisplayedDigest_->aActualRestrictionFragments_[ n10PercentilePosition ]->nSize_; float fGelPositionOfTenthPercentileFragment = ConsEd::fGetPositionOnGelFromRestrictionFragmentSize( n10PercentileFragSize ); // So make sure that this gel position will be located near the bottom // of the screen. fPixelsPerGelUnit_ = ( (float) ( nGetGelWindowPixelHeight() - GuiApp::nGetFontAscent() ) ) / ( fGelPositionOfTenthPercentileFragment - (float) nGetMinGelPosition() ); } const int nHalfVisibleLineTargetHeight = 16; void guiDisplayDigest :: expandVisibleLines() { expandVisibleLines2( &aVisibleLinesForPredictedFragments_ ); expandVisibleLines2( &aVisibleLinesForActualFragments_ ); } void guiDisplayDigest :: expandVisibleLines2( RWTValOrderedVector* pVisibleLineArray ) { for( int nLine = 1; nLine < pVisibleLineArray->length(); ++nLine ) { visibleLineForRestrictionFragments& vis1 = (*pVisibleLineArray)[ nLine - 1]; visibleLineForRestrictionFragments& vis2 = (*pVisibleLineArray)[ nLine ]; int nMidPixel = ( vis1.nBottomPixel_ + vis2.nTopPixel_ ) / 2; // if vis1.nBottomPixel_ and vis2.nTopPixel_ are only 1 pixel // apart, nMidPixel will be which one? It will be the top (smaller) // one. That is the reason (below) that the top vis gets // nMidPixel and the bottom vis gets the nMidPixel + 1 vis1.nBottomPixel_ = MIN( nMidPixel, vis1.nBottomPixel_ + nHalfVisibleLineTargetHeight ); vis2.nTopPixel_ = MAX( nMidPixel + 1, vis2.nTopPixel_ - nHalfVisibleLineTargetHeight ); } // still need to handle the top of the top and the bottom of the bottom if ( pVisibleLineArray->length() > 0 ) { (*pVisibleLineArray)[0].nTopPixel_ -= nHalfVisibleLineTargetHeight; (*pVisibleLineArray)[ pVisibleLineArray->length() - 1 ].nBottomPixel_ += nHalfVisibleLineTargetHeight; } } void guiDisplayDigest :: pointerMoved( const int nPixelX, const int nPixelY ) { restrictionFragment* pNewActualResFrag; restrictionFragment* pNewPredictedResFrag; getFragmentsAtPosition( nPixelX, nPixelY, pNewActualResFrag, pNewPredictedResFrag ); // if pointer hasn't moved much, no need to redraw if ( pNewActualResFrag == pTempMarkedActualRestrictionFragment_ && pNewPredictedResFrag == pTempMarkedPredictedRestrictionFragment_ ) return; clearTempVisibleLines(); drawPermVisibleLines(); pTempMarkedActualRestrictionFragment_ = pNewActualResFrag; pTempMarkedPredictedRestrictionFragment_ = pNewPredictedResFrag; drawTempVisibleLines(); } void guiDisplayDigest :: clearTempVisibleLines() { clearLineIndicator( restrictionFragment::ACTUAL_FRAGMENT, false ); clearLineIndicator( restrictionFragment::PREDICTED_FRAGMENT, false ); } void guiDisplayDigest :: clearPermVisibleLines() { clearLineIndicator( restrictionFragment::ACTUAL_FRAGMENT, true ); clearLineIndicator( restrictionFragment::PREDICTED_FRAGMENT, true ); } void guiDisplayDigest :: clearLineIndicator( const unsigned char cActualOrPredicted, const bool bPermNotTemp ) { restrictionFragment* pRes; if ( cActualOrPredicted == restrictionFragment::ACTUAL_FRAGMENT ) { if ( bPermNotTemp ) { pRes = pPermMarkedActualRestrictionFragment_; pPermMarkedActualRestrictionFragment_ = NULL; } else { pRes = pTempMarkedActualRestrictionFragment_; pTempMarkedActualRestrictionFragment_ = NULL; } } else { if ( bPermNotTemp ) { pRes = pPermMarkedPredictedRestrictionFragment_; pPermMarkedPredictedRestrictionFragment_ = NULL; } else { pRes = pTempMarkedPredictedRestrictionFragment_; pTempMarkedPredictedRestrictionFragment_ = NULL; } } if ( !pRes ) return; int nPixelYOfLine = nGetPixelYFromGelPosition( pRes->fPositionOnGel_ ); clearLineIndicator2( cActualOrPredicted, nPixelYOfLine ); } void guiDisplayDigest :: clearLineIndicator2( unsigned char cActualOrPredicted, const int nPixelYOfLine ) { // erase arrow int nX; if ( cActualOrPredicted == restrictionFragment::ACTUAL_FRAGMENT ) { nX = nGetLeftEndOfLeftArrowForActualFragment(); } else { nX = nGetLeftEndOfRightArrowForPredictedFragment(); } XClearArea( XtDisplay( widGelWindow_ ), XtWindow( widGelWindow_ ), nX, nPixelYOfLine - nHalfHeightOfCursorIndicator, nArrowWidth, 2*nHalfHeightOfCursorIndicator, False ); // erase numbers int nWidth = nMaxDigitsFragmentSize * GuiApp::nGetFontWidth(); int nY = nPixelYOfLine - GuiApp::nGetFontAscent() / 2; if ( cActualOrPredicted == restrictionFragment::ACTUAL_FRAGMENT ) { nX = nGetLeftEndOfActualFragmentSizeOnGel(); } else { nX = nGetLeftEndOfPredictedFragmentSizeOnGel(); } XClearArea( XtDisplay( widGelWindow_ ), XtWindow( widGelWindow_ ), nX, nY, nWidth, GuiApp::nGetFontAscent(), False ); } void guiDisplayDigest :: drawTempVisibleLines() { drawVisibleLine( restrictionFragment::ACTUAL_FRAGMENT, false ); drawVisibleLine( restrictionFragment::PREDICTED_FRAGMENT, false ); } void guiDisplayDigest :: drawPermVisibleLines() { drawVisibleLine( restrictionFragment::ACTUAL_FRAGMENT, true ); drawVisibleLine( restrictionFragment::PREDICTED_FRAGMENT, true ); } void guiDisplayDigest :: drawVisibleLine( const unsigned char cActualOrPredicted, const bool bPermNotTemp ) { restrictionFragment* pResFrag; if ( cActualOrPredicted == restrictionFragment::ACTUAL_FRAGMENT ) { if ( bPermNotTemp ) pResFrag = pPermMarkedActualRestrictionFragment_; else pResFrag = pTempMarkedActualRestrictionFragment_; } else { if ( bPermNotTemp ) pResFrag = pPermMarkedPredictedRestrictionFragment_; else pResFrag = pTempMarkedPredictedRestrictionFragment_; } if ( !pResFrag ) return; visibleLineForRestrictionFragments* pVis = pGetVisibleLineFromRestrictionFragment( pResFrag ); // case in which the marked restriction fragment is off the screen if ( !pVis ) return; int nPixelYOfLine = pVis->nMiddlePixel_; // clear the area we are going to draw to clearLineIndicator2( cActualOrPredicted, nPixelYOfLine ); int nNumberOfPoints; XPoint aPoint[ 6 ]; if ( bPermNotTemp ) { nNumberOfPoints = 5; if ( cActualOrPredicted == restrictionFragment::ACTUAL_FRAGMENT ) { // point 0,4 // point1 point 3 // point 2 aPoint[0].x = nGetLeftEndOfLeftArrowForActualFragment() + nArrowWidth / 2; aPoint[0].y = nPixelYOfLine - nHalfHeightOfCursorIndicator; aPoint[1].x = nGetLeftEndOfLeftArrowForActualFragment(); aPoint[1].y = nPixelYOfLine; aPoint[2].x = aPoint[0].x; aPoint[2].y = nPixelYOfLine + nHalfHeightOfCursorIndicator; aPoint[3].x = nGetRightEndOfLeftArrowForActualFragment(); aPoint[3].y = aPoint[1].y; aPoint[4] = aPoint[0]; } else { // point 0,4 // point 3 point 1 // point 2 aPoint[0].x = nGetRightEndOfRightArrowForPredictedFragment() - nArrowWidth / 2; aPoint[0].y = nPixelYOfLine - nHalfHeightOfCursorIndicator; aPoint[1].x = nGetRightEndOfRightArrowForPredictedFragment(); aPoint[1].y = nPixelYOfLine; aPoint[2].x = aPoint[0].x; aPoint[2].y = nPixelYOfLine + nHalfHeightOfCursorIndicator; aPoint[3].x = nGetLeftEndOfRightArrowForPredictedFragment(); aPoint[3].y = nPixelYOfLine; aPoint[4] = aPoint[0]; } } else { nNumberOfPoints = 4; if ( cActualOrPredicted == restrictionFragment::ACTUAL_FRAGMENT ) { aPoint[0].x = nGetLeftEndOfLeftArrowForActualFragment(); aPoint[0].y = nPixelYOfLine - nHalfHeightOfCursorIndicator; aPoint[1].x = aPoint[0].x; aPoint[1].y = aPoint[0].y + 2 * nHalfHeightOfCursorIndicator; aPoint[2].x = nGetRightEndOfLeftArrowForActualFragment(); aPoint[2].y = aPoint[0].y + nHalfHeightOfCursorIndicator; aPoint[3] = aPoint[0]; } else { aPoint[0].x = nGetRightEndOfRightArrowForPredictedFragment(); aPoint[0].y = nPixelYOfLine - nHalfHeightOfCursorIndicator; aPoint[1].x = aPoint[0].x; aPoint[1].y = aPoint[0].y + 2 * nHalfHeightOfCursorIndicator; aPoint[2].x = nGetLeftEndOfRightArrowForPredictedFragment(); aPoint[2].y = aPoint[0].y + nHalfHeightOfCursorIndicator; aPoint[3] = aPoint[0]; } } XFillPolygon( XtDisplay( widGelWindow_ ), XtWindow( widGelWindow_ ), pVis->pGetGuiColorText()->gcGet(), aPoint, nNumberOfPoints, Convex, CoordModeOrigin ); // now draw the fragment size, using the first // fragment's size int nLength; if ( pVis->aFragmentsAtSamePixel_.length() == 1 ) nLength = sprintf( szNumber, "%d", pResFrag->nSize_ ); else { if ( cActualOrPredicted == restrictionFragment::ACTUAL_FRAGMENT ) nLength = sprintf( szNumber, "(%d) %d", pVis->aFragmentsAtSamePixel_.length(), pResFrag->nSize_ ); else nLength = sprintf( szNumber, "%d (%d)", pResFrag->nSize_, pVis->aFragmentsAtSamePixel_.length() ); } int nX; if ( cActualOrPredicted == restrictionFragment::ACTUAL_FRAGMENT ) nX = nGetRightEndOfActualFragmentSizeOnGel() - nLength * GuiApp::nGetFontWidth(); else nX = nGetLeftEndOfPredictedFragmentSizeOnGel(); int nY = nPixelYOfLine + GuiApp::nGetFontAscent() / 2; XDrawString( XtDisplay( widGelWindow_ ), XtWindow( widGelWindow_ ), pVis->pGetGuiColorText()->gcGet(), nX, nY, szNumber, nLength ); } visibleLineForRestrictionFragments* guiDisplayDigest :: pGetVisibleLineFromRestrictionFragment( restrictionFragment* pResFrag ) { visibleLineForRestrictionFragments* pVis; if ( pResFrag->cActualOrPredictedFragment_ == restrictionFragment::ACTUAL_FRAGMENT ) { pVis = pGetVisibleLineForActualRestrictionFragments( nGetPixelYFromGelPosition( pResFrag->fPositionOnGel_ ) ); } else { pVis = pGetVisibleLineForPredictedRestrictionFragments( nGetPixelYFromGelPosition( pResFrag->fPositionOnGel_ ) ); } return( pVis ); } void guiDisplayDigest :: getFragmentsAtPosition( const int nPointerPixelX, const int nPointerPixelY, restrictionFragment*& pNewActualRestrictionFragment, restrictionFragment*& pNewPredictedRestrictionFragment ) { visibleLineForRestrictionFragments* pNewActualVisibleLine = pGetVisibleLineForActualRestrictionFragments( nPointerPixelY ); if ( pNewActualVisibleLine ) pNewActualRestrictionFragment = pNewActualVisibleLine->aFragmentsAtSamePixel_[0]; else pNewActualRestrictionFragment = NULL; visibleLineForRestrictionFragments* pNewPredictedVisibleLine = pGetVisibleLineForPredictedRestrictionFragments( nPointerPixelY ); if ( pNewPredictedVisibleLine ) pNewPredictedRestrictionFragment = pNewPredictedVisibleLine->aFragmentsAtSamePixel_[0]; else pNewPredictedRestrictionFragment = NULL; } visibleLineForRestrictionFragments* guiDisplayDigest :: pGetVisibleLineForPredictedRestrictionFragments( const int nPointerPixelY ) { return( pGetVisibleLineForRestrictionFragments2( nPointerPixelY, &aVisibleLinesForPredictedFragments_ ) ); } visibleLineForRestrictionFragments* guiDisplayDigest :: pGetVisibleLineForActualRestrictionFragments( const int nPointerPixelY ) { return( pGetVisibleLineForRestrictionFragments2( nPointerPixelY, &aVisibleLinesForActualFragments_ ) ); } visibleLineForRestrictionFragments* guiDisplayDigest :: pGetVisibleLineForRestrictionFragments2( const int nPointerPixelY, RWTValOrderedVector* pVisibleLineArray ) { if ( pVisibleLineArray->length() == 0 ) return( NULL ); int nTooSmallIndex = 0; int nMaxIndex = pVisibleLineArray->length() - 1; // region A // ------------ nTooSmallIndex top // B // ------------ nTooSmallIndex bottom // C // // ------------ nMaxIndex top // D // ------------ nMaxIndex bottom // E // // The loop assumes that the nPointerPixelY lies within either C or D. // Thus we need to first handle the other cases: // case of region E: if ( (*pVisibleLineArray)[ nMaxIndex ].nBottomPixel_ < nPointerPixelY ) return( NULL ); // case of regions A and B: if ( nPointerPixelY <= (*pVisibleLineArray)[ nTooSmallIndex ].nBottomPixel_ ) { // case of region A if ( nPointerPixelY < (*pVisibleLineArray)[ nTooSmallIndex ].nTopPixel_ ) return( NULL ); else { // case of region B return( &( (*pVisibleLineArray)[ nTooSmallIndex ] ) ); } } // region A // ------------ nTooSmallIndex top // B // ------------ nTooSmallIndex bottom // C // ------------ nTestIndex top // F // ------------ nTestIndex bottom // G // // ------------ nMaxIndex top // D // ------------ nMaxIndex bottom // E // while( 1 ) { if ( nMaxIndex - nTooSmallIndex == 1 ) { // nMaxIndex is the candidate if ( (*pVisibleLineArray)[ nMaxIndex ].nTopPixel_ <= nPointerPixelY ) { return( &( (*pVisibleLineArray)[ nMaxIndex ] ) ); } else return( NULL ); } else { int nTestIndex = ( nTooSmallIndex + nMaxIndex ) / 2; if ( (*pVisibleLineArray)[ nTestIndex ].nBottomPixel_ < nPointerPixelY ) // case of pointer in region G or D nTooSmallIndex = nTestIndex; else // case of pointer in region C or F nMaxIndex = nTestIndex; } } } void guiDisplayDigest :: userClicked( XtPointer pCallData ) { if ( ((XmDrawingAreaCallbackStruct*) pCallData )->event->xany.type != ButtonPress ) return; int nPixelX = ((XmDrawingAreaCallbackStruct*) pCallData )->event->xbutton.x; int nPixelY = ((XmDrawingAreaCallbackStruct*) pCallData )->event->xbutton.y; // just in case the temp cursors haven't yet caught up with the // pointer, move them pointerMoved( nPixelX, nPixelY ); // now, which one of the temp cursors is the user pointing at? bool bActualNotPredictedFragment; restrictionFragment* pNewPermRes; restrictionFragment* pOldPermRes; if ( nPixelX <= nGetActualFragmentRightEndOnGel() ) { pNewPermRes = pTempMarkedActualRestrictionFragment_; pOldPermRes = pPermMarkedActualRestrictionFragment_; pPermMarkedActualRestrictionFragment_ = pNewPermRes; bActualNotPredictedFragment = true; } else { pNewPermRes = pTempMarkedPredictedRestrictionFragment_; pOldPermRes = pPermMarkedPredictedRestrictionFragment_; pPermMarkedPredictedRestrictionFragment_ = pNewPermRes; bActualNotPredictedFragment = false; } if ( !pNewPermRes ) { popupErrorMessage2( widPopupShell_, "Before clicking, you must first point to a band so that an arrow points to it" ); return; } // if ( !bActualNotPredictedFragment && // ( pNewPermVis->aFragmentsAtSamePixel_.length() > 1 ) ) { // RWCString soMessage = "Warning--that line represents the following fragments of sizes: "; // for( int nFrag = 0; // nFrag < pNewPermVis->aFragmentsAtSamePixel_.length(); // ++nFrag ) { // restrictionFragment* pFrag = // pNewPermVis->aFragmentsAtSamePixel_[ nFrag ]; // soMessage += RWCString( (long) pFrag->nSize_ ); // soMessage += " "; // } // soMessage += " so I don't know which fragment you are referring to"; // popupErrorMessage2( widPopupShell_, soMessage ); // } if ( pNewPermRes->cActualOrPredictedFragment_ == restrictionFragment::PREDICTED_FRAGMENT ) { highlightTextWindowLineForPredictedFragment( pNewPermRes ); } // erase the perm indicators in the last place if ( pOldPermRes ) { clearLineIndicator2( pOldPermRes->cActualOrPredictedFragment_, nGetPixelYFromGelPosition( pOldPermRes->fPositionOnGel_ ) ); } drawVisibleLine( pNewPermRes->cActualOrPredictedFragment_, true ); } void guiDisplayDigest :: highlightTextWindowLineForPredictedFragment( restrictionFragment* pResFragClickedOn ) { // find that fragment in the list arrayOfRestrictionFragments* pPredictedFragmentArray = pGetPredictedFragmentsArray(); int nChosenFrag = -666; for( int nPredicted = 0; nPredicted < pPredictedFragmentArray->length(); ++nPredicted ) { restrictionFragment* pResFrag = (*pPredictedFragmentArray)[ nPredicted ]; if ( pResFrag == pResFragClickedOn ) { nChosenFrag = nPredicted; break; } } assert( nChosenFrag != -666 ); // convert the index to 1-based as required by XmTextList widgets int nIndexInMotifList = nChosenFrag + 1; int nTopIndex; int nVisibleItems; XtVaGetValues( widTextList_, XmNtopItemPosition, &nTopIndex, XmNvisibleItemCount, &nVisibleItems, NULL ); int nBottomIndex = nTopIndex + nVisibleItems - 1; if ( nIndexInMotifList < nTopIndex || nBottomIndex < nIndexInMotifList ) { // the item we want to select is not visible, so make it so. int nNewTopIndex = nIndexInMotifList - nVisibleItems / 2; if ( nNewTopIndex < 1 ) nNewTopIndex = 1; XmListSetPos( widTextList_, nNewTopIndex ); } XmListSelectPos( widTextList_, nIndexInMotifList, True ); highlightContigMapForFragment( pResFragClickedOn ); } void guiDisplayDigest :: drawTitles() { char* szActual = "Real"; char* szPredicted = "In-silico"; int nY = nGetTitleBaseline(); int nLength = strlen( szActual ); int nX = nGetActualFragmentRightEndOnGel() - nLength * GuiApp::nGetFontWidth(); XDrawString( XtDisplay( widGelWindow_ ), XtWindow( widGelWindow_ ), GuiApp::pGetGuiApp()->pColorOfRestrictionDigestScale_->gcGet(), nX, nY, szActual, nLength ); nX = nGetPredictedFragmentLeftEndOnGel(); nLength = strlen( szPredicted ); XDrawString( XtDisplay( widGelWindow_ ), XtWindow( widGelWindow_ ), GuiApp::pGetGuiApp()->pColorOfRestrictionDigestScale_->gcGet(), nX, nY, szPredicted, nLength ); } static int cmpRestrictionFragmentsBySize( const restrictionFragment** ppRes1, const restrictionFragment** ppRes2 ){ if ( (*ppRes1)->nSize_ < (*ppRes2)->nSize_ ) return( 1 ); else if ( (*ppRes1)->nSize_ == (*ppRes2)->nSize_ ) return( 0 ); else return( -1 ); } void guiDisplayDigest :: createProblemList( RWTPtrOrderedVector* pProblemList ) { // it doesn't matter whether we use aPredictedResFragsBySize_ or // aPredictedResFragsByConsPos_ since they both have the same // pointers, and we will sort the pointers differently later (below) // anyway for( int nPredicted = 0; nPredicted < pCurrentlyDisplayedDigest_->aPredictedResFragsBySize_.length(); ++nPredicted ) { restrictionFragment* pResFrag = pCurrentlyDisplayedDigest_->aPredictedResFragsBySize_[ nPredicted ]; if ( !pResFrag->pCorrespondingFrag_ ) { pProblemList->insert( pResFrag ); } else { if ( ABS( pResFrag->fPositionOnGel_ - pResFrag->pCorrespondingFrag_->fPositionOnGel_ ) > pCP->nRestrictionDigestToleranceInPositionUnits_ ) { pProblemList->insert( pResFrag ); } } } for( int nActual = 0; nActual < pCurrentlyDisplayedDigest_-> aActualRestrictionFragments_.length(); ++nActual ) { restrictionFragment* pActualFrag = pCurrentlyDisplayedDigest_->aActualRestrictionFragments_[ nActual ]; if ( !pActualFrag->pCorrespondingFrag_ ) { pProblemList->insert( pActualFrag ); } else { if ( ABS( pActualFrag->fPositionOnGel_ - pActualFrag->pCorrespondingFrag_->fPositionOnGel_ ) > pCP->nRestrictionDigestToleranceInPositionUnits_ ) { pProblemList->insert( pActualFrag ); } } } // sort the list by fragment size (larger fragments first) void* pArray = (void*) pProblemList->data(); size_t nNumberOfElementsInArray = pProblemList->length(); size_t nSizeOfAnElement = sizeof( restrictionFragment* ); qsort( pArray, nNumberOfElementsInArray, nSizeOfAnElement, ( ( int(*) ( const void*, const void*) ) cmpRestrictionFragmentsBySize ) ); // check that is really is sorted for( int nFrag = 1; nFrag < pProblemList->length(); ++nFrag ) { restrictionFragment* pFrag1 = (*pProblemList)[ nFrag - 1 ]; restrictionFragment* pFrag2 = (*pProblemList)[ nFrag ]; if ( pFrag1->nSize_ < pFrag2->nSize_ ) { // error in qsort RWCString soMessage = "qsort failed in guiDisplayDigest::createProblemList since (*pProblemList)[ "; soMessage += RWCString( (long) nFrag - 1 ); soMessage += " ]->nSize_ = "; soMessage += RWCString( (long) pFrag1->nSize_ ); soMessage += " < (*pProblemList)[ "; soMessage += RWCString( (long) nFrag ); soMessage += " ]->nSize_ = "; soMessage += RWCString( (long) pFrag2->nSize_ ); THROW_ERROR( soMessage ); } } } void guiDisplayDigest :: userPushedShowProblems() { new guiDigestProblemNavigator( this ); } // used by guiDigestProblemNavigator void guiDisplayDigest :: highlightFragment( restrictionFragment* pResFrag ) { clearPermVisibleLines(); clearTempVisibleLines(); // first possibly need to scroll window so this fragment is in view if ( pResFrag->fPositionOnGel_ < nGetGelPositionAtTopOfGelWindow() || nGetGelPositionAtBottomOfGelWindow() < pResFrag->fPositionOnGel_ ) { scrollGel( pResFrag->fPositionOnGel_ ); } // now move pointer. if ( pResFrag->cActualOrPredictedFragment_ == restrictionFragment::ACTUAL_FRAGMENT ) pPermMarkedActualRestrictionFragment_ = pResFrag; else pPermMarkedPredictedRestrictionFragment_ = pResFrag; drawVisibleLine( pResFrag->cActualOrPredictedFragment_, true ); if ( pResFrag->cActualOrPredictedFragment_ == restrictionFragment::PREDICTED_FRAGMENT ) highlightTextWindowLineForPredictedFragment( pResFrag ); else // unhighlight whatever was highlighted before XmListDeselectAllItems( widTextList_ ); } void guiDisplayDigest :: zoomInForNavigate() { fPixelsPerGelUnit_ *= pCP->dRestrictionDigestZoomFactorForNavigate_; adjustScrollBarWhenZoom(); displayGelWindow(); } void guiDisplayDigest :: scrollGel( const float fPositionOnGel ) { // put this position in the center of the gel float fGelUnitsDisplayedAtOnce = nGetGelWindowPixelHeight() / fPixelsPerGelUnit_; int nNewGelPositionAtTopOfGelWindow = fPositionOnGel - fGelUnitsDisplayedAtOnce / 2; if ( nNewGelPositionAtTopOfGelWindow < nGetMinGelPosition() ) nNewGelPositionAtTopOfGelWindow = nGetMinGelPosition(); // I'm going to allow scrolling to a too great position--we might be so // far zoomed out that the furthest visible position is beyond the // maximum. nGelPositionAtTopOfGelWindow_ = nNewGelPositionAtTopOfGelWindow; displayGelWindow(); } const int nExtraNumberOfPixelsBeyondLastFragment = 20; int guiDisplayDigest :: nGetMaxGelPosition() { return( pCurrentlyDisplayedDigest_->nMaxGelPosition_ + nExtraNumberOfPixelsBeyondLastFragment / fPixelsPerGelUnit_ ); } void guiDisplayDigest :: setMinGelPosition() { nMinGelPosition_ = ConsEd::fGetPositionOnGelFromRestrictionFragmentSize( pCP->nRestrictionDigestDoNoShowAreaOfFragmentsOverThisSize_ ); } void guiDisplayDigest :: highlightContigMapForFragment( restrictionFragment* pResFrag ) { int nStartPos; int nEndPos; ConsEd::pGetAssembly()->findRestrictionFragmentInContigMap( pResFrag, nStartPos, nEndPos ); // XmTextSetHighlight's end position is the 0-based position of // the first character that is *not* highlighted. Hence: ++nEndPos; XtVaSetValues( widContigMap_, XmNvalue, ConsEd::pGetAssembly()->soContigMap_.data(), NULL ); XmTextFieldSetHighlight( widContigMap_, 0, ConsEd::pGetAssembly()->soContigMap_.length(), XmHIGHLIGHT_NORMAL ); if ( nStartPos == -1 ) { return; } XmTextFieldSetHighlight( widContigMap_, nStartPos, nEndPos, XmHIGHLIGHT_SELECTED ); } void guiDisplayDigest :: showTextOutput() { char szTitle[100]; sprintf( szTitle, "Restriction Digest for %s", pCurrentlyDisplayedDigest_->soEnzymeName_.data() ); TextBox* pTB = new TextBox( szTitle, 30 ); // number of rows pTB->append( "--------- ----------------------\n" ); pTB->append( " Real In Silico \n" ); pTB->append( "Frag Size Size Position \n" ); pTB->append( "--------- ----- --------------\n" ); int nPredictedFrag = 0; int nActualFrag = 0; const int nJustPrintActual = 1; const int nJustPrintPredicted = 2; const int nPrintBoth = 3; while( true ) { if ( nPredictedFrag >= pCurrentlyDisplayedDigest_->aPredictedResFragsBySize_.length() && nActualFrag >= pCurrentlyDisplayedDigest_->aActualRestrictionFragments_.length() ) break; restrictionFragment* pPredictedFrag = NULL; if ( nPredictedFrag < pCurrentlyDisplayedDigest_->aPredictedResFragsBySize_.length() ) { pPredictedFrag = pCurrentlyDisplayedDigest_->aPredictedResFragsBySize_[ nPredictedFrag ]; } restrictionFragment* pActualFrag = NULL; if ( nActualFrag < pCurrentlyDisplayedDigest_->aActualRestrictionFragments_.length() ) { pActualFrag = pCurrentlyDisplayedDigest_->aActualRestrictionFragments_[ nActualFrag ]; } int nWhichToPrint = 0; if ( !pPredictedFrag ) // case in which there are no more predicted bands nWhichToPrint = nJustPrintActual; else if ( !pActualFrag ) // case in which there are no more actual bands nWhichToPrint = nJustPrintPredicted; else { // case in which there are both actual bands // cases // 1) they correspond to each other // print them on one line // 2) they don't correspond to each other // print the one with the least position and advance it. if ( pPredictedFrag->pCorrespondingFrag_ && pPredictedFrag->pCorrespondingFrag_ == pActualFrag ) { nWhichToPrint = nPrintBoth; } else { if ( pPredictedFrag->fPositionOnGel_ < pActualFrag->fPositionOnGel_ ) { // just print the predicted fragment // this better not have a corresponding actual fragment assert( !pPredictedFrag->pCorrespondingFrag_ ); nWhichToPrint = nJustPrintPredicted; } else { // just print the actual fragment // this better not have a corresponding predicted fragment assert( !pActualFrag->pCorrespondingFrag_ ); nWhichToPrint = nJustPrintActual; } } } // if ( !pPredictedFrag ) else if ... else if (nWhichToPrint == nPrintBoth ) { RWCString soPredictedDescription; pPredictedFrag->getDescriptionLine( soPredictedDescription ); pTB->appendWithArgs( "%8d %8s\n", pActualFrag->nSize_, soPredictedDescription.data() ); ++nPredictedFrag; ++nActualFrag; } else if ( nWhichToPrint == nJustPrintPredicted ) { RWCString soPredictedDescription; pPredictedFrag->getDescriptionLine( soPredictedDescription ); pTB->appendWithArgs( " %s\n", soPredictedDescription.data() ); ++nPredictedFrag; } else if ( nWhichToPrint == nJustPrintActual ) { pTB->appendWithArgs( "%8d\n", pActualFrag->nSize_ ); ++nActualFrag; } // if (nWhichToPrint == nPrintBoth ) else if ... else else assert( false ); } // while( true ) pTB->append( "\n\n\n\n" ); pTB->append( "-------------------------------\n" ); pTB->append( "In Silico Sorted By Position \n" ); pTB->append( "Frag Size Frag Position\n" ); pTB->append( "--------- -------------------\n" ); RWCString soStringToDisplay( (size_t) 200 ); for( int nPredictedFragment = 0; nPredictedFragment < pCurrentlyDisplayedDigest_->aPredictedResFragsByConsPos_.length(); ++nPredictedFragment ) { restrictionFragment* pResFrag = pCurrentlyDisplayedDigest_->aPredictedResFragsByConsPos_[ nPredictedFragment ]; pResFrag->getDescriptionLine( soStringToDisplay ); pTB->append( soStringToDisplay ); pTB->append( "\n" ); } // for debugging, show the vector partial fragments pTB->append( "\n\n\n" ); pTB->append( "partial vector fragments\n" ); pTB->append( "(presumably joined above to partial insert fragments)\n" ); for( int nFrag = 0; nFrag < pCurrentlyDisplayedDigest_->aPredictedVectorRestrictionFragmentsEndingAtVectorInsertJunction_.length(); ++nFrag ) { restrictionFragment* pVectorFrag = pCurrentlyDisplayedDigest_->aPredictedVectorRestrictionFragmentsEndingAtVectorInsertJunction_[ nFrag ]; pTB->appendWithArgs( "size: %d\n", pVectorFrag->nSize_ ); } pTB->makeVisible(); } void guiDisplayDigest :: sortChanged() { updateTextDisplay(); } arrayOfRestrictionFragments* guiDisplayDigest :: pGetPredictedFragmentsArray() { Boolean bSortByPosition = XmToggleButtonGetState( widSortByPosition_ ); if ( bSortByPosition ) return( &( pCurrentlyDisplayedDigest_->aPredictedResFragsByConsPos_ ) ); else return( &( pCurrentlyDisplayedDigest_->aPredictedResFragsBySize_ ) ); } void guiDisplayDigest :: showDocumentationForRestrictionDigest() { TextBox* pTB = new TextBox( "Documentation", 30, // rows visible pCP->soGetDocumentation() ); pTB->makeVisible(); int nFoundPos = pCP->soGetDocumentation().index( "RESTRICTION DIGEST" ); if ( nFoundPos == RW_NPOS ) { popupErrorMessage( "Internal program error finding RESTRICTION DIGEST in documentation." ); return; } XmTextSetHighlight( pTB->widScrolledText_, nFoundPos, nFoundPos + strlen( "RESTRICTION DIGEST" ), XmHIGHLIGHT_SELECTED ); pTB->scrollWindowToLocation( nFoundPos ); } void guiDisplayDigest :: userPushedComplVector() { bFlipVectorFromTheDefault_ = !bFlipVectorFromTheDefault_; RWCString soLabel; if ( bFlipVectorFromTheDefault_ ) soLabel = "uncompl vec"; else soLabel = "compl vector"; XmString xms = XmStringCreateSimple( soLabel.data() ); XtVaSetValues( widComplVector_, XmNlabelString, xms, NULL ); // now do the real flipping, and do this for each enzyme. for( int nEnzyme = 0; nEnzyme < aDigests_.length(); ++nEnzyme ) { digestForOneEnzyme* pDigest = aDigests_[ nEnzyme ]; pDigest->processingAfterFindingAllPartialFragments( bFlipVectorFromTheDefault_ ); } // redisplay everything. (This might not work if the changed // fragments cause some change in the resolution.) updateTextDisplay(); displayGelWindow(); } void guiDisplayDigest :: tellAssemblyView() { if ( ConsEd::pGetConsEd()->pAssemblyView_ ) { ConsEd::pGetConsEd()->pAssemblyView_->drawEverything( true, // calculate positions true ); // erase first } } int guiDisplayDigest :: nGetPixelYFromRestrictionFragmentSize( const int nFragmentSize ) { return( nGetPixelYFromGelPosition( ConsEd::fGetPositionOnGelFromRestrictionFragmentSize( nFragmentSize ) ) ); } void guiDisplayDigest :: raiseWindow() { XtMapWidget( widPopupShell_ ); XRaiseWindow( XtDisplay( widPopupShell_ ), XtWindow( widPopupShell_ ) ); }