/***************************************************************************** # 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 #include #include "guiapp.h" #include using namespace std; #include #include "rwcstring.h" #include "rwcregexp.h" #include "bIsNumericMaybeWithWhitespace.h" #include "assert.h" #include "guiGetTagType.h" #include "tagTypes.h" #include #include "handleWindowManagerDelete.h" #include #include "hp_exception_kludge.h" #include "popupErrorMessage.h" #include "consedParameters.h" #include "popupErrorMessage2.h" static void cbUserChangedBetweenConsensusAndReads( Widget wid, XtPointer pClientData, XtPointer pCallData ) { guiGetTagType* pGuiGetTagType = (guiGetTagType*) pClientData; TRY_CATCH_WRAPPER( pGuiGetTagType->userChangedBetweenConsensusAndReads() ); } static void cbChooseTagTypes( Widget widCallback, XtPointer clientData, XtPointer call_data ) { guiGetTagType* pGuiGetTagType = (guiGetTagType* )clientData; XmListCallbackStruct* pXmListCallbackStruct = (XmListCallbackStruct*) call_data; TRY_CATCH_WRAPPER( pGuiGetTagType->guiChoseTagType( widCallback, pXmListCallbackStruct ); ); } static void cbChooseMultipleTagTypes( Widget widCallback, XtPointer clientData, XtPointer call_data ) { guiGetTagType* pGuiGetTagType = (guiGetTagType* )clientData; TRY_CATCH_WRAPPER( pGuiGetTagType->guiChoseMultipleTagTypes( widCallback ); ); } static void cbChooseTagTypesSingleClick( Widget widCallback, XtPointer client_data, XtPointer call_data ) { XmListCallbackStruct* pXmListCallbackStruct = (XmListCallbackStruct*) call_data; guiGetTagType* pGuiGetTagType = (guiGetTagType*) client_data; TRY_CATCH_WRAPPER( pGuiGetTagType->setCallbackInfoForSingleSelection( pXmListCallbackStruct ); ); } static void cbClearUserSelections( Widget widCallback, XtPointer pClientData, XtPointer pCallData ) { guiGetTagType* pGuiGetTagType = (guiGetTagType*) pClientData; TRY_CATCH_WRAPPER( pGuiGetTagType->clearUserSelections() ); } static void cbUserPushedSelectAllTagsWithStringButton( Widget widCallback, XtPointer pClientData, XtPointer pCallData ) { guiGetTagType* pGuiGetTagType = (guiGetTagType*) pClientData; TRY_CATCH_WRAPPER( pGuiGetTagType->userPushedSelectAllTagsWithStringButton() ); } void guiGetTagType :: popupBoxAndWaitForUserToSelectTagType( RWCString& soTagType, bool& bUserPushedCancel, const bool bOnlyShowTagTypesThatCanBeCreatedBySwiping, const tagType::readOrConsensusType readOrConsensusType, const bool bAllowUserToEnterCommentAndContigName, RWCString& soComment, RWCString& soContigName ) { bAllowUserToEnterCommentAndContigName_ = bAllowUserToEnterCommentAndContigName; int nArgs; Arg aArg[50]; widPopupShell_ = XtVaCreatePopupShell( "Tag", topLevelShellWidgetClass, GuiApp::pGetGuiApp()->widGetTopLevel(), XmNtitle, (char*) "Select Tag Type", XmNnoResize, False, XmNautoUnmanage, False, XmNtransient, False, XmNdeleteResponse, XmDO_NOTHING, XmNmwmDecorations, MWM_DECOR_ALL | MWM_DECOR_MENU | MWM_DECOR_MINIMIZE | MWM_DECOR_MAXIMIZE, NULL ); handleWindowManagerDelete( widPopupShell_ ); // the immediate child of the application shell is a // main window Widget widMainWin = XtVaCreateManagedWidget("mainwin", xmMainWindowWidgetClass, widPopupShell_, XmNancestorSensitive, True, NULL ); // // create the form widget // nArgs = 0; XtSetArg(aArg[nArgs],XmNshadowThickness,0); nArgs++; XtSetArg(aArg[nArgs],XmNborderWidth,0); nArgs++; Widget widForm = XmCreateForm(widMainWin, "form", aArg, nArgs); XtManageChild(widForm); XmString xmsWarningMessage = XmStringCreateLtoR( "YOU MUST RESPOND TO THIS\nBEFORE DOING ANYTHING ELSE", XmFONTLIST_DEFAULT_TAG ); Widget widWarningLabel = XtVaCreateManagedWidget( "label", xmLabelWidgetClass, widForm, XmNleftAttachment, XmATTACH_FORM, XmNrightAttachment, XmATTACH_FORM, XmNtopAttachment, XmATTACH_FORM, XmNlabelString, xmsWarningMessage, XmNalignment, XmALIGNMENT_CENTER, NULL ); XmStringFree( xmsWarningMessage ); widOKButton_ = XtVaCreateManagedWidget( "OK", xmPushButtonWidgetClass, widForm, XmNbottomAttachment, XmATTACH_FORM, XmNbottomOffset, 10, XmNleftAttachment, XmATTACH_POSITION, XmNleftPosition, 35, XmNrightAttachment, XmATTACH_POSITION, XmNrightPosition, 45, NULL ); XtAddCallback(widOKButton_, XmNactivateCallback, (XtCallbackProc )cbChooseTagTypes, this); widCancelButton_ = XtVaCreateManagedWidget( "Cancel", xmPushButtonWidgetClass, widForm, XmNbottomAttachment, XmATTACH_FORM, XmNbottomOffset, 10, XmNleftAttachment, XmATTACH_POSITION, XmNleftPosition, 55, XmNrightAttachment, XmATTACH_POSITION, XmNrightPosition, 65, NULL ); XtAddCallback(widCancelButton_, XmNactivateCallback, (XtCallbackProc )cbChooseTagTypes, this); Widget widBottomOfListConnectsToThis; if ( bAllowUserToEnterCommentAndContigName ) { nArgs = 0; XtSetArg( aArg[nArgs], XmNbottomAttachment, XmATTACH_WIDGET ); ++nArgs; XtSetArg( aArg[nArgs], XmNbottomWidget, widOKButton_ ); ++nArgs; XtSetArg( aArg[nArgs], XmNbottomOffset, 10 ); ++nArgs; XtSetArg( aArg[nArgs], XmNleftAttachment, XmATTACH_FORM ); ++nArgs; XtSetArg( aArg[nArgs], XmNrightAttachment, XmATTACH_FORM ); ++nArgs; XtSetArg( aArg[nArgs], XmNrows, 3 ); ++nArgs; XtSetArg( aArg[nArgs], XmNeditMode, XmMULTI_LINE_EDIT ); ++nArgs; XtSetArg( aArg[nArgs], XmNeditable, True ); ++nArgs; XtSetArg( aArg[nArgs], XmNcursorPositionVisible, True ); ++nArgs; XtSetArg( aArg[nArgs], XmNtraversalOn, True ); ++nArgs; widComment_ = XmCreateScrolledText( widForm, "comment", aArg, nArgs ); XtManageChild( widComment_ ); Widget widCommentLabel = XtVaCreateManagedWidget( "Comment:", xmLabelWidgetClass, widForm, XmNbottomAttachment, XmATTACH_WIDGET, XmNbottomWidget, widComment_, XmNleftAttachment, XmATTACH_FORM, NULL ); widContigNameLabel_ = XtVaCreateManagedWidget( "Contig Name:", xmLabelWidgetClass, widForm, XmNbottomAttachment, XmATTACH_WIDGET, XmNbottomWidget, widCommentLabel, XmNleftAttachment, XmATTACH_FORM, XmNsensitive, False, NULL ); widContigName_ = XtVaCreateManagedWidget( "Contig Name", xmTextWidgetClass, widForm, XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET, XmNbottomWidget, widContigNameLabel_, XmNleftAttachment, XmATTACH_WIDGET, XmNleftWidget, widContigNameLabel_, XmNleftOffset, 10, XmNsensitive, False, NULL ); widBottomOfListConnectsToThis = widContigName_; } else widBottomOfListConnectsToThis = widOKButton_; int nTagTypes = tagTypes::pGetTagTypes()->nGetNumberOfTagTypes(); // nTagTypes is perhaps longer than needed XmStringTable ppXtString = (XmStringTable) XtMalloc( nTagTypes * sizeof( XmString ) ); // nTagTypes is perhaps longer than needed // list items start with index 1 aTranslateTagTypeIndexFromListItemIndex_.reshape( nTagTypes + 1, 0 ); // initial value bool bFoundLastUsedTagType = false; int nListIndexOfLastUsedTagType; int nTagTypesDisplayed = 0; for( int nTagType = 0; nTagType < nTagTypes; ++nTagType ) { RWCString soTagType = tagTypes::pGetTagTypes()->soGetTagType( nTagType ); if (bOnlyShowTagTypesThatCanBeCreatedBySwiping ) { if ( ! tagTypes::pGetTagTypes()->bTagTypeCanBeCreatedBySwiping( nTagType ) ) continue; } // always exclude tagsOverlap since we don't navigate for this (these // tags don't exist) and we don't add this tag type if (soTagType == "tagsOverlap" ) continue; tagType::readOrConsensusType rc = tagTypes::pGetTagTypes()->rcGetTagReadOrConsensusType( nTagType ); if ( !( rc & readOrConsensusType ) ) // notice bitwise compare continue; ppXtString[ nTagTypesDisplayed ] = XmStringCreateLocalized( (char*) soTagType.data() ); ++nTagTypesDisplayed; aTranslateTagTypeIndexFromListItemIndex_[ nTagTypesDisplayed ] = nTagType; if ( soTagType == pCP->soDefaultTagType_ ) { bFoundLastUsedTagType = true; nListIndexOfLastUsedTagType = nTagTypesDisplayed; } } nArgs = 0; XtSetArg( aArg[nArgs], XmNbottomAttachment, XmATTACH_WIDGET ); ++nArgs; XtSetArg( aArg[nArgs], XmNbottomWidget, widBottomOfListConnectsToThis ); ++nArgs; XtSetArg( aArg[nArgs], XmNtopAttachment, XmATTACH_WIDGET ); ++nArgs; XtSetArg( aArg[nArgs], XmNtopWidget, widWarningLabel ); ++nArgs; XtSetArg( aArg[nArgs], XmNleftAttachment, XmATTACH_FORM ); ++nArgs; XtSetArg( aArg[nArgs], XmNrightAttachment, XmATTACH_FORM ); ++nArgs; XtSetArg( aArg[nArgs], XmNvisibleItemCount, 30 ); ++nArgs; XtSetArg( aArg[nArgs], XmNtraversalOn, True ); ++nArgs; XtSetArg( aArg[nArgs], XmNitems, ppXtString ); ++nArgs; XtSetArg( aArg[nArgs], XmNitemCount, nTagTypesDisplayed ); ++nArgs; XtSetArg( aArg[nArgs], XmNselectionPolicy, XmSINGLE_SELECT ); ++nArgs; widTagTypesList_ = XmCreateScrolledList( widForm, "tagTypes", aArg, nArgs ); // if the user previously used a tag type, highlight it so (s)he can // use it again XtManageChild( widTagTypesList_ ); if ( bFoundLastUsedTagType ) { XmListSelectPos( widTagTypesList_, nListIndexOfLastUsedTagType, False ); // if True, invokes the selection callback // make sure that the selected item is visible int nTopIndex; int nVisibleItems; XtVaGetValues( widTagTypesList_, XmNtopItemPosition, &nTopIndex, XmNvisibleItemCount, &nVisibleItems, NULL ); if ( nListIndexOfLastUsedTagType > nTopIndex + nVisibleItems - 1 ) XmListSetBottomPos( widTagTypesList_, nListIndexOfLastUsedTagType ); // I don't think we need to worry about the selected item being // above the top of the list since I believe the first item // of the list will be the top visible item. // pretend the user already single clicked on this item XmListCallbackStruct XmListCallbackStructt; XmListCallbackStructt.reason = XmCR_SINGLE_SELECT; XmListCallbackStructt.item_position = nListIndexOfLastUsedTagType; setCallbackInfoForSingleSelection( &XmListCallbackStructt ); } XtAddCallback( widTagTypesList_, XmNdefaultActionCallback, cbChooseTagTypes, this ); XtAddCallback( widTagTypesList_, XmNsingleSelectionCallback, cbChooseTagTypesSingleClick, this ); XtPopup( widPopupShell_, XtGrabExclusive ); XmProcessTraversal( widTagTypesList_, XmTRAVERSE_CURRENT ); // wait until user answers the question--don't let him do anything else! user_must_answer_question_correctly: bBlockApplication_ = true; // xt callback must clear XEvent xevent; while( bBlockApplication_ ) { XtAppNextEvent( GuiApp::pGetGuiApp()->ctxGetAppContext(), &xevent); XtDispatchEvent( &xevent); } if (widWhichButtonGotPushed_ == widCancelButton_ ) bUserPushedCancel = true; else bUserPushedCancel = false; soTagType = soTagTypeSelected_; if ( bAllowUserToEnterCommentAndContigName && !bUserPushedCancel ) { char* szComment = XmTextGetString( widComment_ ); soComment = szComment; XtFree( szComment ); char* szContigName = XmTextGetString( widContigName_ ); soContigName = szContigName; XtFree( szContigName ); if ( soTagType == "comment" && soComment.isNull() ) { popupErrorMessage( "if you want to add a comment tag, you must also enter a comment" ); goto user_must_answer_question_correctly; } if ( soTagType == "contigName" && soContigName.isNull() ) { popupErrorMessage( "if you want to add a contigName tag, you must also enter a contigName" ); goto user_must_answer_question_correctly; } } pCP->soDefaultTagType_ = soTagType; XtPopdown( widPopupShell_ ); XtDestroyWidget( widPopupShell_ ); } void guiGetTagType :: popupBoxAndWaitForUserToSelectMultipleTagTypes( // RWCString& soTagType, RWTValOrderedVector& aTagTypesToReturn, bool& bUserPushedCancel ) { aTagTypesToReturn.soName_ = "aTagTypesToReturn"; bAllowUserToEnterCommentAndContigName_ = false; int nArgs; Arg aArg[50]; widPopupShell_ = XtVaCreatePopupShell( "Tag", topLevelShellWidgetClass, GuiApp::pGetGuiApp()->widGetTopLevel(), XmNtitle, (char*) "Select Tag Type", XmNnoResize, False, XmNautoUnmanage, False, XmNtransient, False, XmNdeleteResponse, XmDO_NOTHING, XmNmwmDecorations, MWM_DECOR_ALL | MWM_DECOR_MENU | MWM_DECOR_MINIMIZE | MWM_DECOR_MAXIMIZE, NULL ); handleWindowManagerDelete( widPopupShell_ ); // the immediate child of the application shell is a // main window Widget widMainWin = XtVaCreateManagedWidget("mainwin", xmMainWindowWidgetClass, widPopupShell_, XmNancestorSensitive, True, NULL ); // // create the form widget // nArgs = 0; XtSetArg(aArg[nArgs],XmNshadowThickness,0); nArgs++; XtSetArg(aArg[nArgs],XmNborderWidth,0); nArgs++; Widget widForm = XmCreateForm(widMainWin, "form", aArg, nArgs); XtManageChild(widForm); XmString xmsWarningMessage = XmStringCreateLtoR( "YOU MUST RESPOND TO THIS\nBEFORE DOING ANYTHING ELSE", XmFONTLIST_DEFAULT_TAG ); Widget widWarningLabel = XtVaCreateManagedWidget( "label", xmLabelWidgetClass, widForm, XmNleftAttachment, XmATTACH_FORM, XmNrightAttachment, XmATTACH_FORM, XmNtopAttachment, XmATTACH_FORM, XmNlabelString, xmsWarningMessage, XmNalignment, XmALIGNMENT_CENTER, NULL ); XmStringFree( xmsWarningMessage ); widOKButton_ = XtVaCreateManagedWidget( "OK", xmPushButtonWidgetClass, widForm, XmNbottomAttachment, XmATTACH_FORM, XmNbottomOffset, 10, XmNleftAttachment, XmATTACH_POSITION, XmNleftPosition, 35, XmNrightAttachment, XmATTACH_POSITION, XmNrightPosition, 45, NULL ); XtAddCallback(widOKButton_, XmNactivateCallback, (XtCallbackProc )cbChooseMultipleTagTypes, this); widCancelButton_ = XtVaCreateManagedWidget( "Cancel", xmPushButtonWidgetClass, widForm, XmNbottomAttachment, XmATTACH_FORM, XmNbottomOffset, 10, XmNleftAttachment, XmATTACH_POSITION, XmNleftPosition, 55, XmNrightAttachment, XmATTACH_POSITION, XmNrightPosition, 65, NULL ); XtAddCallback(widCancelButton_, XmNactivateCallback, (XtCallbackProc )cbChooseMultipleTagTypes, this); Widget widBottomOfListConnectsToThis; widBottomOfListConnectsToThis = widOKButton_; Widget widForm2 = XtVaCreateManagedWidget( "formForTextBox", xmFormWidgetClass, widForm, XmNbottomAttachment, XmATTACH_WIDGET, XmNbottomWidget, widBottomOfListConnectsToThis, XmNleftAttachment, XmATTACH_FORM, NULL ); widBottomOfListConnectsToThis = widForm2; Widget widLabel = XtVaCreateManagedWidget( "select all tag types containing this string:", xmLabelWidgetClass, widForm2, XmNtopAttachment, XmATTACH_FORM, XmNbottomAttachment, XmATTACH_FORM, XmNleftAttachment, XmATTACH_FORM, NULL ); widUserEnteredString_ = XtVaCreateManagedWidget( "user_entered_string", xmTextFieldWidgetClass, widForm2, XmNtopAttachment, XmATTACH_FORM, XmNbottomAttachment, XmATTACH_FORM, XmNleftAttachment, XmATTACH_WIDGET, XmNleftWidget, widLabel, NULL ); widSelectAllTagsWithStringButton_ = XtVaCreateManagedWidget( "select", xmPushButtonWidgetClass, widForm2, XmNtopAttachment, XmATTACH_FORM, XmNbottomAttachment, XmATTACH_FORM, XmNleftAttachment, XmATTACH_WIDGET, XmNleftWidget, widUserEnteredString_, NULL ); XtAddCallback( widSelectAllTagsWithStringButton_, XmNactivateCallback, cbUserPushedSelectAllTagsWithStringButton, this ); widClearUserSelectionsButton_ = XtVaCreateManagedWidget( "Clear", xmPushButtonWidgetClass, widForm, XmNbottomAttachment, XmATTACH_WIDGET, XmNbottomWidget, widBottomOfListConnectsToThis, XmNleftAttachment, XmATTACH_FORM, NULL ); XtAddCallback( widClearUserSelectionsButton_, XmNactivateCallback, (XtCallbackProc) cbClearUserSelections, this ); widBottomOfListConnectsToThis = widClearUserSelectionsButton_; int nTagTypes = tagTypes::pGetTagTypes()->nGetNumberOfTagTypes(); // nTagTypes is perhaps longer than needed XmStringTable ppXtString = (XmStringTable) XtMalloc( nTagTypes * sizeof( XmString ) ); // nTagTypes is perhaps longer than needed // list items start with index 1 aTranslateTagTypeIndexFromListItemIndex_.reshape( nTagTypes + 1, 0 ); // initial value int nTagTypesDisplayed = 0; for( int nTagType = 0; nTagType < nTagTypes; ++nTagType ) { RWCString soTagType = tagTypes::pGetTagTypes()->soGetTagType( nTagType ); // always exclude tagsOverlap since we don't navigate for this (these // tags don't exist) and we don't add this tag type if (soTagType == "tagsOverlap" ) continue; ppXtString[ nTagTypesDisplayed ] = XmStringCreateLocalized( (char*) soTagType.data() ); ++nTagTypesDisplayed; aTranslateTagTypeIndexFromListItemIndex_[ nTagTypesDisplayed ] = nTagType; } nArgs = 0; XtSetArg( aArg[nArgs], XmNbottomAttachment, XmATTACH_WIDGET ); ++nArgs; XtSetArg( aArg[nArgs], XmNbottomWidget, widBottomOfListConnectsToThis ); ++nArgs; XtSetArg( aArg[nArgs], XmNtopAttachment, XmATTACH_WIDGET ); ++nArgs; XtSetArg( aArg[nArgs], XmNtopWidget, widWarningLabel ); ++nArgs; XtSetArg( aArg[nArgs], XmNleftAttachment, XmATTACH_FORM ); ++nArgs; XtSetArg( aArg[nArgs], XmNrightAttachment, XmATTACH_FORM ); ++nArgs; XtSetArg( aArg[nArgs], XmNvisibleItemCount, 30 ); ++nArgs; XtSetArg( aArg[nArgs], XmNtraversalOn, True ); ++nArgs; XtSetArg( aArg[nArgs], XmNitems, ppXtString ); ++nArgs; XtSetArg( aArg[nArgs], XmNitemCount, nTagTypesDisplayed ); ++nArgs; XtSetArg( aArg[nArgs], XmNselectionPolicy, XmMULTIPLE_SELECT ); ++nArgs; widTagTypesList_ = XmCreateScrolledList( widForm, "tagTypes", aArg, nArgs ); // if the user previously used a tag type, highlight it so (s)he can // use it again XtManageChild( widTagTypesList_ ); XtAddCallback( widTagTypesList_, XmNdefaultActionCallback, cbChooseMultipleTagTypes, this ); XtAddCallback( widTagTypesList_, XmNsingleSelectionCallback, cbChooseTagTypesSingleClick, this ); XtPopup( widPopupShell_, XtGrabExclusive ); XmProcessTraversal( widTagTypesList_, XmTRAVERSE_CURRENT ); // wait until user answers the question--don't let him do anything else! user_must_answer_question_correctly: bBlockApplication_ = true; // xt callback must clear XEvent xevent; while( bBlockApplication_ ) { XtAppNextEvent( GuiApp::pGetGuiApp()->ctxGetAppContext(), &xevent); XtDispatchEvent( &xevent); } if (widWhichButtonGotPushed_ == widCancelButton_ ) bUserPushedCancel = true; else bUserPushedCancel = false; aTagTypesToReturn = aTagTypesSelected_; XtPopdown( widPopupShell_ ); XtDestroyWidget( widPopupShell_ ); } // popupBoxAndWaitForUserToSelectMultipleTagTypes( void guiGetTagType :: popupBoxAndWaitForUserToSelectTagType2( RWCString& soTagType, bool& bUserPushedCancel, const bool bOnlyShowTagTypesThatCanBeCreatedBySwiping, tagType::readOrConsensusType& readOrConsensusType, const bool bAllowUserToEnterCommentAndContigName, RWCString& soComment, RWCString& soContigName ) { bAllowUserToEnterCommentAndContigName_ = bAllowUserToEnterCommentAndContigName; bOnlyShowTagTypesThatCanBeCreatedBySwiping_ = bOnlyShowTagTypesThatCanBeCreatedBySwiping; int nArgs; Arg aArg[50]; widPopupShell_ = XtVaCreatePopupShell( "Tag", topLevelShellWidgetClass, GuiApp::pGetGuiApp()->widGetTopLevel(), XmNtitle, (char*) "Select Tag Type", XmNnoResize, False, XmNautoUnmanage, False, XmNtransient, False, XmNdeleteResponse, XmDO_NOTHING, XmNmwmDecorations, MWM_DECOR_ALL | MWM_DECOR_MENU | MWM_DECOR_MINIMIZE | MWM_DECOR_MAXIMIZE, NULL ); handleWindowManagerDelete( widPopupShell_ ); // the immediate child of the application shell is a // main window Widget widMainWin = XtVaCreateManagedWidget("mainwin", xmMainWindowWidgetClass, widPopupShell_, XmNancestorSensitive, True, NULL ); // // create the form widget // nArgs = 0; XtSetArg(aArg[nArgs],XmNshadowThickness,0); nArgs++; XtSetArg(aArg[nArgs],XmNborderWidth,0); nArgs++; Widget widForm = XmCreateForm(widMainWin, "form", aArg, nArgs); XtManageChild(widForm); XmString xmsWarningMessage = XmStringCreateLtoR( "YOU MUST RESPOND TO THIS\nBEFORE DOING ANYTHING ELSE", XmFONTLIST_DEFAULT_TAG ); Widget widWarningLabel = XtVaCreateManagedWidget( "label", xmLabelWidgetClass, widForm, XmNleftAttachment, XmATTACH_FORM, XmNrightAttachment, XmATTACH_FORM, XmNtopAttachment, XmATTACH_FORM, XmNlabelString, xmsWarningMessage, XmNalignment, XmALIGNMENT_CENTER, NULL ); XmStringFree( xmsWarningMessage ); // put radio button whether the user wants to tag the consensus // or all the reads Widget widRadioBox = XmCreateRadioBox( widForm, "radio", NULL, 0 ); XtVaSetValues( widRadioBox, XmNtopAttachment, XmATTACH_WIDGET, XmNtopWidget, widWarningLabel, XmNorientation, XmHORIZONTAL, NULL ); Widget widConnectToWidgetOnTop = widRadioBox; widTagConsensus_ = XtVaCreateManagedWidget( "Tag Consensus", xmToggleButtonWidgetClass, widRadioBox, XmNset, ( pCP->bDefaultTagOnConsensusNotReads_ ? True : False ), NULL ); XtAddCallback( widTagConsensus_, XmNvalueChangedCallback, cbUserChangedBetweenConsensusAndReads, this ); Widget widTagAllReads = XtVaCreateManagedWidget( "Tag all reads", xmToggleButtonWidgetClass, widRadioBox, XmNset, ( pCP->bDefaultTagOnConsensusNotReads_ ? False : True ), NULL ); XtManageChild( widRadioBox ); // end of radio box widOKButton_ = XtVaCreateManagedWidget( "OK", xmPushButtonWidgetClass, widForm, XmNbottomAttachment, XmATTACH_FORM, XmNbottomOffset, 10, XmNleftAttachment, XmATTACH_POSITION, XmNleftPosition, 35, XmNrightAttachment, XmATTACH_POSITION, XmNrightPosition, 45, NULL ); XtAddCallback(widOKButton_, XmNactivateCallback, (XtCallbackProc )cbChooseTagTypes, this); widCancelButton_ = XtVaCreateManagedWidget( "Cancel", xmPushButtonWidgetClass, widForm, XmNbottomAttachment, XmATTACH_FORM, XmNbottomOffset, 10, XmNleftAttachment, XmATTACH_POSITION, XmNleftPosition, 55, XmNrightAttachment, XmATTACH_POSITION, XmNrightPosition, 65, NULL ); XtAddCallback(widCancelButton_, XmNactivateCallback, (XtCallbackProc )cbChooseTagTypes, this); Widget widBottomOfListConnectsToThis; if ( bAllowUserToEnterCommentAndContigName ) { nArgs = 0; XtSetArg( aArg[nArgs], XmNbottomAttachment, XmATTACH_WIDGET ); ++nArgs; XtSetArg( aArg[nArgs], XmNbottomWidget, widOKButton_ ); ++nArgs; XtSetArg( aArg[nArgs], XmNbottomOffset, 10 ); ++nArgs; XtSetArg( aArg[nArgs], XmNleftAttachment, XmATTACH_FORM ); ++nArgs; XtSetArg( aArg[nArgs], XmNrightAttachment, XmATTACH_FORM ); ++nArgs; XtSetArg( aArg[nArgs], XmNrows, 3 ); ++nArgs; XtSetArg( aArg[nArgs], XmNeditMode, XmMULTI_LINE_EDIT ); ++nArgs; XtSetArg( aArg[nArgs], XmNeditable, True ); ++nArgs; XtSetArg( aArg[nArgs], XmNcursorPositionVisible, True ); ++nArgs; XtSetArg( aArg[nArgs], XmNtraversalOn, True ); ++nArgs; widComment_ = XmCreateScrolledText( widForm, "comment", aArg, nArgs ); XtManageChild( widComment_ ); Widget widCommentLabel = XtVaCreateManagedWidget( "Comment:", xmLabelWidgetClass, widForm, XmNbottomAttachment, XmATTACH_WIDGET, XmNbottomWidget, widComment_, XmNleftAttachment, XmATTACH_FORM, NULL ); widContigNameLabel_ = XtVaCreateManagedWidget( "Contig Name:", xmLabelWidgetClass, widForm, XmNbottomAttachment, XmATTACH_WIDGET, XmNbottomWidget, widCommentLabel, XmNleftAttachment, XmATTACH_FORM, XmNsensitive, False, NULL ); widContigName_ = XtVaCreateManagedWidget( "Contig Name", xmTextWidgetClass, widForm, XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET, XmNbottomWidget, widContigNameLabel_, XmNleftAttachment, XmATTACH_WIDGET, XmNleftWidget, widContigNameLabel_, XmNleftOffset, 10, XmNsensitive, False, NULL ); widBottomOfListConnectsToThis = widContigName_; } else widBottomOfListConnectsToThis = widOKButton_; int nTagTypes = tagTypes::pGetTagTypes()->nGetNumberOfTagTypes(); // nTagTypes is perhaps longer than needed XmStringTable ppXtString = (XmStringTable) XtMalloc( nTagTypes * sizeof( XmString ) ); // nTagTypes is perhaps longer than needed // list items start with index 1 aTranslateTagTypeIndexFromListItemIndex_.reshape( nTagTypes + 1, 0 ); // initial value tagType::readOrConsensusType rcLastUsed = ( pCP->bDefaultTagOnConsensusNotReads_ ? tagType::consensus : tagType::read ); bool bFoundLastUsedTagType = false; int nListIndexOfLastUsedTagType; int nTagTypesDisplayed = 0; for( int nTagType = 0; nTagType < nTagTypes; ++nTagType ) { RWCString soTagType = tagTypes::pGetTagTypes()->soGetTagType( nTagType ); if (bOnlyShowTagTypesThatCanBeCreatedBySwiping ) { if ( ! tagTypes::pGetTagTypes()->bTagTypeCanBeCreatedBySwiping( nTagType ) ) continue; } // always exclude tagsOverlap since we don't navigate for this (these // tags don't exist) and we don't add this tag type if (soTagType == "tagsOverlap" ) continue; tagType::readOrConsensusType rc = tagTypes::pGetTagTypes()->rcGetTagReadOrConsensusType( nTagType ); if ( !( rc & rcLastUsed ) ) // notice bitwise compare continue; ppXtString[ nTagTypesDisplayed ] = XmStringCreateLocalized( (char*) soTagType.data() ); ++nTagTypesDisplayed; aTranslateTagTypeIndexFromListItemIndex_[ nTagTypesDisplayed ] = nTagType; if ( soTagType == pCP->soDefaultTagType_ ) { bFoundLastUsedTagType = true; nListIndexOfLastUsedTagType = nTagTypesDisplayed; } } nArgs = 0; XtSetArg( aArg[nArgs], XmNbottomAttachment, XmATTACH_WIDGET ); ++nArgs; XtSetArg( aArg[nArgs], XmNbottomWidget, widBottomOfListConnectsToThis ); ++nArgs; XtSetArg( aArg[nArgs], XmNtopAttachment, XmATTACH_WIDGET ); ++nArgs; XtSetArg( aArg[nArgs], XmNtopWidget, widConnectToWidgetOnTop ); ++nArgs; XtSetArg( aArg[nArgs], XmNleftAttachment, XmATTACH_FORM ); ++nArgs; XtSetArg( aArg[nArgs], XmNrightAttachment, XmATTACH_FORM ); ++nArgs; XtSetArg( aArg[nArgs], XmNvisibleItemCount, 30 ); ++nArgs; XtSetArg( aArg[nArgs], XmNtraversalOn, True ); ++nArgs; XtSetArg( aArg[nArgs], XmNitems, ppXtString ); ++nArgs; XtSetArg( aArg[nArgs], XmNitemCount, nTagTypesDisplayed ); ++nArgs; XtSetArg( aArg[nArgs], XmNselectionPolicy, XmSINGLE_SELECT ); ++nArgs; widTagTypesList_ = XmCreateScrolledList( widForm, "tagTypes", aArg, nArgs ); // if the user previously used a tag type, highlight it so (s)he can // use it again XtManageChild( widTagTypesList_ ); if ( bFoundLastUsedTagType ) { XmListSelectPos( widTagTypesList_, nListIndexOfLastUsedTagType, False ); // if True, invokes the selection callback // make sure that the selected item is visible int nTopIndex; int nVisibleItems; XtVaGetValues( widTagTypesList_, XmNtopItemPosition, &nTopIndex, XmNvisibleItemCount, &nVisibleItems, NULL ); if ( nListIndexOfLastUsedTagType > nTopIndex + nVisibleItems - 1 ) XmListSetBottomPos( widTagTypesList_, nListIndexOfLastUsedTagType ); // I don't think we need to worry about the selected item being // above the top of the list since I believe the first item // of the list will be the top visible item. // pretend the user already single clicked on this item XmListCallbackStruct XmListCallbackStructt; XmListCallbackStructt.reason = XmCR_SINGLE_SELECT; XmListCallbackStructt.item_position = nListIndexOfLastUsedTagType; setCallbackInfoForSingleSelection( &XmListCallbackStructt ); } XtAddCallback( widTagTypesList_, XmNdefaultActionCallback, cbChooseTagTypes, this ); XtAddCallback( widTagTypesList_, XmNsingleSelectionCallback, cbChooseTagTypesSingleClick, this ); XtPopup( widPopupShell_, XtGrabExclusive ); XmProcessTraversal( widTagTypesList_, XmTRAVERSE_CURRENT ); // wait until user answers the question--don't let him do anything else! user_must_answer_question_correctly: bBlockApplication_ = true; // xt callback must clear XEvent xevent; while( bBlockApplication_ ) { XtAppNextEvent( GuiApp::pGetGuiApp()->ctxGetAppContext(), &xevent); XtDispatchEvent( &xevent); } if (widWhichButtonGotPushed_ == widCancelButton_ ) bUserPushedCancel = true; else bUserPushedCancel = false; soTagType = soTagTypeSelected_; if ( bAllowUserToEnterCommentAndContigName && !bUserPushedCancel ) { char* szComment = XmTextGetString( widComment_ ); soComment = szComment; XtFree( szComment ); char* szContigName = XmTextGetString( widContigName_ ); soContigName = szContigName; XtFree( szContigName ); if ( soTagType == "comment" && soComment.isNull() ) { popupErrorMessage( "if you want to add a comment tag, you must also enter a comment" ); goto user_must_answer_question_correctly; } if ( soTagType == "contigName" && soContigName.isNull() ) { popupErrorMessage( "if you want to add a contigName tag, you must also enter a contigName" ); goto user_must_answer_question_correctly; } } pCP->soDefaultTagType_ = soTagType; XtPopdown( widPopupShell_ ); XtDestroyWidget( widPopupShell_ ); // want to return this: if ( pCP->bDefaultTagOnConsensusNotReads_ ) readOrConsensusType = tagType::consensus; else readOrConsensusType = tagType::read; } void guiGetTagType :: guiChoseTagType( Widget widCallback, XmListCallbackStruct* pXmListCallbackStruct ) { int nIndex; // the purpose of this callback is to set the object (non-automatic) // data bUserPushedCancel_, nIndex_, // and bBlockApplication_ assert( (widCallback == widTagTypesList_) || (widCallback == widCancelButton_) || (widCallback == widOKButton_) ); widWhichButtonGotPushed_ = widCallback; if (widCallback == widCancelButton_ ) { bBlockApplication_ = false; return; } else if ( widCallback == widTagTypesList_) { // case of double click nIndex = pXmListCallbackStruct->item_position; } else { if (! bUserSingleClicked_ ) { GuiApp::pGetGuiApp()->popupErrorMessage( "you must first single click on a tag type before clicking ok" ); // don't unblock--keep application pending return; } // case of single click followed by clicking ok nIndex = nSingleClickIndex_; } int nTagTypeIndex = aTranslateTagTypeIndexFromListItemIndex_[ nIndex ]; soTagTypeSelected_ = tagTypes::pGetTagTypes()->soGetTagType( nTagTypeIndex); bBlockApplication_ = false; } void guiGetTagType :: guiChoseMultipleTagTypes( Widget widCallback ) { // the purpose of this callback is to set the object (non-automatic) // data bUserPushedCancel_ // and bBlockApplication_ assert( (widCallback == widTagTypesList_) || (widCallback == widCancelButton_) || (widCallback == widOKButton_) ); widWhichButtonGotPushed_ = widCallback; if (widCallback == widCancelButton_ ) { bBlockApplication_ = false; return; } // check what is selected int* pPositionInList; int nNumberOfSelectedTagTypes; bool bSomeSelected = false; if ( XmListGetSelectedPos( widTagTypesList_, &pPositionInList, &nNumberOfSelectedTagTypes ) ) { if ( nNumberOfSelectedTagTypes > 0 ) { bSomeSelected = true; } } if ( !bSomeSelected ) { popupErrorMessage2( widPopupShell_, "you must first single click on a tag type before clicking ok" ); // don't unblock--keep application pending return; } for( int nSelected = 0; nSelected < nNumberOfSelectedTagTypes; ++nSelected ) { int n1PositionInDisplayedList = pPositionInList[ nSelected ]; int nTagTypeIndex = aTranslateTagTypeIndexFromListItemIndex_[ n1PositionInDisplayedList ]; RWCString soTagType = tagTypes::pGetTagTypes()->soGetTagType( nTagTypeIndex ); aTagTypesSelected_.insert( soTagType ); } bBlockApplication_ = false; } void guiGetTagType :: setCallbackInfoForSingleSelection( XmListCallbackStruct* pXmListCallbackStruct ) { // the purpose of this callback is to set the object (non-automatic) // data bUserPushedCancel_, nIndex_, // and bBlockApplication_ if (pXmListCallbackStruct->reason != XmCR_SINGLE_SELECT ) { assert(False); } bUserSingleClicked_ = true; nSingleClickIndex_ = pXmListCallbackStruct->item_position; // sensitize or desensitize the Contig Name box if ( bAllowUserToEnterCommentAndContigName_ ) { int nTagTypeIndex = aTranslateTagTypeIndexFromListItemIndex_[ nSingleClickIndex_ ]; soTagTypeSelected_ = tagTypes::pGetTagTypes()->soGetTagType( nTagTypeIndex); if (soTagTypeSelected_ == "contigName" ) { XtVaSetValues( widContigNameLabel_, XmNsensitive, True, NULL ); XtVaSetValues( widContigName_, XmNsensitive, True, NULL ); } else { XtVaSetValues( widContigNameLabel_, XmNsensitive, False, NULL ); XtVaSetValues( widContigName_, XmNsensitive, False, NULL ); } } } void guiGetTagType :: userChangedBetweenConsensusAndReads() { tagType::readOrConsensusType readOrConsensusTypeWanted; if ( XmToggleButtonGetState( widTagConsensus_ ) == True ) { readOrConsensusTypeWanted = tagType::consensus; pCP->bDefaultTagOnConsensusNotReads_ = true; } else { readOrConsensusTypeWanted = tagType::read; pCP->bDefaultTagOnConsensusNotReads_ = false; } // clear for( int n = 0; n < aTranslateTagTypeIndexFromListItemIndex_.length(); ++n ) { aTranslateTagTypeIndexFromListItemIndex_[n] = 0; } int nTagTypes = tagTypes::pGetTagTypes()->nGetNumberOfTagTypes(); // nTagTypes is perhaps longer than needed XmStringTable ppXtString = (XmStringTable) XtMalloc( nTagTypes * sizeof( XmString ) ); bool bFoundLastUsedTagType = false; int nListIndexOfLastUsedTagType; int nTagTypesDisplayed = 0; // list item index starts at 1. ++ will cause // this to start at 1 for( int nTagType = 0; nTagType < nTagTypes; ++nTagType ) { tagType::readOrConsensusType rc = tagTypes::pGetTagTypes()->rcGetTagReadOrConsensusType( nTagType ); if ( ! ( rc & readOrConsensusTypeWanted ) ) // notice bitwise compare continue; if ( bOnlyShowTagTypesThatCanBeCreatedBySwiping_ ) { if ( ! tagTypes::pGetTagTypes()->bTagTypeCanBeCreatedBySwiping( nTagType ) ) continue; } RWCString soTagType = tagTypes::pGetTagTypes()->soGetTagType( nTagType ); // always exclude tagsOverlap since we don't navigate for this (these // tags don't exist) and we don't add this tag type if (soTagType == "tagsOverlap" ) continue; ppXtString[ nTagTypesDisplayed ] = XmStringCreateLocalized( (char*) soTagType.data() ); ++nTagTypesDisplayed; aTranslateTagTypeIndexFromListItemIndex_[ nTagTypesDisplayed ] = nTagType; if ( soTagType == pCP->soDefaultTagType_ ) { bFoundLastUsedTagType = true; nListIndexOfLastUsedTagType = nTagTypesDisplayed; } } XtVaSetValues( widTagTypesList_, XmNitems, ppXtString, XmNitemCount, nTagTypesDisplayed, NULL ); if ( bFoundLastUsedTagType ) { XmListSelectPos( widTagTypesList_, nListIndexOfLastUsedTagType, False ); // if True, invokes selection callback // make sure that the selected item is visible int nTopIndex; int nVisibleItems; XtVaGetValues( widTagTypesList_, XmNtopItemPosition, &nTopIndex, XmNvisibleItemCount, &nVisibleItems, NULL ); if ( nListIndexOfLastUsedTagType > nTopIndex + nVisibleItems - 1 ) XmListSetBottomPos( widTagTypesList_, nListIndexOfLastUsedTagType ); // I don't think we need to worry about the selected item being // above the top of the list since I believe the first item // of the list will be the top visible item. // pretend the user already single clicked on this item XmListCallbackStruct XmListCallbackStructt; XmListCallbackStructt.reason = XmCR_SINGLE_SELECT; XmListCallbackStructt.item_position = nListIndexOfLastUsedTagType; setCallbackInfoForSingleSelection( &XmListCallbackStructt ); } } void guiGetTagType :: clearUserSelections() { XmListDeselectAllItems( widTagTypesList_ ); } void guiGetTagType :: userPushedSelectAllTagsWithStringButton() { char* szValue; RWCString soUserEnteredString; szValue = XmTextFieldGetString( widUserEnteredString_ ); soUserEnteredString = szValue; XtFree( szValue ); for( int nTagTypesDisplayed = 0; nTagTypesDisplayed < aTranslateTagTypeIndexFromListItemIndex_.length(); ++nTagTypesDisplayed ) { int nTagType = aTranslateTagTypeIndexFromListItemIndex_[ nTagTypesDisplayed ]; RWCString soTagType = tagTypes::pGetTagTypes()->soGetTagType( nTagType ); if ( soTagType.bContains( soUserEnteredString ) ) { // there is a bug with XmListSelectPos on linux: if the item is already // selected, XmListSelectPos will deselect the item. // Workaround is to only call XmListSelectPos if the item is currently not selected. if ( ! XmListPosSelected( widTagTypesList_, nTagTypesDisplayed ) ) { XmListSelectPos( widTagTypesList_, nTagTypesDisplayed, False ); // if True, invokes selection callback } } } }