/***************************************************************************** # 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 #include #include "guitedwin.h" #include "guiteditor.h" #include "tedwin.h" #include "teditor.h" #include "guihighlight.h" #include "filename.h" #include "readsense_bitmaps.h" #include "xsynchronize.h" #include "hp_exception_kludge.h" #include "motifutils.h" #include "colorDefaults.h" #include "consed.h" #include "consedParameters.h" #include "mbtValOrderedVectorOfInt.h" // specific to traces window within GuiTedWin //const int nInitialTracesWindowPixelWidth = 600; //const int nInitialTracesWindowPixelHeight = 50; const int nAmountToScrollWhenArrowIsPushed = 10; // class static variable definitions bool GuiTedWin :: bColorsAllocated_ = FALSE; GuiColorText* GuiTedWin :: pGuiColorTextA_ = NULL; GuiColorText* GuiTedWin :: pGuiColorTextC_ = NULL; GuiColorText* GuiTedWin :: pGuiColorTextG_ = NULL; GuiColorText* GuiTedWin :: pGuiColorTextT_ = NULL; GuiColorText* GuiTedWin :: pGuiColorTextN_ = NULL; GuiColorText* GuiTedWin :: pGuiColorTextPad_ = NULL; GuiColorText* GuiTedWin :: pGuiColorTextHighlightedA_ = NULL; GuiColorText* GuiTedWin :: pGuiColorTextHighlightedC_ = NULL; GuiColorText* GuiTedWin :: pGuiColorTextHighlightedG_ = NULL; GuiColorText* GuiTedWin :: pGuiColorTextHighlightedT_ = NULL; GuiColorText* GuiTedWin :: pGuiColorTextHighlightedN_ = NULL; GuiColorText* GuiTedWin :: pGuiColorTextHighlightedX_ = NULL; GuiColorText* GuiTedWin :: pGuiColorTextHighlightedPad_ = NULL; GuiColorText* GuiTedWin :: pGuiColorTextHighlightBackground_ = NULL; GuiColorText* GuiTedWin :: pGuiColorTextForScale_ = NULL; GuiColorText* GuiTedWin :: pGuiColorTextForConsCursor_ = NULL; GuiColorText* GuiTedWin :: pGuiColorTextForScaleNumbers_ = NULL; bool GuiTedWin :: bTracesGCSetToDashed_ = false; bool GuiTedWin::bPixmapsCreated_ = false; Pixmap GuiTedWin::pixSenseForward_; Pixmap GuiTedWin::pixSenseReverse_; // // forward declarations for callbacks // CbInfoButton cbRemoveTedWin; CbInfoButton cbTedWinUndo; void cbScrollTogetherRadioBox( Widget wid, GuiTedWin* pGuiTedWin, XmToggleButtonCallbackStruct *pXmToggleButtonCallbackStruct ) { TRY_CATCH_WRAPPER( pGuiTedWin->pTeditorGet()->changeAllTedWinsScrollTogether( pXmToggleButtonCallbackStruct->set, pGuiTedWin ); ); } void GuiTedWin :: changeGuiTedWinsScrollTogetherButtons( const bool bScrollTogether ){ bool b = bScrollTogether; XtVaSetValues( widYes_, XmNset, b, NULL ); XtVaSetValues( widNo_, XmNset, !b, NULL ); } GuiTedWin :: GuiTedWin(TedWin* pTedWin, const int nPositionOnTeditor, const bool bAddToScrollingWindow, const bool bShowABICalledBasesLine, const bool bShowPhredCalledBasesLine, const bool bShowConsensusLine, const bool bShowEditableReadLine, const bool bShowConsensusPositionsLine, const bool bShowScrollbar ) : dPixelsPerPoint_(dPixelsPerPointInit), nLeftEdgePointPosition_( 0 ), pTedWin_(pTedWin), aBasePixelPositions_( 100 ), // set default size of array bGuiTedWinCtorFinished_( false ), bShowABICalledBases_( bShowABICalledBasesLine ), bShowPhredCalledBasesLine_( bShowPhredCalledBasesLine ), bShowConsensusLine_( bShowConsensusLine ), bShowEditableReadLine_( bShowEditableReadLine ), bShowConsensusPositionsLine_( bShowConsensusPositionsLine ), bShowScrollbar_( bShowScrollbar ), bMouseIsOnWindow_( true ), bAutomaticScrollingInProgress_( false ), widShowAllTracesConsensusScale_( 0 ) { Arg aArg[30]; int nArgs; // if this is the first time through the ctor, allocate the colors if (! bColorsAllocated_ ) allocateColors(); char szFragmentName[200]; strcpy( szFragmentName, pTedWin_->pLocFragGet()->soGetFragmentName() ); // the highest level widget created by a GuiTedWin is a frame containing // the widget, which is available publicly via the widGet() member // function // all attachments, positioning of this widget are done in addGuiTedWin() if ( bAddToScrollingWindow ) { widFrame_ = XtVaCreateManagedWidget( "frame", xmFrameWidgetClass, pGuiTeditorGet()->widRowCol_, XmNancestorSensitive, True, XmNshadowType, XmSHADOW_IN, XmNleftAttachment, XmATTACH_FORM, XmNrightAttachment, XmATTACH_FORM, XmNtopAttachment, XmATTACH_FORM, XmNbottomAttachment, XmATTACH_FORM, // XmNwidth, dimWidth, NULL ); widForm_ = XtVaCreateManagedWidget( "formInFrame", xmFormWidgetClass, widFrame_, XmNancestorSensitive, True, XmNshadowThickness, 0, XmNborderWidth, 0, NULL ); Widget widLastAddedWidget; ////////////////////////////////////////////////////////////////////// // // create the scale drawing area widget // ////////////////////////////////////////////////////////////////////// widScale_ = XtVaCreateManagedWidget( "scaleDrawingArea", xmDrawingAreaWidgetClass, widForm_, XmNtopAttachment, XmATTACH_FORM, XmNleftAttachment, XmATTACH_FORM, XmNrightAttachment, XmATTACH_FORM, XmNtopOffset, 0, XmNbottomOffset, 0, XmNleftOffset, 0, XmNrightOffset, 0, XmNshadowThickness, 0, XmNborderWidth, 0, XtNheight, nGetScaleWidgetHeight(), NULL ); widLastAddedWidget = widScale_; XtAddCallback( widScale_, XmNexposeCallback, (XtCallbackProc ) guiTedWinScaleExposureXtCb, this ); // all the drawing areas of the GuiTedWin will pass KeyPress events // to this handler. The user is not required to click on the // fragment base window specifically to put input focus there. XtAddEventHandler( widScale_, KeyPressMask, False, (XtEventHandler) guiTedWinKeyPressXtEventHandler, this ); ////////////////////////////////////////////////////////////////////// // // create the consensus base drawing area widget // ////////////////////////////////////////////////////////////////////// if ( bShowConsensusLine_ ) { widConsensus_ = XtVaCreateManagedWidget( "consensusDrawingArea", xmDrawingAreaWidgetClass, widForm_, XmNleftAttachment, XmATTACH_FORM, XmNrightAttachment, XmATTACH_FORM, XmNtopAttachment, XmATTACH_WIDGET, XmNtopWidget, widLastAddedWidget, XmNtopOffset, 0, XmNbottomOffset, 0, XmNleftOffset, 0, XmNrightOffset, 0, XmNshadowThickness, 0, XmNborderWidth, 0, XtNheight, nGetTextWindowHeight( eConsensusBase ), NULL ); widLastAddedWidget = widConsensus_; XtAddCallback( widConsensus_, XmNexposeCallback, (XtCallbackProc ) guiTedWinConsensusExposureXtCb, this ); // all the drawing areas of the GuiTedWin will pass KeyPress events // to this handler. The user is not required to click on the // fragment base window specifically to put input focus there. XtAddEventHandler( widConsensus_, KeyPressMask, False, (XtEventHandler) guiTedWinKeyPressXtEventHandler, this ); } ////////////////////////////////////////////////////////////////////// // // create the fragment base drawing area widget // ////////////////////////////////////////////////////////////////////// if ( bShowEditableReadLine_ ) { widFragmentBases_ = XtVaCreateManagedWidget( "editableBasesDrawingArea", xmDrawingAreaWidgetClass, widForm_, XmNtopAttachment, XmATTACH_WIDGET, XmNtopWidget, widLastAddedWidget, XmNleftAttachment, XmATTACH_FORM, XmNrightAttachment, XmATTACH_FORM, XmNtopOffset, 0, XmNbottomOffset, 0, XmNleftOffset, 0, XmNrightOffset, 0, XmNshadowThickness, 0, XmNborderWidth, 0, XtNheight, nGetTextWindowHeight( eFragmentBase ), NULL ); widLastAddedWidget = widFragmentBases_; XtAddCallback( widFragmentBases_, XmNexposeCallback, (XtCallbackProc ) guiTedWinSameAsContigWinExposureXtCb, this ); // This resize callback has been moved to the traces since it is the // trace window that is used to find the window pixel width in // nGetTracesWindowPixelWidth and this is used to calculate the // range of consensus positions on the screen. For some reason, // the different windows do not all have their sizes changed at once--the // resize callback for the widFragmentBases_ window runs before the // traces window has resized. Thus this causes the bases to not be // displayed when you expand the window. // XtAddCallback(widFragmentBases_, // XmNresizeCallback, // (XtCallbackProc ) guiTedWinResizeXtCb, // this); XtAddEventHandler( widFragmentBases_, ButtonPressMask, False, (XtEventHandler) guiTedWinFragButtonPressXtEventHandler, this ); XtAddEventHandler( widFragmentBases_, Button2MotionMask, False, (XtEventHandler) guiTedWinButtonMotionXtEventHandler, this ); XtAddEventHandler( widFragmentBases_, ButtonReleaseMask, False, (XtEventHandler) guiTedWinButtonReleaseXtEventHandler, this ); XtAddEventHandler( widFragmentBases_, LeaveWindowMask, False, (XtEventHandler) guiTedWinLeaveNotifyXtEventHandler, this ); // all the drawing areas of the GuiTedWin will pass KeyPress events // to this handler. The user is not required to click on the // fragment base window specifically to put input focus there. XtAddEventHandler( widFragmentBases_, KeyPressMask, False, (XtEventHandler) guiTedWinKeyPressXtEventHandler, this ); } // if ( bShowEditableReadLine_ ) ////////////////////////////////////////////////////////////////////// // // create the called bases drawing area widget // ////////////////////////////////////////////////////////////////////// if ( bShowPhredCalledBasesLine_ ) { widPhredCalledBases_ = XtVaCreateManagedWidget( "phredCalledBasesDrawingArea", xmDrawingAreaWidgetClass, widForm_, XmNtopOffset, 0, XmNbottomOffset, 0, XmNleftOffset, 0, XmNrightOffset, 0, XmNshadowThickness, 0, XmNborderWidth, 0, XtNheight, nGetTextWindowHeight( ePhredCalledBase ), XmNleftAttachment, XmATTACH_FORM, XmNrightAttachment, XmATTACH_FORM, XmNtopAttachment, XmATTACH_WIDGET, XmNtopWidget, widLastAddedWidget, NULL ); widLastAddedWidget = widPhredCalledBases_; // all the drawing areas of the GuiTedWin will pass KeyPress events // to this handler. The user is not required to click on the // fragment base window specifically to put input focus there. XtAddEventHandler( widPhredCalledBases_, KeyPressMask, False, (XtEventHandler) guiTedWinKeyPressXtEventHandler, this ); XtAddCallback( widPhredCalledBases_, XmNexposeCallback, (XtCallbackProc ) guiTedWinPhredCalledBasesXtCb, this ); } if ( bShowABICalledBases_ ) { widABICalledBases_ = XtVaCreateManagedWidget( "ABICalledBasesDrawingArea", xmDrawingAreaWidgetClass, widForm_, XmNtopOffset, 0, XmNbottomOffset, 0, XmNleftOffset, 0, XmNrightOffset, 0, XmNshadowThickness, 0, XmNborderWidth, 0, XtNheight, nGetTextWindowHeight( eABICalledBase ), XmNleftAttachment, XmATTACH_FORM, XmNrightAttachment, XmATTACH_FORM, XmNtopAttachment, XmATTACH_WIDGET, XmNtopWidget, widLastAddedWidget, NULL ); widLastAddedWidget = widABICalledBases_; // all the drawing areas of the GuiTedWin will pass KeyPress events // to this handler. The user is not required to click on the // fragment base window specifically to put input focus there. XtAddEventHandler( widABICalledBases_, KeyPressMask, False, (XtEventHandler) guiTedWinKeyPressXtEventHandler, this ); XtAddCallback( widABICalledBases_, XmNexposeCallback, (XtCallbackProc ) guiTedWinABICalledBasesXtCb, this ); } ////////////////////////////////////////////////////////////////////// // // create the traces drawing area widget // ////////////////////////////////////////////////////////////////////// widTraces_ = XtVaCreateManagedWidget("tracesDrawingArea", xmDrawingAreaWidgetClass, widForm_, XmNancestorSensitive, True, XmNtopOffset, 0, XmNbottomOffset, 0, XmNleftOffset, 0, XmNrightOffset, 0, XmNshadowThickness, 0, XmNborderWidth, 0, XmNtopAttachment, XmATTACH_WIDGET, XmNtopWidget, widLastAddedWidget, XmNbottomAttachment, XmATTACH_FORM, XmNleftAttachment, XmATTACH_FORM, XmNrightAttachment, XmATTACH_FORM, XtNheight, (Dimension) consedParameters::pGetConsedParameters()->nTracesWindowInitialPixelHeight_, XtNwidth, pGuiTeditorGet()->dimClipWindowWidth_, NULL ); XtAddCallback( widTraces_, XmNexposeCallback, (XtCallbackProc ) guiTedWinTracesExposureXtCb, this ); XtAddCallback(widTraces_, XmNresizeCallback, (XtCallbackProc ) guiTedWinResizeXtCb, this); // all the drawing areas of the GuiTedWin will pass KeyPress events // to this handler. The user is not required to click on the // fragment base window specifically to put input focus there. XtAddEventHandler( widTraces_, KeyPressMask, False, (XtEventHandler) guiTedWinKeyPressXtEventHandler, this ); // initialize the text field containing the trace file's name widSequenceName_ = XtVaCreateManagedWidget( "sequence_name", xmTextFieldWidgetClass, widForm_, XmNtraversalOn, False, XmNtopAttachment, XmATTACH_FORM, XmNleftAttachment, XmATTACH_FORM, XmNvalue, szFragmentName, XmNcolumns, (short) pTedWin_->pLocFragGet()->soGetFragmentName().length(), XmNeditable, False, XmNcursorPositionVisible, False, NULL ); widUndoButton_ = XtVaCreateManagedWidget( "Undo", xmPushButtonWidgetClass, widForm_, XmNtopAttachment, XmATTACH_WIDGET, XmNtopWidget, widSequenceName_, XmNborderWidth, 0, XmNmarginHeight, 0, XmNleftAttachment, XmATTACH_FORM, XmNsensitive, False, // initialize not sensitive NULL ); widReadSenseLabel_ = XtVaCreateManagedWidget( "readSensePixmapLabel", xmLabelWidgetClass, widForm_, XmNtopAttachment, XmATTACH_WIDGET, XmNtopWidget, widSequenceName_, XmNleftAttachment, XmATTACH_WIDGET, XmNleftWidget, widUndoButton_, XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET, XmNbottomWidget, widUndoButton_, XmNrightAttachment, XmATTACH_OPPOSITE_WIDGET, XmNrightWidget, widSequenceName_, XmNheight, forward_bitmap_height, XmNwidth, forward_bitmap_width, XmNborderWidth, 0, XmNmarginHeight, 0, XmNlabelType, XmPIXMAP, NULL ); XtAddCallback( widUndoButton_, XmNactivateCallback, (XtCallbackProc) cbTedWinUndo, this ); // static class member pixmaps get created first time through ctor if (! bPixmapsCreated_) createReadSensePixmaps(); // possibly dangerous kludge: // the user can set both the range and initial value of the mag sliders // by overriding the fallback values specified in guiapp.cpp // however, the GuiTedWin needs to know these values for the initial // expose callback. thus, we ask the already formed widgets what their // values are int nHorizScaleValue; if ( !bAddToScrollingWindow ) { nArgs = 0; XtSetArg(aArg[nArgs], XmNvalue, &nHorizScaleValue); nArgs++; XtGetValues(widHorizontalScale_, aArg, nArgs); } else nHorizScaleValue = 10; dPixelsPerPoint_ = nHorizScaleValue * dPixelsPerPointInit / (double) nHorizontalScaleInit; if ( !bAddToScrollingWindow ) { // do same for vert scale nArgs = 0; XtSetArg(aArg[nArgs], XmNvalue, &nVerticalScaleValue_ ); nArgs++; XtGetValues(widVerticalScale_, aArg, nArgs); } else nVerticalScaleValue_ = 100; XmProcessTraversal( widFragmentBases_, XmTRAVERSE_CURRENT ); bGuiTedWinCtorFinished_ = true; } // if ( bAddToScrollingWindow ) { else { // the highest level widget created by a GuiTedWin is a frame containing // the widget, which is available publicly via the widGet() member // function // all attachments, positioning of this widget are done in addGuiTedWin() widFrame_ = XtVaCreateManagedWidget("frame", xmFrameWidgetClass, pGuiTeditorGet()->widGuiTedWinFormGet(), XmNancestorSensitive, True, XmNshadowType, XmSHADOW_IN, XmNleftAttachment, XmATTACH_FORM, XmNrightAttachment, XmATTACH_FORM, XmNtopAttachment, XmATTACH_POSITION, XmNtopPosition, nPositionOnTeditor, XmNbottomAttachment, XmATTACH_POSITION, XmNbottomPosition, nPositionOnTeditor + 1, NULL ); nArgs = 0; XtSetArg(aArg[nArgs],XmNshadowThickness,0); nArgs++; XtSetArg(aArg[nArgs],XmNborderWidth,0); nArgs++; XtSetArg(aArg[nArgs],XmNancestorSensitive,True); nArgs++; widForm_ = XmCreateForm(widFrame_, "form", aArg, nArgs); XtManageChild(widForm_); // initialize the text field containing the trace file's name widSequenceName_ = XtVaCreateManagedWidget( "sequence_name", xmTextFieldWidgetClass, widForm_, XmNtraversalOn, False, XmNtopAttachment, XmATTACH_FORM, XmNleftAttachment, XmATTACH_POSITION, XmNleftPosition, 1, XmNvalue, szFragmentName, XmNeditable, False, XmNcursorPositionVisible, False, NULL ); // this label will later get a pixmap indicating read sense // (i.e. forward or reverse). set by setReadSenseForward/Reverse() widReadSenseLabel_ = XtVaCreateManagedWidget( "readSensePixmapLabel", xmLabelWidgetClass, widForm_, XmNtopAttachment, XmATTACH_WIDGET, XmNtopWidget, widSequenceName_, XmNleftAttachment, XmATTACH_FORM, XmNheight, forward_bitmap_height, XmNwidth, forward_bitmap_width, XmNlabelType, XmPIXMAP, NULL ); // label for horizontal scale XmString xmsHorizScaleLabel = XmStringCreateSimple("H"); nArgs = 0; XtSetArg(aArg[nArgs], XmNlabelString, xmsHorizScaleLabel); nArgs++; XtSetArg(aArg[nArgs], XmNtopAttachment, XmATTACH_WIDGET); nArgs++; XtSetArg(aArg[nArgs], XmNtopWidget, widReadSenseLabel_); nArgs++; XtSetArg(aArg[nArgs], XmNleftAttachment, XmATTACH_POSITION); nArgs++; XtSetArg(aArg[nArgs], XmNleftPosition, 1); nArgs++; Widget widHorizScaleLabel = XmCreateLabel(widForm_, "label", aArg, nArgs); XtManageChild(widHorizScaleLabel); XmStringFree(xmsHorizScaleLabel); // horizontal scale nArgs = 0; XtSetArg(aArg[nArgs], XmNtraversalOn, False); nArgs++; XtSetArg(aArg[nArgs], XmNorientation, XmHORIZONTAL); nArgs++; XtSetArg(aArg[nArgs], XmNleftAttachment, XmATTACH_WIDGET); nArgs++; XtSetArg(aArg[nArgs], XmNleftWidget, widHorizScaleLabel); nArgs++; XtSetArg(aArg[nArgs], XmNrightAttachment, XmATTACH_OPPOSITE_WIDGET); nArgs++; XtSetArg(aArg[nArgs], XmNrightWidget, widSequenceName_ ); nArgs++; XtSetArg(aArg[nArgs], XmNtopAttachment, XmATTACH_WIDGET); nArgs++; XtSetArg(aArg[nArgs], XmNtopWidget, widReadSenseLabel_ ); nArgs++; XtSetArg(aArg[nArgs], XmNshowValue, False); nArgs++; widHorizontalScale_ = XmCreateScale(widForm_, "horizontalScale", aArg, nArgs); XtManageChild(widHorizontalScale_); XtAddCallback(widHorizontalScale_, XmNvalueChangedCallback, (XtCallbackProc ) guiTedWinHorizontalMagXtCb, this); XtAddCallback(widHorizontalScale_, XmNdragCallback, (XtCallbackProc ) guiTedWinHorizontalMagXtCb, this); // label for vertical scale XmString xmsVertScaleLabel = XmStringCreateSimple("V"); nArgs = 0; XtSetArg(aArg[nArgs], XmNlabelString, xmsVertScaleLabel); nArgs++; XtSetArg(aArg[nArgs], XmNtopAttachment, XmATTACH_WIDGET); nArgs++; XtSetArg(aArg[nArgs], XmNtopWidget, widHorizontalScale_); nArgs++; XtSetArg(aArg[nArgs], XmNleftAttachment, XmATTACH_POSITION); nArgs++; XtSetArg(aArg[nArgs], XmNleftPosition, 1); nArgs++; Widget widVertScaleLabel = XmCreateLabel(widForm_, "label", aArg, nArgs); XtManageChild(widVertScaleLabel); XmStringFree(xmsVertScaleLabel); // vertical scale nArgs = 0; XtSetArg(aArg[nArgs], XmNtraversalOn, False); nArgs++; XtSetArg(aArg[nArgs], XmNorientation, XmHORIZONTAL); nArgs++; XtSetArg(aArg[nArgs], XmNtopAttachment, XmATTACH_WIDGET); nArgs++; XtSetArg(aArg[nArgs], XmNtopWidget, widHorizontalScale_); nArgs++; XtSetArg(aArg[nArgs], XmNrightAttachment, XmATTACH_OPPOSITE_WIDGET); nArgs++; XtSetArg(aArg[nArgs], XmNrightWidget, widSequenceName_); nArgs++; XtSetArg(aArg[nArgs], XmNleftAttachment, XmATTACH_WIDGET); nArgs++; XtSetArg(aArg[nArgs], XmNleftWidget, widVertScaleLabel); nArgs++; XtSetArg(aArg[nArgs], XmNshowValue, False); nArgs++; XtSetArg(aArg[nArgs], XmNminimum, 1); nArgs++; XtSetArg(aArg[nArgs], XmNmaximum, 200 ); nArgs++; XtSetArg(aArg[nArgs], XmNvalue, 100 ); nArgs++; widVerticalScale_ = XmCreateScale(widForm_, "verticalScale", aArg, nArgs); XtManageChild(widVerticalScale_); XtAddCallback(widVerticalScale_, XmNvalueChangedCallback, (XtCallbackProc ) guiTedWinVerticalMagXtCb, this); XtAddCallback(widVerticalScale_, XmNdragCallback, (XtCallbackProc ) guiTedWinVerticalMagXtCb, this); // make labels widConsensusScaleLabel_ = widMakeLabel( eConsensusScale ); widReadScaleLabel_ = widMakeLabel( eReadScale ); widConsensusLabel_ = widMakeLabel( eConsensusBase ); widFragmentBasesLabel_ = widMakeLabel( eFragmentBase ); widPhredCalledBasesLabel_ = widMakeLabel( ePhredCalledBase ); if ( bShowABICalledBases_ ) widABICalledBasesLabel_ = widMakeLabel( eABICalledBase ); // scrollbar widScrollBar_ = XtVaCreateManagedWidget("scrollbar", xmScrollBarWidgetClass, widForm_, XmNorientation, XmHORIZONTAL, XmNleftAttachment, XmATTACH_WIDGET, XmNleftWidget, widSequenceName_, XmNleftOffset, nGetMaxWidthOfLabels() + nOffsetFromLabels, XmNrightAttachment, XmATTACH_FORM, XmNbottomAttachment, XmATTACH_FORM, XmNincrement, nAmountToScrollWhenArrowIsPushed, NULL ); XtAddCallback(widScrollBar_, XmNvalueChangedCallback, (XtCallbackProc ) guiTedWinScrollBarXtCb, this); XtAddCallback(widScrollBar_, XmNdragCallback, (XtCallbackProc ) guiTedWinScrollBarXtCb, this); Widget widFrameOnForm = XtVaCreateManagedWidget( "frameOnForm", xmFrameWidgetClass, widForm_, XmNancestorSensitive, True, XmNtopAttachment, XmATTACH_FORM, XmNleftAttachment, XmATTACH_WIDGET, XmNleftWidget, widSequenceName_, XmNleftOffset, nGetMaxWidthOfLabels() + nOffsetFromLabels, XmNrightAttachment, XmATTACH_FORM, XmNbottomAttachment, XmATTACH_WIDGET, XmNbottomWidget, widScrollBar_, XmNshadowType, XmSHADOW_IN, NULL ); Widget widFormInFrame = XtVaCreateManagedWidget( "formInFrame", xmFormWidgetClass, widFrameOnForm, XmNancestorSensitive, True, NULL ); ////////////////////////////////////////////////////////////////////// // // create the scale drawing area widget // ////////////////////////////////////////////////////////////////////// widScale_ = XtVaCreateManagedWidget( "scaleDrawingArea", xmDrawingAreaWidgetClass, widFormInFrame, XmNtopAttachment, XmATTACH_FORM, XmNleftAttachment, XmATTACH_FORM, XmNrightAttachment, XmATTACH_FORM, XmNtopOffset, 0, XmNbottomOffset, 0, XmNleftOffset, 0, XmNrightOffset, 0, XmNshadowThickness, 0, XmNborderWidth, 0, XtNheight, nGetScaleWidgetHeight(), NULL ); XtAddCallback( widScale_, XmNexposeCallback, (XtCallbackProc ) guiTedWinScaleExposureXtCb, this ); // all the drawing areas of the GuiTedWin will pass KeyPress events // to this handler. The user is not required to click on the // fragment base window specifically to put input focus there. XtAddEventHandler( widScale_, KeyPressMask, False, (XtEventHandler) guiTedWinKeyPressXtEventHandler, this ); ////////////////////////////////////////////////////////////////////// // // create the consensus base drawing area widget // ////////////////////////////////////////////////////////////////////// widConsensus_ = XtVaCreateManagedWidget( "consensusDrawingArea", xmDrawingAreaWidgetClass, widFormInFrame, XmNleftAttachment, XmATTACH_FORM, XmNrightAttachment, XmATTACH_FORM, XmNtopAttachment, XmATTACH_WIDGET, XmNtopWidget, widScale_, XmNtopOffset, 0, XmNbottomOffset, 0, XmNleftOffset, 0, XmNrightOffset, 0, XmNshadowThickness, 0, XmNborderWidth, 0, XtNheight, nGetTextWindowHeight( eConsensusBase ), NULL ); XtAddCallback( widConsensus_, XmNexposeCallback, (XtCallbackProc ) guiTedWinConsensusExposureXtCb, this ); // all the drawing areas of the GuiTedWin will pass KeyPress events // to this handler. The user is not required to click on the // fragment base window specifically to put input focus there. XtAddEventHandler( widConsensus_, KeyPressMask, False, (XtEventHandler) guiTedWinKeyPressXtEventHandler, this ); // user can set cursor on consensus by MB1 click in this window // XtAddEventHandler( widConsensus_, // ButtonPressMask, // False, // (XtEventHandler) guiTedWinConsButtonPressXtEventHandler, // this ); ////////////////////////////////////////////////////////////////////// // // create the fragment base drawing area widget // ////////////////////////////////////////////////////////////////////// widFragmentBases_ = XtVaCreateManagedWidget( "editableBasesDrawingArea", xmDrawingAreaWidgetClass, widFormInFrame, XmNtopAttachment, XmATTACH_WIDGET, XmNtopWidget, widConsensus_, XmNleftAttachment, XmATTACH_FORM, XmNrightAttachment, XmATTACH_FORM, XmNtopOffset, 0, XmNbottomOffset, 0, XmNleftOffset, 0, XmNrightOffset, 0, XmNshadowThickness, 0, XmNborderWidth, 0, XtNheight, nGetTextWindowHeight( eFragmentBase ), NULL ); XtAddCallback( widFragmentBases_, XmNexposeCallback, (XtCallbackProc ) guiTedWinSameAsContigWinExposureXtCb, this ); // This resize callback has been moved to the traces since it is the // trace window that is used to find the window pixel width in // nGetTracesWindowPixelWidth and this is used to calculate the // range of consensus positions on the screen. For some reason, // the different windows do not all have their sizes changed at once--the // resize callback for the widFragmentBases_ window runs before the // traces window has resized. Thus this causes the bases to not be // displayed when you expand the window. // XtAddCallback(widFragmentBases_, // XmNresizeCallback, // (XtCallbackProc ) guiTedWinResizeXtCb, // this); XtAddEventHandler( widFragmentBases_, ButtonPressMask, False, (XtEventHandler) guiTedWinFragButtonPressXtEventHandler, this ); XtAddEventHandler( widFragmentBases_, Button2MotionMask, False, (XtEventHandler) guiTedWinButtonMotionXtEventHandler, this ); XtAddEventHandler( widFragmentBases_, ButtonReleaseMask, False, (XtEventHandler) guiTedWinButtonReleaseXtEventHandler, this ); XtAddEventHandler( widFragmentBases_, LeaveWindowMask, False, (XtEventHandler) guiTedWinLeaveNotifyXtEventHandler, this ); // all the drawing areas of the GuiTedWin will pass KeyPress events // to this handler. The user is not required to click on the // fragment base window specifically to put input focus there. XtAddEventHandler( widFragmentBases_, KeyPressMask, False, (XtEventHandler) guiTedWinKeyPressXtEventHandler, this ); ////////////////////////////////////////////////////////////////////// // // create the called bases drawing area widget // ////////////////////////////////////////////////////////////////////// widPhredCalledBases_ = XtVaCreateManagedWidget( "phredCalledBasesDrawingArea", xmDrawingAreaWidgetClass, widFormInFrame, XmNtopOffset, 0, XmNbottomOffset, 0, XmNleftOffset, 0, XmNrightOffset, 0, XmNshadowThickness, 0, XmNborderWidth, 0, XtNheight, nGetTextWindowHeight( ePhredCalledBase ), XmNleftAttachment, XmATTACH_FORM, XmNrightAttachment, XmATTACH_FORM, XmNtopAttachment, XmATTACH_WIDGET, XmNtopWidget, widFragmentBases_, NULL ); Widget widLastAddedWidget = widPhredCalledBases_; // all the drawing areas of the GuiTedWin will pass KeyPress events // to this handler. The user is not required to click on the // fragment base window specifically to put input focus there. XtAddEventHandler( widPhredCalledBases_, KeyPressMask, False, (XtEventHandler) guiTedWinKeyPressXtEventHandler, this ); XtAddCallback( widPhredCalledBases_, XmNexposeCallback, (XtCallbackProc ) guiTedWinPhredCalledBasesXtCb, this ); if ( bShowABICalledBases_ ) { widABICalledBases_ = XtVaCreateManagedWidget( "ABICalledBasesDrawingArea", xmDrawingAreaWidgetClass, widFormInFrame, XmNtopOffset, 0, XmNbottomOffset, 0, XmNleftOffset, 0, XmNrightOffset, 0, XmNshadowThickness, 0, XmNborderWidth, 0, XtNheight, nGetTextWindowHeight( eABICalledBase ), XmNleftAttachment, XmATTACH_FORM, XmNrightAttachment, XmATTACH_FORM, XmNtopAttachment, XmATTACH_WIDGET, XmNtopWidget, widPhredCalledBases_, NULL ); widLastAddedWidget = widABICalledBases_; // all the drawing areas of the GuiTedWin will pass KeyPress events // to this handler. The user is not required to click on the // fragment base window specifically to put input focus there. XtAddEventHandler( widABICalledBases_, KeyPressMask, False, (XtEventHandler) guiTedWinKeyPressXtEventHandler, this ); XtAddCallback( widABICalledBases_, XmNexposeCallback, (XtCallbackProc ) guiTedWinABICalledBasesXtCb, this ); } ////////////////////////////////////////////////////////////////////// // // create the traces drawing area widget // ////////////////////////////////////////////////////////////////////// widTraces_ = XtVaCreateManagedWidget("tracesDrawingArea", xmDrawingAreaWidgetClass, widFormInFrame, XmNancestorSensitive, True, XmNtopOffset, 0, XmNbottomOffset, 0, XmNleftOffset, 0, XmNrightOffset, 0, XmNshadowThickness, 0, XmNborderWidth, 0, XmNtopAttachment, XmATTACH_WIDGET, XmNtopWidget, widLastAddedWidget, XmNbottomAttachment, XmATTACH_FORM, XmNbottomWidget, widScrollBar_, XmNleftAttachment, XmATTACH_FORM, XmNrightAttachment, XmATTACH_FORM, XtNheight, (Dimension) consedParameters::pGetConsedParameters()->nTracesWindowInitialPixelHeight_, XtNwidth, (Dimension) consedParameters::pGetConsedParameters()->nTracesWindowInitialPixelWidth_, NULL ); XtAddCallback( widTraces_, XmNexposeCallback, (XtCallbackProc ) guiTedWinTracesExposureXtCb, this ); XtAddCallback(widTraces_, XmNresizeCallback, (XtCallbackProc ) guiTedWinResizeXtCb, this); // all the drawing areas of the GuiTedWin will pass KeyPress events // to this handler. The user is not required to click on the // fragment base window specifically to put input focus there. XtAddEventHandler( widTraces_, KeyPressMask, False, (XtEventHandler) guiTedWinKeyPressXtEventHandler, this ); XmString xmsLabel = XmStringCreateLtoR("Scroll\nTogether?", XmFONTLIST_DEFAULT_TAG ); Widget widLabel = XtVaCreateManagedWidget("Scroll Traces Together?", xmLabelWidgetClass, widForm_, XmNtopAttachment, XmATTACH_WIDGET, XmNtopWidget, widVerticalScale_, XmNtopOffset, 10, XmNleftAttachment, XmATTACH_FORM, XmNlabelString, xmsLabel, XmNalignment, XmALIGNMENT_BEGINNING, NULL ); XmStringFree( xmsLabel ); Widget widScrollTogetherRadioBox = XmCreateRadioBox( widForm_, "radio", NULL, 0 ); XtVaSetValues( widScrollTogetherRadioBox, XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET, XmNtopWidget, widLabel, XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET, XmNbottomWidget, widLabel, XmNleftAttachment, XmATTACH_WIDGET, XmNleftWidget, widLabel, XmNorientation, XmHORIZONTAL, XmNtraversalOn, False, XmNshadowThickness,0, XmNborderWidth, 0, XmNmarginWidth, 0, NULL ); widYes_ = XtVaCreateManagedWidget( "Yes", xmToggleButtonWidgetClass, widScrollTogetherRadioBox, XmNset, bGuiTedWinsScrollTogether(), NULL ); XtAddCallback( widYes_, XmNvalueChangedCallback, (XtCallbackProc) cbScrollTogetherRadioBox, this ); widNo_ = XtVaCreateManagedWidget( "No", xmToggleButtonWidgetClass, widScrollTogetherRadioBox, XmNset, !bGuiTedWinsScrollTogether(), NULL ); XtManageChild( widScrollTogetherRadioBox ); // // remove button // ibRemove_.initialize(widForm_, // child of outermost form cbRemoveTedWin, // callback invokes dtor this, // pointer to GuiTedWin NULL, // no client data "Remove", // label true, // always visible true); // initially active // positioned in the lower left hand corner nArgs = 0; XtSetArg(aArg[nArgs], XmNtopAttachment, XmATTACH_NONE); nArgs++; XtSetArg(aArg[nArgs], XmNrightAttachment, XmATTACH_NONE); nArgs++; XtSetArg(aArg[nArgs], XmNbottomAttachment, XmATTACH_FORM); nArgs++; XtSetArg(aArg[nArgs], XmNleftAttachment, XmATTACH_POSITION); nArgs++; XtSetArg(aArg[nArgs], XmNleftPosition, 1); nArgs++; XtSetValues(ibRemove_.widGet(), aArg, nArgs); widUndoButton_ = XtVaCreateManagedWidget( "Undo", xmPushButtonWidgetClass, widForm_, XmNtopAttachment, XmATTACH_NONE, XmNleftAttachment, XmATTACH_NONE, XmNbottomAttachment, XmATTACH_FORM, XmNrightAttachment, XmATTACH_OPPOSITE_WIDGET, XmNrightWidget, widSequenceName_, XmNtopWidget, widSequenceName_, XmNsensitive, False, // initialize not sensitive NULL ); XtAddCallback( widUndoButton_, XmNactivateCallback, (XtCallbackProc) cbTedWinUndo, this ); // static class member pixmaps get created first time through ctor if (! bPixmapsCreated_) createReadSensePixmaps(); // possibly dangerous kludge: // the user can set both the range and initial value of the mag sliders // by overriding the fallback values specified in guiapp.cpp // however, the GuiTedWin needs to know these values for the initial // expose callback. thus, we ask the already formed widgets what their // values are nArgs = 0; int nHorizScaleValue; XtSetArg(aArg[nArgs], XmNvalue, &nHorizScaleValue); nArgs++; XtGetValues(widHorizontalScale_, aArg, nArgs); // set private data member dPixelsPerPoint_ = nHorizScaleValue * dPixelsPerPointInit / (double) nHorizontalScaleInit; // do same for vert scale nArgs = 0; XtSetArg(aArg[nArgs], XmNvalue, &nVerticalScaleValue_ ); nArgs++; XtGetValues(widVerticalScale_, aArg, nArgs); positionLabel( eConsensusScale ); positionLabel( eReadScale ); positionLabel( eConsensusBase ); positionLabel( eFragmentBase ); positionLabel( ePhredCalledBase ); if ( bShowABICalledBases_ ) positionLabel( eABICalledBase ); XmProcessTraversal( widFragmentBases_, XmTRAVERSE_CURRENT ); bGuiTedWinCtorFinished_ = true; } // if ( bAddToScrollingWindow ) { else } // GuiTedWin ctor // not inlined to avoid circular includes Teditor* GuiTedWin::pTeditorGet() { return pTedWin_->pTeditorGet(); } GuiTeditor* GuiTedWin::pGuiTeditorGet() { return pTeditorGet()->pGuiTeditorGet(); } // all this pixmap stuff is here because XCreatePixmapFromData // can't get a valid drawable until it has been realized... void GuiTedWin::createReadSensePixmaps() { // pick up fg bg, depth values from the label itself // which by now should have been realized. copy it's colors // and depth, allowing user resource prefs Pixel fg, bg; int depth; XtVaGetValues(widReadSenseLabel_, XmNforeground, &fg, XmNbackground, &bg, XmNdepth, &depth, NULL); pixSenseForward_ = XCreatePixmapFromBitmapData(XtDisplay(widReadSenseLabel_), XtWindowOfObject(widReadSenseLabel_), forward_bitmap_bits, forward_bitmap_width, forward_bitmap_height, fg, bg, depth); pixSenseReverse_ = XCreatePixmapFromBitmapData(XtDisplay(widReadSenseLabel_), XtWindowOfObject(widReadSenseLabel_), reverse_bitmap_bits, reverse_bitmap_width, reverse_bitmap_height, fg, bg, depth); // set class flag to indicate this has been done bPixmapsCreated_ = true; } void GuiTedWin::setReadSenseForward() { Arg aArg[10]; int nArgs = 0; // set the pixmap resource of the label nArgs = 0; XtSetArg(aArg[nArgs], XmNlabelPixmap, pixSenseForward_); nArgs++; XtSetValues(widReadSenseLabel_, aArg, nArgs); } void GuiTedWin::setReadSenseReverse() { Arg aArg[10]; int nArgs = 0; // set the pixmap resource of the label nArgs = 0; XtSetArg(aArg[nArgs], XmNlabelPixmap, pixSenseReverse_); nArgs++; XtSetValues(widReadSenseLabel_, aArg, nArgs); } // callback for "Remove" button destroys self, Teditor object // and motif shell void cbRemoveTedWin(void* pvClientThis, void* /* pvClientData */ ) { GuiTedWin* pGuiTedWin = (GuiTedWin* )pvClientThis; GuiTeditor* pGuiTeditor = pGuiTedWin->pGuiTeditorGet(); pGuiTeditor->removeGuiTedWinByUser( pGuiTedWin ); } // callback for "Undo" button tells the ConsEd to undo the last edit void cbTedWinUndo(void*, void*) { TRY_CATCH_WRAPPER( ConsEd::pGetConsEd()->undoLastEditAction( true ); ); } void guiTedWinResizeXtCb( Widget, GuiTedWin* pGuiTedWin, XmDrawingAreaCallbackStruct*) { TRY_CATCH_WRAPPER( if (!pGuiTedWin->bGuiTedWinCtorFinished_ ) return; pGuiTedWin->resizeSlider(); pGuiTedWin->pTedWin_->setBasePixelPositions(); pGuiTedWin->pTedWin_->drawBasesAndTraces( false ) ); } void guiTedWinTracesExposureXtCb( Widget, GuiTedWin* pGuiTedWin, XmDrawingAreaCallbackStruct*) { TRY_CATCH_WRAPPER( pGuiTedWin->pTedWinGet()->drawTraces(); pGuiTedWin->pTedWinGet()->drawVerticalLineThroughTraces()); } void guiTedWinABICalledBasesXtCb(Widget, GuiTedWin* pGuiTedWin, XmDrawingAreaCallbackStruct*) { TRY_CATCH_WRAPPER(pGuiTedWin->pTedWinGet()->drawCalledBases( eABICalledBase )); } void guiTedWinPhredCalledBasesXtCb( Widget, GuiTedWin* pGuiTedWin, XmDrawingAreaCallbackStruct*) { TRY_CATCH_WRAPPER(pGuiTedWin->pTedWinGet()->drawCalledBases(ePhredCalledBase)); } void guiTedWinConsensusExposureXtCb(Widget, GuiTedWin* pGuiTedWin, XmDrawingAreaCallbackStruct*) { TRY_CATCH_WRAPPER(pGuiTedWin->pTedWinGet()->drawConsensusBases()); } void guiTedWinSameAsContigWinExposureXtCb(Widget, GuiTedWin* pGuiTedWin, XmDrawingAreaCallbackStruct*) { TRY_CATCH_WRAPPER(pGuiTedWin->pTedWinGet()->drawFragmentBases()); } void guiTedWinScaleExposureXtCb(Widget, GuiTedWin* pGuiTedWin, XmDrawingAreaCallbackStruct*) { TRY_CATCH_WRAPPER(pGuiTedWin->pTedWinGet()->drawScale( false, // bDrawInShowAllTracesConsensusWindow pGuiTedWin->bShowConsensusPositionsLine_ ) ); } int GuiTedWin :: nGetTraceWindowPointsWide() { int nPixelsWide = nGetTraceWindowPixelWidth(); double dPointsWide = nPixelsWide / dPixelsPerPoint_; int nPointsWide = (int) (dPointsWide + .5 ); return( nPointsWide ); } // currently only used to draw called bases void GuiTedWin :: guiDrawBaseAtPeakPosition( eTeditorType eTeditorTypee, int nCurrentBasePointLocation, char cBase, GuiColorText* pGuiColorText, const bool bLeftMostBase ) { Widget wid = widGetWidgetFromBaseType( eTeditorTypee ); int nPixelXThisBase = nPixelXFromPoint( nCurrentBasePointLocation ); // adjust the location of the base so that it is centered over the peak nPixelXThisBase -= GuiApp::pGetGuiApp()->nGetFontOriginFromCenter(); if (!bLeftMostBase ) { if (nPixelXPreviousBase_ + GuiApp::pGetGuiApp()->nGetFontWidth() > nPixelXThisBase) nPixelXThisBase = nPixelXPreviousBase_ + GuiApp :: pGetGuiApp()->nGetFontWidth(); } XDrawString( XtDisplay( wid ), XtWindow( wid ), pGuiColorText->gcGet(), nPixelXThisBase, nGetTextBaseline( eTeditorTypee ), &cBase, 1 ); nPixelXPreviousBase_ = nPixelXThisBase; } void GuiTedWin :: guiDrawBaseAtSavedPixelPosition( eTeditorType eTeditorTypee, int nConsPos, char cBase, GuiColorText* pGuiColorText ) { Widget wid = widGetWidgetFromBaseType( eTeditorTypee ); int nLeftPixel = nLeftPixelXFromConsPos( nConsPos ); int nRightPixel = nRightPixelXFromConsPos( nConsPos ); int nPixelWidth = nRightPixel - nLeftPixel + 1; int nTopPixel = nGetTextTopPixel( eTeditorTypee ); XFillRectangle( XtDisplay( wid ), XtWindow( wid ), pGuiColorText->gcGetReverse(), nLeftPixel, nTopPixel, nPixelWidth - 1, // this was set experimentally // so the bounds of the rectangle // coincided with the bounds of which // base is selected when a user clicks // MB2 GuiApp::pGetGuiApp()->nGetFontHeight() // this was // set experimentally so that the rectange // was the same height as a character background ); int nPixelXThisBase = nPixelXFromConsPos( nConsPos ); // adjust the location of the base so that it is centered over the peak nPixelXThisBase -= GuiApp::pGetGuiApp()->nGetFontOriginFromCenter(); XDrawImageString( XtDisplay( wid ), XtWindow( wid ), pGuiColorText->gcGet(), nPixelXThisBase, nGetTextBaseline( eTeditorTypee ), &cBase, 1 ); } void GuiTedWin :: guiDrawHalfCharacterTagAtSavedPixelPosition( const eTeditorType eTeditorTypee, int nConsPos, GuiColorText* pGuiColorTextForTag ) { assert( eTeditorTypee == eFragmentBase || eTeditorTypee == eConsensusBase ); Widget wid = widGetWidgetFromBaseType( eTeditorTypee ); int nLeftPixel = nLeftPixelXFromConsPos( nConsPos ); int nRightPixel = nRightPixelXFromConsPos( nConsPos ); int nPixelWidth = nRightPixel - nLeftPixel + 1; int nBottomPixel = nGetTextTopPixel( eTeditorTypee ) + GuiApp::pGetGuiApp()->nGetFontHeight(); int nTopPixel = nBottomPixel - ( GuiApp::nGetFontHeight() * consedParameters::pGetConsedParameters()->nTagColorPerCentOfBase_ ) / 100; int nHeight = nBottomPixel - nTopPixel; XFillRectangle( XtDisplay( wid ), XtWindow( wid ), pGuiColorTextForTag->gcGetReverse(), nLeftPixel, nTopPixel, nPixelWidth - 1, // this was set experimentally // so the bounds of the rectangle // coincided with the bounds of which // base is selected when a user clicks // MB2 nHeight ); } void GuiTedWin :: guiDrawBaseWithoutBackgroundAtSavedPixelPosition( const eTeditorType eTeditorTypee, int nConsPos, char cBase, GuiColorText* pGuiColorText ) { assert( eTeditorTypee == eFragmentBase || eTeditorTypee == eConsensusBase ); Widget wid = widGetWidgetFromBaseType( eTeditorTypee ); int nPixelXThisBase = nPixelXFromConsPos( nConsPos ); // adjust the location of the base so that it is centered over the peak nPixelXThisBase -= GuiApp::pGetGuiApp()->nGetFontOriginFromCenter(); XDrawString( XtDisplay( wid ), XtWindow( wid ), pGuiColorText->gcGet(), nPixelXThisBase, nGetTextBaseline( eTeditorTypee ), &cBase, 1 ); } int GuiTedWin :: nGetTraceWindowPixelWidth() { Arg aArg[10]; Dimension nPixelsWide; int nArgs = 0; XtSetArg( aArg[nArgs], XtNwidth, &nPixelsWide); ++nArgs; XtGetValues( widTraces_, aArg, nArgs ); return( (int) nPixelsWide ); } void GuiTedWin :: guiClearWindow( eTeditorType eTeditorTypee ) { Widget wid = widGetWidgetFromBaseType( eTeditorTypee ); XClearArea( XtDisplay( wid ), XtWindow( wid ), 0, 0, 0, // clear whole area 0, // clear whole area false // no expose event ); } void GuiTedWin :: clearTracesWindow( ) { XClearArea( XtDisplay( widTraces_ ), XtWindow( widTraces_ ), 0, 0, 0, // clear whole area 0, // clear whole area false // no expose event ); } int GuiTedWin :: nPixelXFromPoint( const int nPoint ) { double d = nPoint - nLeftEdgePointPosition_; // 0.5 is to round double d2 = d * dPixelsPerPoint_ + 0.5; return( d2 ); } int GuiTedWin :: nPointFromPixelX( const int nPixelX ) { double dPointsFromLeftEdge = nPixelX / dPixelsPerPoint_; int nPointsFromLeftEdge = (int) (dPointsFromLeftEdge + .5 ); int nPoint = nPointsFromLeftEdge + nLeftEdgePointPosition_; return( nPoint ); } Widget GuiTedWin :: widGetWidgetFromBaseType( eTeditorType ebt ) { if ( ebt == eABICalledBase ) return( widABICalledBases_ ); else if ( ebt == ePhredCalledBase ) return( widPhredCalledBases_ ); else if ( ebt == eConsensusBase ) return( widConsensus_ ); else if ( ebt == eFragmentBase ) return( widFragmentBases_ ); else if ( ebt == eScaleWindow ) return( widScale_ ); else if ( ebt == eShowAllTracesScaleWindow ) return( pTedWin_->pTeditor_->pGuiTeditor_->widConsensusScale_ ); else assert( false ); // programming error } void GuiTedWin :: drawTrace( const char c ) { // these are needed to scale the trace height. Notice that // when automatically scaling the traces, the // pCP->nVerticalTraceMagnification_ value is not used so the // parameter on the general preferences has no effect. float fTraceHeightFactor; if ( pCP->bAutomaticallyScaleTraces_ ) fTraceHeightFactor = fGetScaleFactorToAutomaticallyScaleTraces() * ( (float) nVerticalScaleValue_ / 100.0 ); else fTraceHeightFactor = ( (float) nVerticalScaleValue_ / 100.0 ) * ( (float) pCP->nVerticalTraceMagnification_ / 30.0 ); int nTraceHeightBias = ( pCP->bAutomaticallyScaleTraces_ ? pTedWin_->pLocatedFragment_->pTraceFile_->nMinTraceValue_ : 0 ); int nTraceWindowHeight = nGetTraceWindowHeight(); const int nMaxPoints = 2000; // some servers can handle more points than this, but // this is the minimum. It is also more than enough, so // don't waste time asking the server for its maximum. XPoint xpoints[ nMaxPoints ]; int nPointEnd = nGetRightEdgePointPosition(); // the traces might end in the middle of the window, if the // user has recently changed the horizontal scale. // Don't go out of bounds. if ( nPointEnd > (pTedWin_->nGetNumberOfPoints() -1) ) nPointEnd = pTedWin_->nGetNumberOfPoints() - 1; int nXPointIndex = -1; // set up for ++ int nPoint = nLeftEdgePointPosition_ - 1; // set up for ++ // handle case in which the window is part way off the left of the // trace if (nPoint < -1 ) nPoint = -1; bool bEnd = FALSE; while( !bEnd ) { ++nXPointIndex; ++nPoint; xpoints[nXPointIndex].x = nPixelXFromPoint( nPoint ); unsigned int nTraceVal = pTedWin_->nGetTraceValue( c, nPoint ); // X windows have 0 at the top and numbers increase down // Thus must subtract from nTraceWindowHeight xpoints[nXPointIndex].y = nTraceWindowHeight - (int) ( ( nTraceVal - nTraceHeightBias ) * fTraceHeightFactor ); if ( (nXPointIndex >= ( nMaxPoints - 1 ) ) || ( nPoint >= nPointEnd )) { XDrawLines( XtDisplay( widTraces_ ), XtWindow( widTraces_ ), GCForTrace( c ), xpoints, nXPointIndex + 1, // since it starts at 0 CoordModeOrigin ); nXPointIndex = -1; } if (nPoint >= nPointEnd ) bEnd = TRUE; } // while( !bEnd ) { } GC GuiTedWin :: GCForTrace( const char c ) { if (c == 'A') return( pGetGuiColorTextA()->gcGet() ); else if (c == 'C') return( pGetGuiColorTextC()->gcGet() ); else if (c == 'G') return( pGetGuiColorTextG()->gcGet() ); else if (c == 'T') return( pGetGuiColorTextT()->gcGet() ); else assert( FALSE ); // programming bug } int GuiTedWin :: nGetTraceWindowHeight() { Arg aArg[10]; Dimension nPixelsHigh; int nArgs = 0; XtSetArg( aArg[nArgs], XtNheight, &nPixelsHigh); ++nArgs; XtGetValues( widTraces_, aArg, nArgs); return( nPixelsHigh ); } float GuiTedWin :: fGetScaleFactorToAutomaticallyScaleTraces() { int nCalledPosLeft; int nCalledPosRight; bool bError; pTedWin_->pLocFragGet()->getRangeOfPhredCalledPositions( nGetLeftEdgePointPosition(), nGetRightEdgePointPosition(), nCalledPosLeft, nCalledPosRight, bError ); if ( bError ) { // there were no called bases on the screen return( 100.0 ); } int nNumberOfBasesOnScreen = nCalledPosRight - nCalledPosLeft + 1; mbtValOrderedVectorOfInt aPeakHeights_( (size_t) nNumberOfBasesOnScreen ); for( int nCalledBase = nCalledPosLeft; nCalledBase <= nCalledPosRight; ++nCalledBase ) { int nPointPos = pTedWin_->pLocFragGet()->nGetPointPosOfPhredCalledBase( nCalledBase ); char cBase = pTedWin_->pLocFragGet()->ntideGetPhredCalledBase( nCalledBase ).cGetBase(); int nHeightOfHighestTrace; if ( cBase == 'a' || cBase == 'c' || cBase == 'g' || cBase == 't' ) nHeightOfHighestTrace= pTedWin_->nGetTraceValue( cBase, nPointPos ); else { int nHeightA = pTedWin_->nGetTraceValue( 'a', nPointPos ); int nHeightC = pTedWin_->nGetTraceValue( 'c', nPointPos ); int nHeightG = pTedWin_->nGetTraceValue( 'g', nPointPos ); int nHeightT = pTedWin_->nGetTraceValue( 't', nPointPos ); nHeightOfHighestTrace = MAX( nHeightA, MAX( nHeightC, MAX( nHeightG, nHeightT ))); } aPeakHeights_.insert( nHeightOfHighestTrace ); } // sort this list aPeakHeights_.resort(); // find the value at the correct percentile value // index: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 // 1-based 1 2 3 4 5 6 7 8 9 10 // percentile: 10 20 30 40 50 60 70 80 90 100 float fSampleIndex = (float) pCP->nAutomaticallyScaleTracesSamplePeakPercentile_ / 100.0 * nNumberOfBasesOnScreen - 1.0; // should we round up or down? E.g., suppose 80th percentile and there // are only 2 values so .8 * 2 - 1.0 = .6 Should we use the upper or lower // value? Upper may be fake. So use the lower. int nSampleIndex = fSampleIndex; int nSamplePeakHeight = aPeakHeights_[ nSampleIndex ]; // now let's scale this so that it fits in a certain height of the // window. We want it such that window-height * fraction-of-window-height // = fScale * nSamplePeakHeight float fScale = (float) nGetTraceWindowHeight() * pCP->dAutomaticallyScaleTracesSamplePeakHeightFractionOfWindowHeight_ / (float) nSamplePeakHeight; return( fScale ); } // for efficiency when scaling each trace y value int GuiTedWin :: nGetTraceHeightFactor() { const int nMaxTraceVal = 4000; // ted authors thought this was true int nTraceHeightFactor = nVerticalScaleValue_ * pCP->nVerticalTraceMagnification_ * nGetTraceWindowHeight() * 100; // the 100 is just so that // this factor is around 100 rather than 1 so that the rounding to // an integer doesn't have such a dramatic %age effect if ( pCP->bAutomaticallyScaleTraces_ ) { TraceFile* pTrace = pTedWin_->pLocatedFragment_->pTraceFile_; int nRange = pTrace->nMaxTraceValue_ - pTrace->nMinTraceValue_; // just to make sure we don't divide by zero if ( nRange == 0 ) nRange = nMaxTraceVal; nTraceHeightFactor /= nRange; nTraceHeightFactor /= 3; } else { nTraceHeightFactor /= nMaxTraceVal; } return( nTraceHeightFactor ); } // // this is the Xt callback for the horizontal magnification scale // void guiTedWinHorizontalMagXtCb(Widget, GuiTedWin* pGuiTedWin, XmScaleCallbackStruct *pCbStruct) { pGuiTedWin->dPixelsPerPoint_ = pCbStruct->value * dPixelsPerPointInit / nHorizontalScaleInit; TRY_CATCH_WRAPPER( pGuiTedWin->pTedWinGet()->userChangedHorizontalMagnification(); ); } // // this is the Xt callback for the vertical magnification scale // void guiTedWinVerticalMagXtCb(Widget, GuiTedWin* pGuiTedWin, XmScaleCallbackStruct *pCbStruct) { pGuiTedWin->nVerticalScaleValue_ = pCbStruct->value; TRY_CATCH_WRAPPER(pGuiTedWin->pTedWin_->drawTraces( )); } // this is the Xt callback for the scroll bar moving void guiTedWinScrollBarXtCb(Widget, GuiTedWin* pGuiTedWin, XmScrollBarCallbackStruct *pCbStruct ) { TRY_CATCH_WRAPPER(pGuiTedWin->pTedWin_->userMovedScrollBar( pCbStruct->value )); } // used just after creating the scroll bar void GuiTedWin :: guiTedWinResetSlider( const int nCurrentPosition, const int nMin, const int nMax, const int nUnitsDisplayed ) { if ( !bShowScrollbar_ ) return; Arg aArg[20]; int nArgs; nArgs = 0; XtSetArg( aArg[nArgs], XmNvalue, nCurrentPosition ); ++nArgs; XtSetArg( aArg[nArgs], XmNminimum, nMin); ++nArgs; XtSetArg( aArg[nArgs], XmNmaximum, nMax ); ++nArgs; XtSetArg( aArg[nArgs], XmNsliderSize, nUnitsDisplayed); ++nArgs; XtSetArg( aArg[nArgs], XmNpageIncrement, nUnitsDisplayed - 1); ++nArgs; XtSetValues( widScrollBar_, aArg, nArgs ); } // passed position in points, sets scrollbar resources to that // position and saves new current pos in member data void GuiTedWin::setScrollBarPosition( const int nNewScrollBarPosition ) { if (!bShowScrollbar_ ) return; Arg aArg[2]; int nArgs = 0; XtSetArg( aArg[nArgs], XmNvalue, nNewScrollBarPosition ); ++nArgs; XtSetValues( widScrollBar_, aArg, nArgs ); } // used after changing the horizontal size or horizontal scale of the // traces window void GuiTedWin :: resizeSlider() { if (!bShowScrollbar_ ) return; Arg aArg[20]; int nArgs; nArgs = 0; XtSetArg( aArg[nArgs], XmNsliderSize, nGetTraceWindowPointsWide() ); ++nArgs; XtSetArg( aArg[nArgs], XmNpageIncrement, nGetTraceWindowPointsWide() - 1); ++nArgs; XtSetValues( widScrollBar_, aArg, nArgs ); } // this routine returns the width, in points, required to draw // a passed integer on the scale window. that way we can know // if the numbers above adjacent scale ticks are starting to // smush together. int GuiTedWin:: nGetPixelsRequiredForString(const int nCharactersWide) { int nPixelsRequired = nCharactersWide * GuiApp::pGetGuiApp()->nGetFontWidth(); return nPixelsRequired; } void GuiTedWin :: guiDrawScaleNumber(const int nNumberToDraw, const int nConsPos, const eScaleType eScaleTypee, const bool bDrawInShowAllTracesConsensusWindow ) { Widget wid = widGetScaleWidget( bDrawInShowAllTracesConsensusWindow ); char szNumber[200]; sprintf( szNumber, "%d", nNumberToDraw ); int nNumberOfDigits = strlen( szNumber ); int nPixelXOfTickk = nPixelXOfTick( nConsPos ); int nPixelsOffset = ( nNumberOfDigits * GuiApp::pGetGuiApp()->nGetFontWidth() ) / 2; int nPixelXOfNumber = nPixelXOfTickk - nPixelsOffset; int nY = bDrawInShowAllTracesConsensusWindow ? nShowAllTracesScaleNumbersBaseline() : nScaleNumbersBaseline( eScaleTypee ); XDrawString( XtDisplay( wid ), XtWindow( wid ), pGetGuiColorTextForScaleNumbers()->gcGet(), nPixelXOfNumber, // x nY, szNumber, strlen( szNumber ) ); } void GuiTedWin :: guiDrawScaleTick(const int nConsPos, const bool bDrawBigTick, const bool bDrawInShowAllTracesConsensusWindow ) { Widget wid = widGetScaleWidget( bDrawInShowAllTracesConsensusWindow ); int nPixelXOfTickk = nPixelXOfTick( nConsPos ); int nLengthOfTick = ( bDrawBigTick )? nScaleMarksHeight() : (nScaleMarksHeight() / 3 ); int nY = bDrawInShowAllTracesConsensusWindow ? nGetShowAllTracesScaleLinePixelY() : nScaleLinePixelY(); XDrawLine( XtDisplay( wid ), XtWindow( wid ), pGetGuiColorTextForScale()->gcGet(), nPixelXOfTickk, nY, nPixelXOfTickk, nY + nLengthOfTick ); } void GuiTedWin :: guiDrawScaleLine( const bool bDrawInShowAllTracesConsensusWindow ) { Widget wid = widGetScaleWidget( bDrawInShowAllTracesConsensusWindow ); int nY = bDrawInShowAllTracesConsensusWindow ? nGetShowAllTracesScaleLinePixelY() : nScaleLinePixelY(); // draw the line below the numbers and above the tickmarks XDrawLine(XtDisplay( wid ), XtWindow( wid ), pGetGuiColorTextForScale()->gcGet(), 0, // left edge of window nY, nGetTraceWindowPixelWidth() - 1, nY ); } // draw the line below the consensus bases void GuiTedWin :: guiDrawConsSepLine() { XDrawLine(XtDisplay( widConsensus_ ), XtWindow( widConsensus_ ), pGetGuiColorTextForScale()->gcGet(), 0, // left edge of window nGetTextWindowHeight( eConsensusBase ) - 1, nGetTraceWindowPixelWidth() - 1, nGetTextWindowHeight( eConsensusBase ) - 1 ); } void GuiTedWin::allocateColors() { bColorsAllocated_ = TRUE; pGuiColorTextA_ = new GuiColorText( ColorDefaults::pGetColorDefaults()->soColorTracesA_, "Black" ); pGuiColorTextC_ = new GuiColorText( ColorDefaults::pGetColorDefaults()->soColorTracesC_, "Black" ); pGuiColorTextG_ = new GuiColorText( ColorDefaults::pGetColorDefaults()->soColorTracesG_, "Black" ); pGuiColorTextT_ = new GuiColorText( ColorDefaults::pGetColorDefaults()->soColorTracesT_, "Black" ); pGuiColorTextN_ = new GuiColorText( ColorDefaults::pGetColorDefaults()->soColorTracesN_, "Black" ); pGuiColorTextPad_ = new GuiColorText( ColorDefaults::pGetColorDefaults()->soColorTracesPad_, "Black" ); pGuiColorTextHighlightedA_ = new GuiColorText( ColorDefaults::pGetColorDefaults()->soColorHighlightForegroundX_, ColorDefaults::pGetColorDefaults()->soColorHighlightBackground_ ); pGuiColorTextHighlightedC_ = new GuiColorText( ColorDefaults::pGetColorDefaults()->soColorHighlightForegroundX_, ColorDefaults::pGetColorDefaults()->soColorHighlightBackground_ ); pGuiColorTextHighlightedG_ = new GuiColorText( ColorDefaults::pGetColorDefaults()->soColorHighlightForegroundX_, ColorDefaults::pGetColorDefaults()->soColorHighlightBackground_ ); pGuiColorTextHighlightedT_ = new GuiColorText( ColorDefaults::pGetColorDefaults()->soColorHighlightForegroundX_, ColorDefaults::pGetColorDefaults()->soColorHighlightBackground_ ); pGuiColorTextHighlightedN_ = new GuiColorText( ColorDefaults::pGetColorDefaults()->soColorHighlightForegroundX_, ColorDefaults::pGetColorDefaults()->soColorHighlightBackground_ ); pGuiColorTextHighlightedX_ = new GuiColorText( ColorDefaults::pGetColorDefaults()->soColorHighlightForegroundX_, ColorDefaults::pGetColorDefaults()->soColorHighlightBackground_ ); pGuiColorTextHighlightedPad_ = new GuiColorText( ColorDefaults::pGetColorDefaults()->soColorHighlightForegroundX_, ColorDefaults::pGetColorDefaults()->soColorHighlightBackground_ ); pGuiColorTextHighlightBackground_ = new GuiColorText( ColorDefaults::pGetColorDefaults()->soColorHighlightBackground_, ColorDefaults::pGetColorDefaults()->soColorHighlightBackground_ ); pGuiColorTextForScale_ = new GuiColorText( ColorDefaults::pGetColorDefaults()->soColorScale_, "Black" ); pGuiColorTextForConsCursor_ = new GuiColorText( ColorDefaults::pGetColorDefaults()->soColorMode_editCursorForeground_, ColorDefaults::pGetColorDefaults()->soColorMode_editCursorBackground_ ); pGuiColorTextForScaleNumbers_ = new GuiColorText( ColorDefaults::pGetColorDefaults()->soColorScale_, "Black" ); } // labels the consensus, fragment, phred calls, ABI calls Widget GuiTedWin :: widMakeLabel( const eTeditorType eTeditorTypee, const int nPositionY ) { char* szLabel; switch( eTeditorTypee ) { case eConsensusBase : szLabel = "con"; break; case eFragmentBase : szLabel = "edt"; break; case ePhredCalledBase : szLabel = "phd"; break; case eABICalledBase : szLabel = "ABI"; break; case eConsensusScale : szLabel = "con"; break; case eReadScale : szLabel = "rd"; break; default: assert( false ); } // label the consensus line int nArgs = 0; Arg aArg[30]; Position pos = nPositionY; XtSetArg(aArg[nArgs], XmNy, pos ); nArgs++; XtSetArg(aArg[nArgs], XmNmarginHeight, 0 ); nArgs++; XtSetArg(aArg[nArgs], XmNmarginTop, 0 ); nArgs++; XtSetArg(aArg[nArgs], XmNmarginBottom, 0 ); nArgs++; XtSetArg(aArg[nArgs], XmNborderWidth, 0 ); nArgs++; XtSetArg(aArg[nArgs], XmNshadowThickness, 0 ); nArgs++; XtSetArg(aArg[nArgs], XmNleftAttachment, XmATTACH_WIDGET); nArgs++; XtSetArg(aArg[nArgs], XmNleftWidget, widSequenceName_ ); nArgs++; Widget widLabel = XmCreateLabel( widForm_, szLabel, aArg, nArgs); XtManageChild( widLabel ); return( widLabel ); } int GuiTedWin :: nGetMaxWidthOfLabels() { int nMaxWidth = 0; int nWidth; nWidth = nGetWidthOfWidget( widConsensusScaleLabel_ ); if (nWidth > nMaxWidth) nMaxWidth = nWidth; nWidth = nGetWidthOfWidget( widReadScaleLabel_ ); if (nWidth > nMaxWidth) nMaxWidth = nWidth; if ( bShowConsensusLine_ ) { nWidth = nGetWidthOfWidget( widConsensusLabel_ ); if (nWidth > nMaxWidth) nMaxWidth = nWidth; } nWidth = nGetWidthOfWidget( widFragmentBasesLabel_ ); if (nWidth > nMaxWidth) nMaxWidth = nWidth; if ( bShowPhredCalledBasesLine_ ) { nWidth = nGetWidthOfWidget( widPhredCalledBasesLabel_ ); if (nWidth > nMaxWidth) nMaxWidth = nWidth; } if ( bShowABICalledBases_ ) { nWidth = nGetWidthOfWidget( widABICalledBasesLabel_ ); if (nWidth > nMaxWidth) nMaxWidth = nWidth; } nWidth = nGetWidthOfWidget( widReadSenseLabel_ ); if (nWidth > nMaxWidth) nMaxWidth = nWidth; return( nMaxWidth ); } int GuiTedWin :: nGetTextBaseline( eTeditorType eTeditorTypee) { // different windows have different top margins, so this is // the simplest way of getting the baseline, which works for // all different windows. if ( eTeditorTypee == eConsensusScale ) return( nScaleNumbersBaseline( eConsensusPosition ) ); else if (eTeditorTypee == eReadScale ) return( nScaleNumbersBaseline( eFragmentPosition ) ); else return( nGetTextWindowHeight( eTeditorTypee ) - nBottomTextMargin - GuiApp::pGetGuiApp()->nGetFontDescent() ); } int GuiTedWin :: nGetTextWindowHeight( eTeditorType eTeditorTypee ) { int nHeight = GuiApp::pGetGuiApp()->nGetFontHeight() + nBottomTextMargin; switch ( eTeditorTypee ) { case eConsensusBase : nHeight += nConsensusTopMargin; break; case eABICalledBase: nHeight += nCalledBasesTopMargin; break; case ePhredCalledBase: nHeight += nCalledBasesTopMargin; break; case eFragmentBase : nHeight += nFragmentBaseTopMargin; break; default: assert( false ); } return( nHeight ); } void GuiTedWin :: positionLabel( eTeditorType eTeditorTypee ) { // To position the label, get the midline of the corresponding line // of text that you want to label. (The midline is halfway between // the baseline and the top of the ascenders.) Translate this to // the widForm_ coordinate system, since that is the parent of the labels // and hence what is used by // the X routines to set the position of the labels. // The reason that the midline is used is that the label font is // this is the way of aligning--using the baseline doesn't work. (DG) int nMidlineOfTextInRootCoords = nGetTextWindowMidlineInRootCoords( eTeditorTypee); int nMidlineInFormCoords = nRootYCoordsToFormYCoords( nMidlineOfTextInRootCoords); Widget widLabel; switch ( eTeditorTypee ) { case eConsensusScale : widLabel = widConsensusScaleLabel_; break; case eReadScale : widLabel = widReadScaleLabel_; break; case eConsensusBase : widLabel = widConsensusLabel_; break; case eFragmentBase : widLabel = widFragmentBasesLabel_; break; case ePhredCalledBase: widLabel = widPhredCalledBasesLabel_; break; case eABICalledBase: widLabel = widABICalledBasesLabel_; break; default: assert( false ); } int nLabelHeight = nGetHeightOfWidget( widLabel ); Position posTopOfLabelInFormCoords = nMidlineInFormCoords - ( nLabelHeight / 2 ); // Due to a bug in X, the value of XmNy cannot be changed--even if you // unmanage, change, and manage. So destroy and recreate where you // want the label. XtDestroyWidget( widLabel ); widLabel = widMakeLabel( eTeditorTypee, posTopOfLabelInFormCoords ); switch ( eTeditorTypee ) { case eConsensusScale : widConsensusScaleLabel_ = widLabel; break; case eReadScale : widReadScaleLabel_ = widLabel; break; case eConsensusBase : widConsensusLabel_ = widLabel; break; case eFragmentBase : widFragmentBasesLabel_ = widLabel; break; case ePhredCalledBase: widPhredCalledBasesLabel_ = widLabel; break; case eABICalledBase: widABICalledBasesLabel_ = widLabel; break; default: assert( false ); } } int GuiTedWin :: nGetTextWindowMidlineInRootCoords( eTeditorType eTeditorTypee ) { // Halfway between baseline and top of ascenders. Position posMidline = nGetTextBaseline( eTeditorTypee ) - ( GuiApp::pGetGuiApp()->nGetFontAscent() / 2 ); Widget widTextWindow; switch ( eTeditorTypee ) { case eConsensusScale : widTextWindow = widScale_; break; case eReadScale : widTextWindow = widScale_; break; case eConsensusBase : widTextWindow = widConsensus_; break; case eFragmentBase : widTextWindow = widFragmentBases_; break; case ePhredCalledBase: widTextWindow = widPhredCalledBases_; break; case eABICalledBase: widTextWindow = widABICalledBases_; break; default: assert( false ); } Position posRootX, posRootY; XtTranslateCoords( widTextWindow, 0, posMidline, &posRootX, &posRootY ); return( posRootY ); } int GuiTedWin :: nRootYCoordsToFormYCoords( const int nRootYCoord ) { Position posFormOriginRootX, posFormOriginRootY; XtTranslateCoords( widForm_, 0, 0, &posFormOriginRootX, &posFormOriginRootY ); return( nRootYCoord - posFormOriginRootY ); } void GuiTedWin :: clearBasePixelPositions() { aBasePixelPositions_.clear(); nLeftMostConsPos_ = nINVALID_CONS_POS; // invalidate } int GuiTedWin :: nPixelXFromConsPos( const int nConsPos ) { return( aBasePixelPositions_[ nConsPos - nLeftMostConsPos_ ] ); } int GuiTedWin :: nConsPosFromPixelX( const int nPixelX ) { int nZeroBasedBaseIndex = nZeroBasedBaseIndexFromPixelX( nPixelX ); int nConsPos = nZeroBasedBaseIndex + nLeftMostConsPos_; return( nConsPos ); } int GuiTedWin :: nZeroBasedBaseIndexFromPixelX( const int nPixelX ) { int nZeroBasedIndex = 0; bool bFound = false; while( !bFound && nZeroBasedIndex < aBasePixelPositions_.length() ) { if ( aBasePixelPositions_[ nZeroBasedIndex ] >= nPixelX ) bFound = true; else ++nZeroBasedIndex; } // handle case in which the pointer is to the right of the rightmost // base if (!bFound) { nZeroBasedIndex = (int)aBasePixelPositions_.length() - 1; return( nZeroBasedIndex ); } // handle case in which the pointer is to the left of the leftmost // base if ( nZeroBasedIndex == 0 ) return( nZeroBasedIndex ); // case in which the pointer is between 2 bases. Pick whichever base it // is closest to. int nBaseToLeftOfPointer = nZeroBasedIndex - 1; int nBaseToRightOfPointer = nZeroBasedIndex; if (nPixelX < nLeftPixelXFromConsPos( nBaseToRightOfPointer + nLeftMostConsPos_ ) ) return( nBaseToLeftOfPointer ); else return( nBaseToRightOfPointer ); } int GuiTedWin :: nLeftPixelXFromConsPos( const int nConsPos ) { int nZeroBasedBaseIndex = nConsPos - nLeftMostConsPos_; if (nZeroBasedBaseIndex == 0) return( 0 ); int nLeftBasePixelX = aBasePixelPositions_[ nZeroBasedBaseIndex - 1]; int nRightBasePixelX = aBasePixelPositions_[ nZeroBasedBaseIndex ]; int nBetweenBasesPixelX = ( nLeftBasePixelX + nRightBasePixelX ) / 2; return( nBetweenBasesPixelX ); } int GuiTedWin :: nRightPixelXFromConsPos( const int nConsPos ) { int nZeroBasedBaseIndex = nConsPos - nLeftMostConsPos_; if ( nZeroBasedBaseIndex == (aBasePixelPositions_.length() - 1) ) return( nGetTraceWindowPixelWidth() - 1 ); int nLeftBasePixelX = aBasePixelPositions_[ nZeroBasedBaseIndex ]; int nRightBasePixelX = aBasePixelPositions_[ nZeroBasedBaseIndex + 1 ]; int nBetweenBasesPixelX = (nLeftBasePixelX + nRightBasePixelX ) / 2; return( nBetweenBasesPixelX ); } void GuiTedWin :: getSavedRangeOfConsensusPositions( int& nConsPosMin, int& nConsPosMax ) { nConsPosMin = nLeftMostConsPos_; nConsPosMax = nLeftMostConsPos_ + (int)aBasePixelPositions_.length() - 1; // if ( nLeftMostConsPos_ == nINVALID_CONS_POS ) { // RWCString soError = "read "; // if ( pTedWinGet() && pTedWinGet()->pLocFragGet() ) { // soError += pTedWinGet()->pLocFragGet()->soGetName(); // } // soError += " is off the screen or cannot be aligned against its traces"; // THROW_ERROR( soError ); // } } void GuiTedWin :: getSavedRangeOfConsensusPositionsOnScreen( int& nConsPosMin, int& nConsPosMax, bool& bPartOfTraceWithoutBases ) { getSavedRangeOfConsensusPositions( nConsPosMin, nConsPosMax ); if ( nConsPosMin == nINVALID_CONS_POS ) { bPartOfTraceWithoutBases = true; return; } bPartOfTraceWithoutBases = false; // There is a possibility that nConsPosMin and nConsPosMax, as returned // by getRangeOfConsensusPositions, are slightly off the screen // (but the division between them and the on-screen base is on screen) if ( pTedWinGet()->pLocFragGet()->nGetPointPosByConsPos( nConsPosMin ) < nLeftEdgePointPosition_ ) ++nConsPosMin; if ( nGetRightEdgePointPosition() < pTedWinGet()->pLocFragGet()->nGetPointPosByConsPos( nConsPosMax ) ) --nConsPosMax; } int GuiTedWin :: nPixelXOfTick( const int nConsPos ) { return( nPixelXFromConsPos( nConsPos ) ); } void GuiTedWin :: guiSetBasePixelPosition( const int nConsPos, const int nPointPosition ) { int nPixelXThisBase = nPixelXFromPoint( nPointPosition ); if (! aBasePixelPositions_.isEmpty() ) { if (nPixelXPreviousBase_ + GuiApp::pGetGuiApp()->nGetFontWidth() > nPixelXThisBase) { nPixelXThisBase = nPixelXPreviousBase_ + GuiApp :: pGetGuiApp()->nGetFontWidth(); } } aBasePixelPositions_.insert( nPixelXThisBase ); assert( (int)aBasePixelPositions_.length() - 1 == nConsPos - nLeftMostConsPos_ ); nPixelXPreviousBase_ = nPixelXThisBase; } bool GuiTedWin :: bGuiTedWinsScrollTogether() { return( pTeditorGet()->bTedWinsScrollTogether() ); } void GuiTedWin :: getWindowInMasterAboutCursor( int& nConsPosToAlign, int& nConsPosLeft, int& nConsPosRight, bool& bInPartOfTraceWithoutBases ) { int nConsPosMinOnScreen; int nConsPosMaxOnScreen; pGetGuiTedWinScrollMaster()->getSavedRangeOfConsensusPositionsOnScreen( nConsPosMinOnScreen, nConsPosMaxOnScreen, bInPartOfTraceWithoutBases ); if ( bInPartOfTraceWithoutBases ) return; LocatedFragment* pMasterLocFrag = pGetGuiTedWinScrollMaster()->pTedWin_->pLocatedFragment_; EditCursor* pEditCursor = pGetTeditor()->pContigWinGet()->pGetEditCursor(); // all this futzing around is so that the window will be completely // contained within the master read and the point to align will // be contained within the window. if ( pEditCursor->bCursorValid() ) { nConsPosToAlign = pEditCursor->nConsPosGet(); if ( ! (nConsPosMinOnScreen <= nConsPosToAlign && nConsPosToAlign <= nConsPosMaxOnScreen ) ) { nConsPosToAlign = ( nConsPosMaxOnScreen + nConsPosMinOnScreen ) / 2; } } else { nConsPosToAlign = ( nConsPosMaxOnScreen + nConsPosMinOnScreen ) / 2; } // This is Phil's suggestion: to have the spacing dependent on // the peaks close to the peak of interest so that the peaks // near the peak of interest all line up. int nHalfWindowSize = 5; // move this many unpadded rather than padded // for getting the window. Contig* pContig = pTedWinGet()->pGetContig(); int nNonPads = 0; bool bFoundRight = false; int nConsPos; for( nConsPos = nConsPosToAlign; nConsPos <= nConsPosMaxOnScreen && !bFoundRight; ++nConsPos ) { if ( !pContig->ntGetCons( nConsPos ).bIsPad() ) { ++nNonPads; if ( nNonPads >= nHalfWindowSize ) { bFoundRight = true; nConsPosRight = nConsPos; } } } if ( !bFoundRight ) { nConsPosRight = nConsPosMaxOnScreen; } // now find left-most (nonpad) base of window int nNonPadsLeft = 0; bool bFoundLeft = false; for( nConsPos = nConsPosToAlign; nConsPos >= nConsPosMinOnScreen && !bFoundLeft; --nConsPos ) { if ( !pContig->ntGetCons( nConsPos ).bIsPad() ) { ++nNonPadsLeft; if ( nNonPadsLeft >= nHalfWindowSize ) { bFoundLeft = true; nConsPosLeft = nConsPos; } } } if ( !bFoundLeft ) { nConsPosLeft = nConsPosMinOnScreen; } // this is the way it used to be, but if there were lots of // pads, most of the window could be pads and this wouldn't // give a very estimate of the trace magnification // nConsPosLeft = nConsPosToAlign - nHalfWindowSize; // nConsPosRight = nConsPosToAlign + nHalfWindowSize; assert( nConsPosLeft <= nConsPosToAlign && nConsPosToAlign <= nConsPosRight ); } Teditor* GuiTedWin :: pGetTeditor() { return( pTedWin_->pTeditor_ ); } void GuiTedWin :: alignTraceToMaster() { // figure out the nConsPos we want to align int nConsPosToAlign; int nConsPosWindowLeft; int nConsPosWindowRight; bool bInPartOfMasterTraceWithoutBases; // finds window about cursor on the master trace getWindowInMasterAboutCursor( nConsPosToAlign, nConsPosWindowLeft, nConsPosWindowRight, bInPartOfMasterTraceWithoutBases ); LocatedFragment* pLocFrag = pTedWin_->pLocatedFragment_; if ( bInPartOfMasterTraceWithoutBases ) { // anomalous case--the user has scrolled the master // trace to part of the trace that has no base calls. Thus // it is impossible to align any other trace to it. Just // make other traces blank. dPixelsPerPoint_ = pGetGuiTedWinScrollMaster()->dPixelsPerPoint_; setHorizontalMagnificationSlider(); LocatedFragment* pLocFragOfMaster = pGetGuiTedWinScrollMaster()->pTedWinGet()->pLocFragGet(); if ( pLocFragOfMaster->nGetAlignStart() < pLocFrag->nGetAlignStart() ) { screenBlackAndScrollBarAtFarLeft(); } else { screenBlackAndScrollBarAtFarRight(); } return; } if ( pLocFrag->bIsInRead( nConsPosToAlign ) && bIntersect( nConsPosWindowLeft, nConsPosWindowRight, pLocFrag->nGetAlignStart(), pLocFrag->nGetAlignEnd(), nConsPosWindowLeft, nConsPosWindowRight ) ) { int nPointPosLeftSlave = pLocFrag->nGetPointPosByConsPos( nConsPosWindowLeft ); int nPointPosRightSlave = pLocFrag->nGetPointPosByConsPos( nConsPosWindowRight ); LocatedFragment* pLocFragOfMaster = pGetGuiTedWinScrollMaster()->pTedWinGet()->pLocFragGet(); int nPointPosLeftMaster = pLocFragOfMaster->nGetPointPosByConsPos( nConsPosWindowLeft ); int nPointPosRightMaster = pLocFragOfMaster->nGetPointPosByConsPos( nConsPosWindowRight ); // cannot always use the following to get the pixel separation // because there might be a bunch of pads in a row and thus the // letters will be moved over from their peaks so as to make // them legible and we want the other traces lined up with the master // trace and not the master bases: // int nPixelOfMasterLeft = // pGetGuiTedWinScrollMaster()->nPixelXFromConsPos( nConsPosWindowLeft ); // int nPixelOfMasterRight = // pGetGuiTedWinScrollMaster()->nPixelXFromConsPos( nConsPosWindowRight ); int nMasterPixelSeparation = ( nPointPosRightMaster - nPointPosLeftMaster ) * pGetGuiTedWinScrollMaster()->dPixelsPerPoint_; if ( nMasterPixelSeparation != 0 && nPointPosRightSlave != nPointPosLeftSlave ) { dPixelsPerPoint_ = ( (double) nMasterPixelSeparation ) / ( (double) nPointPosRightSlave - (double) nPointPosLeftSlave ); } else { dPixelsPerPoint_ = pGetGuiTedWinScrollMaster()->dPixelsPerPoint_; } // now make the cursor consensus position base align with // that in the master trace int nPixelOfAlignedBase = pGetGuiTedWinScrollMaster()->nPixelXFromConsPos( nConsPosToAlign ); double dLeftEdgePointPosition = (double) pLocFrag->nGetPointPosByConsPos( nConsPosToAlign ) - (double) nPixelOfAlignedBase / dPixelsPerPoint_; // round if ( dLeftEdgePointPosition > 0 ) nLeftEdgePointPosition_ = dLeftEdgePointPosition + 0.5; else nLeftEdgePointPosition_ = dLeftEdgePointPosition - 0.5; // need to do stuff with sliders setHorizontalMagnificationSlider(); pTedWin_->setBasePixelPositions(); // careful! Even though the rightmost base is in range, the rightmost // point at this magnification may be out of range. Thus don't move // the scrollbar over too far if ( nGetRightEdgePointPosition() <= (pTedWin_->nGetNumberOfPoints() - 1) ) setScrollBarPositionAndResizeSlider(); else setScrollBarAtMax(); } else { // if this read does not intersect this alignment point, then do a // very half-hearted job of aligning it. Notice I am not // even trying to squeeze/stretch it to fit. I think this is // justified since the user is not interested in that read // since the user has the cursor on a position that doesn't // exist in this read. I'm a little worried, however, that this might // happen: // ------x------------ master, x is cursor // ----------- (slave) // but due to the imprecise squeeze/stretch of the slave trace, it // looks like this: // ------x------------ master, x is cursor // - - - - - - - - - - - (slave) // so it looks as though it *does* intersect the cursor. Let's // see in practice. dPixelsPerPoint_ = pGetGuiTedWinScrollMaster()->dPixelsPerPoint_; setHorizontalMagnificationSlider(); int nMasterReadConsPosLeft; int nMasterReadConsPosRight; pGetGuiTedWinScrollMaster()->getSavedRangeOfConsensusPositionsOnScreen( nMasterReadConsPosLeft, nMasterReadConsPosRight, bInPartOfMasterTraceWithoutBases ); // should have checked for this already above assert( !bInPartOfMasterTraceWithoutBases ); // if this read doesn't overlap the master read at all, // I'm not going to show it. Could be improved in following case: // ---x------- (master) (x is cursor) // ---------- (slave) // but I believe this comes up very rarely and people aren't // interested in the slave since they don't have their cursor there. if ( pLocFrag->nGetAlignEnd() < nMasterReadConsPosLeft ) { screenBlackAndScrollBarAtFarRight(); } else if ( nMasterReadConsPosRight < pLocFrag->nGetAlignStart() ) { screenBlackAndScrollBarAtFarLeft(); } else { // so some of the read must be on the screen and overlap // the master read int nIntersectConsPosLeft; int nIntersectConsPosRight; assert( bIntersect( nMasterReadConsPosLeft, nMasterReadConsPosRight, pLocFrag->nGetAlignStart(), pLocFrag->nGetAlignEnd(), nIntersectConsPosLeft, nIntersectConsPosRight ) ); // which point of this window is closest to the cursor? Align // that point with the master trace. if ( ABS( nConsPosToAlign - nIntersectConsPosLeft ) < ABS( nConsPosToAlign - nIntersectConsPosRight ) ) nConsPosToAlign = nIntersectConsPosLeft; else nConsPosToAlign = nIntersectConsPosRight; // what pixel is this read at in the master trace? We // will put the corresponding base of this (slave) trace // at the same location int nPixelOfConsPosToAlign = pGetGuiTedWinScrollMaster()->nPixelXFromConsPos( nConsPosToAlign ); // then simply convert this to find the point position of the slave // read at the left edge nLeftEdgePointPosition_ = pLocFrag->nGetPointPosByConsPos( nConsPosToAlign ) - nPixelOfConsPosToAlign / dPixelsPerPoint_; pTedWin_->setBasePixelPositions(); // Note: since the slave trace didn't intersect the cursor, // it have an end on the screen. So its scroll bar will // be at one max or the other if ( nLeftEdgePointPosition_ <= 0 ) setScrollBarPosition( 0 ); else setScrollBarAtMax(); } } // this doesn't always need to be done, especially if the trace // isn't visible. It might help performance a little // if we could tell if it was off screen and not draw in that case. pTedWin_->drawBasesAndTraces( false ); } void GuiTedWin :: setHorizontalMagnificationSlider() { if ( pGuiTeditorGet()->bShowTracesInScrollingWindow_ ) return; int nHorizScaleValue = dPixelsPerPoint_ * nHorizontalScaleInit / dPixelsPerPointInit; XtVaSetValues( widHorizontalScale_, XmNvalue, nHorizScaleValue, NULL); } void GuiTedWin :: setHorizontalMagnification( const double dPixelsPerPoint ) { dPixelsPerPoint_ = dPixelsPerPoint; setHorizontalMagnificationSlider(); } GuiTedWin :: ~GuiTedWin() { XtDestroyWidget( widFrame_ ); } void GuiTedWin :: setScrollBarAtMax() { if (!bShowScrollbar_ ) return; int nMaxScrollBarPosition = pTedWin_->nGetNumberOfPoints() - nGetTraceWindowPointsWide(); // all this must be done at once to avoid getting the error message: //Warning: // Name: scrollbar // Class: XmScrollBar // The specified scrollbar value is greater than the maximum // scrollbar value minus the scrollbar slider size. XtVaSetValues( widScrollBar_, XmNsliderSize, nGetTraceWindowPointsWide(), XmNpageIncrement, nGetTraceWindowPointsWide() - 1, XmNvalue, nMaxScrollBarPosition, NULL ); } // used when changing horizontal magnification and scrolling under program // control at the same time void GuiTedWin :: setScrollBarPositionAndResizeSlider() { if (!bShowScrollbar_ ) return; // all this must be done at once to avoid getting the error message: //Warning: // Name: scrollbar // Class: XmScrollBar // The specified scrollbar value is greater than the maximum // scrollbar value minus the scrollbar slider size. XtVaSetValues( widScrollBar_, XmNsliderSize, nGetTraceWindowPointsWide(), XmNpageIncrement, nGetTraceWindowPointsWide() - 1, XmNvalue, nLeftEdgePointPosition_, NULL ); } void GuiTedWin :: screenBlackAndScrollBarAtFarRight() { setScrollBarAtMax(); int nAnyPointPositionOffEndOfTrace = pTedWin_->nGetNumberOfPoints() + 2 *nGetTraceWindowPointsWide(); setLeftEdgePointPosition( nAnyPointPositionOffEndOfTrace ); pTedWin_->clearTedWin(); } void GuiTedWin :: screenBlackAndScrollBarAtFarLeft() { setScrollBarPosition( 0 ); int nAnyPointPositionOffLeftEndOfTrace = -2 * nGetTraceWindowPointsWide(); setLeftEdgePointPosition( nAnyPointPositionOffLeftEndOfTrace ); pTedWin_->clearTedWin(); } void GuiTedWin :: guiDrawVerticalLineThroughTraces( const int nPointPos ) { int nPixelX = nPixelXFromPoint( nPointPos ); int nPixelY = nGetTraceWindowHeight(); XDrawLine( XtDisplay( widTraces_ ), XtWindow( widTraces_ ), pGetGuiColorTextForConsensusCursor()->gcGet(), nPixelX, 0, nPixelX, nPixelY ); } void GuiTedWin :: activateUndoButton() { XtVaSetValues( widUndoButton_, XmNsensitive, True, NULL ); } void GuiTedWin :: deactivateUndoButton() { XtVaSetValues( widUndoButton_, XmNsensitive, False, NULL ); } void GuiTedWin :: alignScrollingWindowConsensusToThisTrace() { widConsensus_ = pTeditorGet()->pGuiTeditor_->widConsensus_; widShowAllTracesConsensusScale_ = pTeditorGet()->pGuiTeditor_->widConsensusScale_; bShowConsensusLine_ = true; } void GuiTedWin :: grabInputFocus() { XmProcessTraversal( widFragmentBases_, XmTRAVERSE_CURRENT ); } void GuiTedWin :: maybeChangeTracesDashedOrNot( const bool bDashed ) { if ( bTracesGCSetToDashed_ == bDashed ) return; bTracesGCSetToDashed_ = bDashed; int nLineStyle = ( bDashed ? LineOnOffDash : LineSolid ); // make traces dashed XGCValues xgcvalues; unsigned long valuemask = GCLineWidth | GCCapStyle | GCJoinStyle; assert( XGetGCValues( XtDisplay( GuiApp::pGetGuiApp()->widGetTopLevel() ), pGuiColorTextA_->gcGet(), valuemask, &xgcvalues ) ); XSetLineAttributes( XtDisplay( GuiApp::pGetGuiApp()->widGetTopLevel() ), pGuiColorTextA_->gcGet(), xgcvalues.line_width, nLineStyle, xgcvalues.cap_style, xgcvalues.join_style ); assert( XGetGCValues( XtDisplay( GuiApp::pGetGuiApp()->widGetTopLevel() ), pGuiColorTextC_->gcGet(), valuemask, &xgcvalues ) ); XSetLineAttributes( XtDisplay( GuiApp::pGetGuiApp()->widGetTopLevel() ), pGuiColorTextC_->gcGet(), xgcvalues.line_width, nLineStyle, xgcvalues.cap_style, xgcvalues.join_style ); assert( XGetGCValues( XtDisplay( GuiApp::pGetGuiApp()->widGetTopLevel() ), pGuiColorTextG_->gcGet(), valuemask, &xgcvalues ) ); XSetLineAttributes( XtDisplay( GuiApp::pGetGuiApp()->widGetTopLevel() ), pGuiColorTextG_->gcGet(), xgcvalues.line_width, nLineStyle, xgcvalues.cap_style, xgcvalues.join_style ); assert( XGetGCValues( XtDisplay( GuiApp::pGetGuiApp()->widGetTopLevel() ), pGuiColorTextT_->gcGet(), valuemask, &xgcvalues ) ); XSetLineAttributes( XtDisplay( GuiApp::pGetGuiApp()->widGetTopLevel() ), pGuiColorTextT_->gcGet(), xgcvalues.line_width, nLineStyle, xgcvalues.cap_style, xgcvalues.join_style ); }