/***************************************************************************** # 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 "guiDigestProblemNavigator.h" #include "handleWindowManagerDelete2.h" #include #include #include #include "hp_exception_kludge.h" #include "guiDisplayDigest.h" #include #include "popupErrorMessage.h" #include "assert.h" void cbGuiDigestProblemNavigator( Widget wid, XtPointer pClientData, XtPointer pCallData ) { guiDigestProblemNavigator* pGuiDigestProblemNavigator = (guiDigestProblemNavigator*) pClientData; TRY_CATCH_WRAPPER( pGuiDigestProblemNavigator->userPushedButtonOrClicked( wid ); ); } void cbDismiss( Widget wid, XtPointer pClientData, XtPointer pCallData ) { TRY_CATCH_WRAPPER( guiDigestProblemNavigator* pGuiDigestProblemNavigator = (guiDigestProblemNavigator*) pClientData; delete pGuiDigestProblemNavigator; ); } guiDigestProblemNavigator :: guiDigestProblemNavigator( guiDisplayDigest* pGuiDisplayDigest ) : pGuiDisplayDigest_( pGuiDisplayDigest ), bAlreadyZoomedIn_( false ) { pDigestForOneEnzyme_ = pGuiDisplayDigest_->pCurrentlyDisplayedDigest_; widPopupShell_ = XtVaCreatePopupShell( "guiDigestProblemNavigator", topLevelShellWidgetClass, pGuiDisplayDigest_->widPopupShell_, XmNtitle, "Restriction Digest Problems", XmNnoResize, False, XmNautoUnmanage, False, XmNtransient, False, XmNdeleteResponse, XmDO_NOTHING, NULL ); handleWindowManagerDelete2( widPopupShell_, cbDismiss, this ); Widget widForm = XtVaCreateManagedWidget( "form", xmFormWidgetClass, widPopupShell_, XmNshadowThickness, 0, XmNborderWidth, 0, NULL ); const int nWidthInColumns = 30; RWCString soHeadings = "size type"; widHeadingLines_ = XtVaCreateManagedWidget( "heading_lines", xmTextWidgetClass, widForm, XmNtopAttachment, XmATTACH_FORM, XmNleftAttachment, XmATTACH_FORM, XmNrightAttachment, XmATTACH_FORM, XmNrows, 1, XmNeditable, False, XmNcursorPositionVisible, False, XmNtraversalOn, False, XmNeditMode, XmMULTI_LINE_EDIT, XmNcolumns, nWidthInColumns, XmNvalue, soHeadings.data(), NULL ); // buttons from left to right are: // Go, Prev, Next, Save, Dismiss const int nNumberOfButtons = 5; int nButtonLocationLeft[ nNumberOfButtons ]; int nButtonLocationRight[ nNumberOfButtons ]; const int nSpacingBetweenButtons = 1; double dWidthOfAButton = ( 100 - nSpacingBetweenButtons * ( nNumberOfButtons + 1 ) ) / (double) nNumberOfButtons; for( int nButton = 0; nButton < nNumberOfButtons; ++nButton ) { nButtonLocationLeft[ nButton ] = nSpacingBetweenButtons* ( nButton + 1 ) + (int) ( dWidthOfAButton * nButton ); nButtonLocationRight[ nButton ] = nSpacingBetweenButtons * ( nButton + 1 ) + (int) ( dWidthOfAButton * ( nButton + 1 ) ); } #define makeButton( WID, NAME, NUMBER, CALLBACK ) \ WID = XtVaCreateManagedWidget( \ NAME, \ xmPushButtonWidgetClass, \ widForm, \ XmNbottomAttachment, XmATTACH_WIDGET, \ XmNbottomOffset, 10, \ XmNleftAttachment, XmATTACH_POSITION, \ XmNleftPosition, nButtonLocationLeft[NUMBER], \ XmNrightAttachment, XmATTACH_POSITION,\ XmNrightPosition, nButtonLocationRight[NUMBER], \ XmNtraversalOn, False, \ NULL ); \ \ XtAddCallback( WID, \ XmNactivateCallback, \ CALLBACK, \ this ); // So // makeButton( widGoButton_, "Go", 0, cbGuiDigestProblemNavigator ); // expands to: // // widGoButton_ = XtVaCreateManagedWidget( // "Go", // xmPushButtonWidgetClass, // widForm, // XmNbottomAttachment, XmATTACH_WIDGET, // XmNbottomOffset, 10, // XmNleftAttachment, XmATTACH_POSITION, // XmNleftPosition, nButtonLocationLeft[0], // XmNrightAttachment, XmATTACH_POSITION, // XmNrightPosition, nButtonLocationRight[0], // XmNtraversalOn, False, // NULL ); // XtAddCallback( widGoButton_, // XmNactivateCallback, // cbGuiDigestProblemNavigator, // this ); makeButton( widGoButton_, "Go", 0, cbGuiDigestProblemNavigator ); makeButton( widPrevButton_, "Prev", 1, cbGuiDigestProblemNavigator ); makeButton( widNextButton_, "Next", 2, cbGuiDigestProblemNavigator ); makeButton( widSaveButton_, "Save", 3, cbGuiDigestProblemNavigator ); makeButton( widDismissButton_, "Dismiss", 4, cbDismiss ); // aProblemList_ will be empty since we are in the ctor pGuiDisplayDigest_->createProblemList( &aProblemList_ ); XmString* pXmStrings = (XmString*) XtMalloc( sizeof( XmString ) * aProblemList_.length() ); int nProblemFrag; for( nProblemFrag = 0; nProblemFrag < aProblemList_.length(); ++nProblemFrag ) { restrictionFragment* pProblemFrag = aProblemList_[ nProblemFrag ]; pXmStrings[ nProblemFrag ] = XmStringCreateSimple( pProblemFrag->soGetProblemDescription() ); } Arg aArg[30]; int nArgs = 0; XtSetArg( aArg[nArgs], XmNselectionPolicy, XmBROWSE_SELECT); ++nArgs; XtSetArg( aArg[nArgs], XmNvisibleItemCount, 20 ); ++nArgs; XtSetArg( aArg[nArgs], XmNleftAttachment, XmATTACH_FORM); ++nArgs; XtSetArg( aArg[nArgs], XmNrightAttachment, XmATTACH_FORM); ++nArgs; XtSetArg( aArg[nArgs], XmNbottomAttachment, XmATTACH_WIDGET); ++nArgs; XtSetArg( aArg[nArgs], XmNbottomWidget, widGoButton_ ); ++nArgs; XtSetArg( aArg[nArgs], XmNbottomOffset, 10 ); ++nArgs; XtSetArg( aArg[nArgs], XmNtopAttachment, XmATTACH_WIDGET ); ++nArgs; XtSetArg( aArg[nArgs], XmNtopWidget, widHeadingLines_ ); ++nArgs; XtSetArg( aArg[nArgs], XmNitems, pXmStrings ); ++nArgs; XtSetArg( aArg[nArgs], XmNitemCount, aProblemList_.length() ); ++nArgs; XtSetArg( aArg[nArgs], XmNtraversalOn, False ); ++nArgs; widList_ = XmCreateScrolledList( widForm, "list", aArg, nArgs ); XtManageChild( widList_ ); XtAddCallback( widList_, XmNdefaultActionCallback, cbGuiDigestProblemNavigator, this ); // clean up for( nProblemFrag = 0; nProblemFrag < aProblemList_.length(); ++nProblemFrag ) { XmStringFree( pXmStrings[ nProblemFrag ] ); } XtFree( (char*) pXmStrings ); XtPopup( widPopupShell_, XtGrabNone ); } // value returned when nothing is selected static const int digestNavigatorNoSelection = -1; void guiDigestProblemNavigator :: userPushedButtonOrClicked( const Widget wid ) { if ( aProblemList_.length() == 0 ) { popupErrorMessage( "This command doesn't make sense with an empty list" ); return; } if ( wid == widSaveButton_ ) { saveNavigatorList(); return; } int nCurIndex; int* pPositionList; int nNumberOfSelectedItems; if ( XmListGetSelectedPos( widList_, &pPositionList, &nNumberOfSelectedItems ) ) { assert( nNumberOfSelectedItems == 1 ); nCurIndex = pPositionList[0]; XtFree( (char*) pPositionList ); } else nCurIndex = digestNavigatorNoSelection; int nGotoIndex; if ( wid == widGoButton_ || wid == widList_ ) { if ( ( wid == widGoButton_ ) && ( nCurIndex == digestNavigatorNoSelection ) ) { popupErrorMessage( "First click on an item before clicking Go" ); return; } nGotoIndex = nCurIndex; } else if ( wid == widNextButton_ ) { // which one is next? if ( nCurIndex == digestNavigatorNoSelection ) { nGotoIndex = 1; // go to first one } else if ( nCurIndex < nGetMaxIndex() ) nGotoIndex = nCurIndex + 1; else nGotoIndex = nCurIndex; } else if ( wid == widPrevButton_ ) { // which one is previous? if ( nCurIndex == digestNavigatorNoSelection || nCurIndex == 1 ) nGotoIndex = 1; else nGotoIndex = nCurIndex - 1; } else assert( false ); assert( nGotoIndex != digestNavigatorNoSelection ); // are we currently in view? If not, scroll the list. int nTopIndex; int nVisibleItems; XtVaGetValues( widList_, XmNtopItemPosition, &nTopIndex, XmNvisibleItemCount, &nVisibleItems, NULL ); int nBottomIndex = nTopIndex + nVisibleItems - 1; if ( nGotoIndex < nTopIndex ) XmListSetPos( widList_, nGotoIndex ); else if ( nGotoIndex > nBottomIndex ) XmListSetBottomPos( widList_, nGotoIndex ); // highlight the item in the list XmListSelectPos( widList_, nGotoIndex, True ); // now highlight the fragment in the display if ( pDigestForOneEnzyme_ != pGuiDisplayDigest_->pCurrentlyDisplayedDigest_ ) { popupErrorMessage( "You changed enzymes in the display so this problem list if no longer valid" ); return; } // subtract 1 to get back to 0-based indices restrictionFragment* pResFrag = aProblemList_[ nGotoIndex - 1 ]; if ( !bAlreadyZoomedIn_ ) { bAlreadyZoomedIn_ = true; pGuiDisplayDigest_->zoomInForNavigate(); } pGuiDisplayDigest_->highlightFragment( pResFrag ); } guiDigestProblemNavigator :: ~guiDigestProblemNavigator() { XtPopdown( widPopupShell_ ); XtDestroyWidget( widPopupShell_ ); } void guiDigestProblemNavigator :: saveNavigatorList() { }