// CMultiGridDlg.cpp : Dialog for controlling multiple grid operations // // Copyright (C) 2024 by the Regents of the University of // Colorado. See Copyright.txt for full notice of copyright and limitations. // // Author: David Mastronarde // #include "stdafx.h" #include "SerialEM.h" #include "SerialEMDoc.h" #include "EMscope.h" #include "MultiGridTasks.h" #include "MultiGridDlg.h" #include "MGSettingsManagerDlg.h" #include "NavigatorDlg.h" #include "MontageSetupDlg.h" #include "StateDlg.h" #include "CameraController.h" #include "NavHelper.h" #include "Shared\b3dutil.h" #include "Utilities\KGetOne.h" #define MAX_DLG_SLOTS 13 static int sIdTable[] = {IDC_STAT_RUN, IDC_STAT_NAME, IDC_BUT_CLOSE_ALL, PANEL_END, IDC_CHECK_MULGRID_RUN1, IDC_CHECK_MULGRID_RUN2, IDC_CHECK_MULGRID_RUN3, IDC_CHECK_MULGRID_RUN4, IDC_CHECK_MULGRID_RUN5, IDC_CHECK_MULGRID_RUN6, IDC_CHECK_MULGRID_RUN7, IDC_CHECK_MULGRID_RUN8, IDC_CHECK_MULGRID_RUN9, IDC_CHECK_MULGRID_RUN10, IDC_CHECK_MULGRID_RUN11, IDC_CHECK_MULGRID_RUN12, IDC_CHECK_MULGRID_RUN13, IDC_RADIO_MULGRID_SEL1, IDC_RADIO_MULGRID_SEL2, IDC_RADIO_MULGRID_SEL3, IDC_STAT_NOTE, IDC_EDIT_GRID_NOTE, IDC_RADIO_MULGRID_SEL4, IDC_RADIO_MULGRID_SEL5, IDC_RADIO_MULGRID_SEL6, IDC_RADIO_MULGRID_SEL7, IDC_RADIO_MULGRID_SEL8, IDC_RADIO_MULGRID_SEL9, IDC_RADIO_MULGRID_SEL10, IDC_RADIO_MULGRID_SEL11, IDC_RADIO_MULGRID_SEL12, IDC_RADIO_MULGRID_SEL13,IDC_EDIT_MULGRID_NAME1, IDC_EDIT_MULGRID_NAME2, IDC_EDIT_MULGRID_NAME3, IDC_EDIT_MULGRID_NAME4, IDC_EDIT_MULGRID_NAME5, IDC_EDIT_MULGRID_NAME6, IDC_EDIT_MULGRID_NAME7, IDC_EDIT_MULGRID_NAME8, IDC_EDIT_MULGRID_NAME9, IDC_EDIT_MULGRID_NAME10, IDC_EDIT_MULGRID_NAME11, IDC_EDIT_MULGRID_NAME12, IDC_EDIT_MULGRID_NAME13, IDC_BUT_LOAD_GRID, IDC_STAT_MULGRID_STATUS1, IDC_STAT_MULGRID_STATUS6, IDC_STAT_MULGRID_STATUS10, IDC_STAT_MULGRID_STATUS2, IDC_STAT_MULGRID_STATUS7, IDC_STAT_MULGRID_STATUS11, IDC_STAT_MULGRID_STATUS3, IDC_STAT_MULGRID_STATUS8, IDC_STAT_MULGRID_STATUS12, IDC_STAT_MULGRID_STATUS4, IDC_STAT_MULGRID_STATUS9, IDC_STAT_MULGRID_STATUS13, IDC_STAT_MULGRID_STATUS5, IDC_CHECK_TOGGLE_ALL, IDC_STAT_NOTE, IDC_EDIT_GRID_NOTE, IDC_BUT_SET_ORDER, IDC_BUT_RESET_ORDER, IDC_BUT_REALIGN_TO_GRID_MAP, IDC_BUT_OPEN_NAV, IDC_BUT_SET_GRID_TYPE, PANEL_END, IDC_BUT_MG_SETUP, IDC_STAT_MG_GRID_SETUP, IDC_TSS_LINE4, PANEL_END, IDC_BUT_MG_GET_NAMES, IDC_BUT_MG_INVENTORY, IDC_STAT_MG_PREFIX, IDC_EDIT_MG_PREFIX, IDC_CHECK_MG_APPEND_NAME, IDC_BUT_MG_RESET_NAMES, IDC_BUT_MG_CLEAR, IDC_STAT_MG_ROOTNAME, IDC_STAT_MG_CURRENT_DIR, IDC_BUT_SET_CURRENT_DIR, IDC_CHECK_MG_USE_SUBDIRS, PANEL_END, IDC_BUT_MG_LOW_MAG_MAPS, IDC_CHECK_RUN_LMMS, IDC_TSS_LINE10, PANEL_END, IDC_RLMM_SEARCH, IDC_STAT_USE1, IDC_RLMM_VIEW, IDC_RLMM_CUR_OR_STATE, IDC_CHECK_SET_LMM_STATE, IDC_COMBO_LMM_STATE, IDC_CHECK_REMOVE_OBJ, IDC_CHECK_SET_CONDENSER, IDC_EDIT_CONDENSER, IDC_STAT_MG_MICRON, IDC_RFULL_GRID_MONT, IDC_RNUM_MONT_PIECES, IDC_STAT_MONTAGE, IDC_EDIT_MONT_XPCS, IDC_STAT_MONT_BY, IDC_EDIT_MONT_NUM_YPCS, IDC_STAT_MONT_PCS, IDC_CHECK_USE_OVERLAP, IDC_EDIT_OVERLAP, IDC_STAT_PERCENT, IDC_BUT_SETUP_LMM_MONT, IDC_CHECK_AUTOCONTOUR, IDC_BUT_SETUP_AUTOCONT2, PANEL_END, IDC_BUT_MG_MEDIUM_MAG_MAPS, IDC_CHECK_TAKE_MMMS, IDC_TSS_LINE6, PANEL_END, IDC_BUT_SETUP_POLYMONT, IDC_RMMM_SEARCH, IDC_STAT_USE2, IDC_RMMM_VIEW, IDC_RMMM_CUR_OR_STATE, IDC_COMBO_MMM_STATE1, IDC_COMBO_MMM_STATE2, IDC_COMBO_MMM_STATE3, IDC_STAT_SET_MMM_STATES, IDC_STAT_MMM_ACQ_TYPE, IDC_RSINGLE_IMAGE, IDC_RPOLYGON_MONT, IDC_BUT_SETUP_MAPPING, IDC_COMBO_MMM_STATE4, IDC_RFIXED_MONT, PANEL_END, IDC_BUT_MG_FINAL_ACQ, IDC_CHECK_RUN_FINAL_ACQ, IDC_TSS_LINE8, PANEL_END, IDC_COMBO_FINAL_STATE3, IDC_COMBO_FINAL_STATE2, IDC_COMBO_FINAL_STATE1, IDC_COMBO_FINAL_STATE4, IDC_STAT_SET_FINAL_STATES, IDC_BUT_SETUP_FINAL_ACQ, IDC_CHECK_SET_FINAL_BY_GRID, IDC_BUT_REVERT_TO_GLOBAL, IDC_CHECK_FRAMES_UNDER_SESSION, PANEL_END, IDC_BUT_START_RUN, IDC_TSS_LINE2, IDCANCEL, IDOK, IDC_BUTHELP, IDC_STAT_SPACER, IDC_BUT_RUN_UNDONE, IDC_BUT_CLOSE_RIGHT, PANEL_END, TABLE_END}; static int sTopTable[sizeof(sIdTable) / sizeof(int)]; static int sLeftTable[sizeof(sIdTable) / sizeof(int)]; static int sHeightTable[sizeof(sIdTable) / sizeof(int)]; // CMultiGridDlg dialog CMultiGridDlg::CMultiGridDlg(CWnd* pParent /*=NULL*/) : CBaseDlg(IDD_MULTI_GRID, pParent) , m_strCurrentDir(_T("")) , m_strRootname(_T("")) , m_bAppendNames(FALSE) , m_bUseSubdirs(FALSE) , m_strPrefix(_T("")) , m_bSetCondenser(FALSE) , m_bRemoveObjective(FALSE) , m_iCondenserSize(150) , m_bUseMontOverlap(FALSE) , m_iMontOverlap(10) , m_iXpieces(3) , m_iYpieces(4) , m_iLMMmontType(0) , m_iSingleVsPolyMont(0) , m_iMMMacquireType(0) , m_bSetLMMstate(FALSE) , m_bTakeLMMs(FALSE) , m_bTakeMMMs(FALSE) , m_bRunFinalAcq(FALSE) , m_bSetFinalByGrid(FALSE) , m_bToggleAll(FALSE) , m_strNote(_T("")) { mNonModal = true; for (int ind = 0; ind < MAX_MULGRID_PANELS; ind++) mPanelStates[ind] = true; mSelectedGrid = -1; mSelGridOnStage = false; mOnStageDlgIndex = -1; mGridMontSetupOK = false; mMMMsetupAcqType = -1; mMMMsetupMontType = -1; mMMMsetupStateForMont = -1; mMMMsetupOK = false; mMMMmontWasSetup = 0; mLMneedsLowDose = 0; mMMMneedsLowDose = 0; mRightIsOpen = -1; mClosedAll = false; mSettingOrder = false; } CMultiGridDlg::~CMultiGridDlg() { } void CMultiGridDlg::DoDataExchange(CDataExchange* pDX) { CBaseDlg::DoDataExchange(pDX); DDX_Text(pDX, IDC_STAT_MG_CURRENT_DIR, m_strCurrentDir); DDX_Text(pDX, IDC_STAT_MG_ROOTNAME, m_strRootname); DDX_Check(pDX, IDC_CHECK_MG_APPEND_NAME, m_bAppendNames); DDX_Check(pDX, IDC_CHECK_MG_USE_SUBDIRS, m_bUseSubdirs); DDX_Control(pDX, IDC_EDIT_MG_PREFIX, m_editPrefix); DDX_Text(pDX, IDC_EDIT_MG_PREFIX, m_strPrefix); DDX_Radio(pDX, IDC_RLMM_SEARCH, m_iLMMacquireType); DDX_Control(pDX, IDC_COMBO_LMM_STATE, m_comboLMMstate); DDX_Check(pDX, IDC_CHECK_SET_CONDENSER, m_bSetCondenser); DDX_Check(pDX, IDC_CHECK_REMOVE_OBJ, m_bRemoveObjective); DDX_MM_INT(pDX, IDC_EDIT_CONDENSER, m_iCondenserSize, 1, 250, "condenser size to switch to"); DDX_Check(pDX, IDC_CHECK_USE_OVERLAP, m_bUseMontOverlap); DDX_MM_INT(pDX, IDC_EDIT_OVERLAP, m_iMontOverlap, 3, 30, "montage overlap"); DDX_MM_INT(pDX, IDC_EDIT_MONT_XPCS, m_iXpieces, 1, 30, "number of montages pieces in X"); DDX_MM_INT(pDX, IDC_EDIT_MONT_NUM_YPCS, m_iYpieces, 1, 30, "number of montages pieces in Y"); DDX_Radio(pDX, IDC_RFULL_GRID_MONT, m_iLMMmontType); DDX_Control(pDX, IDC_COMBO_MMM_STATE1, m_comboMMMstate1); DDX_Control(pDX, IDC_COMBO_MMM_STATE2, m_comboMMMstate2); DDX_Control(pDX, IDC_COMBO_MMM_STATE3, m_comboMMMstate3); DDX_Control(pDX, IDC_COMBO_FINAL_STATE3, m_comboFinalState3); DDX_Control(pDX, IDC_COMBO_FINAL_STATE2, m_comboFinalState2); DDX_Control(pDX, IDC_COMBO_FINAL_STATE1, m_comboFinalState1); DDX_Control(pDX, IDC_STAT_MG_GRID_SETUP, m_statMgSetup); DDX_Radio(pDX, IDC_RSINGLE_IMAGE, m_iSingleVsPolyMont); DDX_Radio(pDX, IDC_RMMM_SEARCH, m_iMMMacquireType); DDX_Check(pDX, IDC_CHECK_SET_LMM_STATE, m_bSetLMMstate); DDX_Check(pDX, IDC_CHECK_AUTOCONTOUR, m_bAutocontour); DDX_Control(pDX, IDC_CHECK_RUN_LMMS, m_butTakeLMMs); DDX_Check(pDX, IDC_CHECK_RUN_LMMS, m_bTakeLMMs); DDX_Control(pDX, IDC_CHECK_TAKE_MMMS, m_butTakeMMMs); DDX_Check(pDX, IDC_CHECK_TAKE_MMMS, m_bTakeMMMs); DDX_Control(pDX, IDC_CHECK_RUN_FINAL_ACQ, m_butRunFinalAcq); DDX_Check(pDX, IDC_CHECK_RUN_FINAL_ACQ, m_bRunFinalAcq); DDX_Control(pDX, IDC_STAT_MG_PREFIX, m_statMgPrefix); DDX_Control(pDX, IDC_COMBO_MMM_STATE4, m_comboMMMstate4); DDX_Control(pDX, IDC_COMBO_FINAL_STATE4, m_comboFinalState4); DDX_Control(pDX, IDC_STAT_MG_CURRENT_DIR, m_statCurrentDir); DDX_Control(pDX, IDC_BUT_CLOSE_RIGHT, m_butCloseRight); DDX_Check(pDX, IDC_CHECK_SET_FINAL_BY_GRID, m_bSetFinalByGrid); DDX_Check(pDX, IDC_CHECK_FRAMES_UNDER_SESSION, m_bFramesUnderSession); DDX_Check(pDX, IDC_CHECK_TOGGLE_ALL, m_bToggleAll); DDX_Text(pDX, IDC_EDIT_GRID_NOTE, m_strNote); } BEGIN_MESSAGE_MAP(CMultiGridDlg, CBaseDlg) ON_BN_CLICKED(IDC_CHECK_MG_APPEND_NAME, OnCheckMgAppendName) ON_BN_CLICKED(IDC_BUT_MG_GET_NAMES, OnButMgGetNames) ON_BN_CLICKED(IDC_BUT_MG_INVENTORY, OnButMgInventory) ON_BN_CLICKED(IDC_BUT_MG_RESET_NAMES, OnButMgResetNames) ON_BN_CLICKED(IDC_BUT_MG_CLEAR, OnButMgClearNames) ON_BN_CLICKED(IDC_BUT_SET_CURRENT_DIR, OnButSetCurrentDir) ON_EN_CHANGE(IDC_EDIT_MG_PREFIX, OnEnChangeEditMgPrefix) ON_BN_CLICKED(IDC_BUT_MG_SETUP, OnButMgSetup) ON_CONTROL_RANGE(EN_KILLFOCUS, IDC_EDIT_MULGRID_NAME1, IDC_EDIT_MULGRID_NAME13, OnEnKillfocusEditName) ON_COMMAND_RANGE(IDC_RADIO_MULGRID_SEL1, IDC_RADIO_MULGRID_SEL13, OnRadioMulgridSelect) ON_BN_CLICKED(IDC_BUT_LOAD_GRID, OnButLoadGrid) ON_BN_CLICKED(IDC_BUT_REALIGN_TO_GRID_MAP, OnButRealignToGridMap) ON_BN_CLICKED(IDC_RLMM_SEARCH, OnRadioLMMSearch) ON_BN_CLICKED(IDC_RLMM_VIEW, OnRadioLMMSearch) ON_BN_CLICKED(IDC_RLMM_CUR_OR_STATE, OnRadioLMMSearch) ON_BN_CLICKED(IDC_CHECK_SET_LMM_STATE, OnCheckSetLmmState) ON_EN_KILLFOCUS(IDC_EDIT_CONDENSER, OnEnKillfocusEditCondenser) ON_BN_CLICKED(IDC_BUT_SETUP_LMM_MONT, OnButSetupLmmMont) ON_BN_CLICKED(IDC_CHECK_USE_OVERLAP, OnCheckUseOverlap) ON_EN_KILLFOCUS(IDC_EDIT_OVERLAP, OnEnKillfocusEditOverlap) ON_EN_KILLFOCUS(IDC_EDIT_MONT_XPCS, OnEnKillfocusEditMontXpcs) ON_EN_KILLFOCUS(IDC_EDIT_MONT_NUM_YPCS, OnEnKillfocusEditMontNumYpcs) ON_BN_CLICKED(IDC_RFULL_GRID_MONT, OnRfullGridMont) ON_BN_CLICKED(IDC_RNUM_MONT_PIECES, OnRfullGridMont) ON_BN_CLICKED(IDC_BUT_MG_LOW_MAG_MAPS, OnButMgLowMagMaps) ON_BN_CLICKED(IDC_BUT_MG_MEDIUM_MAG_MAPS, OnButMgMediumMagMaps) ON_BN_CLICKED(IDC_BUT_MG_FINAL_ACQ, OnButMgFinalAcq) ON_CBN_SELENDOK(IDC_COMBO_LMM_STATE, OnSelendokComboLmmState) ON_CBN_SELENDOK(IDC_COMBO_MMM_STATE1, OnSelendokComboMmmState1) ON_CBN_SELENDOK(IDC_COMBO_MMM_STATE2, OnSelendokComboMmmState2) ON_CBN_SELENDOK(IDC_COMBO_MMM_STATE3, OnSelendokComboMmmState3) ON_CBN_SELENDOK(IDC_COMBO_MMM_STATE4, OnSelendokComboMmmState4) ON_CBN_SELENDOK(IDC_COMBO_FINAL_STATE1, OnSelendokComboFinalState1) ON_CBN_SELENDOK(IDC_COMBO_FINAL_STATE2, OnSelendokComboFinalState2) ON_CBN_SELENDOK(IDC_COMBO_FINAL_STATE3, OnSelendokComboFinalState3) ON_CBN_SELENDOK(IDC_COMBO_FINAL_STATE4, OnSelendokComboFinalState4) ON_BN_CLICKED(IDC_BUT_SETUP_FINAL_ACQ, OnButSetupFinalAcq) ON_BN_CLICKED(IDC_BUT_SETUP_MAPPING, OnButSetupMapping) ON_BN_CLICKED(IDC_BUT_SETUP_POLYMONT, OnButSetupPolymont) ON_BN_CLICKED(IDC_RSINGLE_IMAGE, OnRsingleImage) ON_BN_CLICKED(IDC_RPOLYGON_MONT, OnRsingleImage) ON_BN_CLICKED(IDC_RFIXED_MONT, OnRsingleImage) ON_BN_CLICKED(IDC_RMMM_SEARCH, OnRmmmSearch) ON_BN_CLICKED(IDC_RMMM_VIEW, OnRmmmSearch) ON_BN_CLICKED(IDC_RMMM_CUR_OR_STATE, OnRmmmSearch) ON_BN_CLICKED(IDC_CHECK_RUN_LMMS, OnCheckRunLmms) ON_BN_CLICKED(IDC_CHECK_TAKE_MMMS, OnCheckTakeMmms) ON_BN_CLICKED(IDC_CHECK_RUN_FINAL_ACQ, OnCheckRunFinalAcq) ON_BN_CLICKED(IDC_CHECK_SET_CONDENSER, OnCheckSetCondenser) ON_BN_CLICKED(IDC_CHECK_AUTOCONTOUR, OnCheckAutocontour) ON_BN_CLICKED(IDC_BUT_SETUP_AUTOCONT2, OnButSetupAutocont) ON_BN_CLICKED(IDC_BUT_START_RUN, OnButStartRun) ON_COMMAND_RANGE(IDC_CHECK_MULGRID_RUN1, IDC_CHECK_MULGRID_RUN13, OnCheckMulgridRun) ON_BN_CLICKED(IDC_BUT_RUN_UNDONE, OnButRunUndone) ON_BN_CLICKED(IDC_BUT_OPEN_NAV, OnButOpenNav) ON_BN_CLICKED(IDC_BUT_SET_GRID_TYPE, OnButSetGridType) ON_WM_PAINT() ON_BN_CLICKED(IDC_BUT_CLOSE_RIGHT, OnButCloseRight) ON_BN_CLICKED(IDC_CHECK_SET_FINAL_BY_GRID, OnCheckSetFinalByGrid) ON_BN_CLICKED(IDC_BUT_REVERT_TO_GLOBAL, OnButRevertToGlobal) ON_BN_CLICKED(IDC_CHECK_FRAMES_UNDER_SESSION, OnCheckFramesUnderSession) ON_BN_CLICKED(IDC_CHECK_MG_USE_SUBDIRS, OnCheckMgUseSubdirs) ON_BN_CLICKED(IDC_BUT_CLOSE_ALL, &CMultiGridDlg::OnButCloseAll) ON_BN_CLICKED(IDC_CHECK_TOGGLE_ALL, &CMultiGridDlg::OnCheckToggleAll) ON_EN_KILLFOCUS(IDC_EDIT_GRID_NOTE, &CMultiGridDlg::OnEnKillfocusEditGridNote) ON_BN_CLICKED(IDC_BUT_SET_ORDER, &CMultiGridDlg::OnButSetOrder) ON_BN_CLICKED(IDC_BUT_RESET_ORDER, &CMultiGridDlg::OnButResetOrder) END_MESSAGE_MAP() // CMultiGridDlg message handlers /* * INITIALIZATION AND STANDARD OK/CANCEL ETC HANDLING */ BOOL CMultiGridDlg::OnInitDialog() { CBaseDlg::OnInitDialog(); CString names; CRect rect; int *activeList = mWinApp->GetActiveCameraList(); int cam; bool noSubdirs, movable; CameraParameters *camParams = mWinApp->GetCamParams(); mMGTasks = mWinApp->mMultiGridTasks; mMasterParams = mMGTasks->GetMultiGridParams(); mMGTasks->SetUseCustomOrder(false); mCustomRunDlgInds = mMGTasks->GetCustomRunDlgInds(); mParams = *mMasterParams; mScope = mWinApp->mScope; mCartInfo = mWinApp->mScope->GetJeolLoaderInfo(); mStateArray = mWinApp->mNavHelper->GetStateArray(); m_butTakeLMMs.GetWindowRect(&rect); mBiggerFont.CreateFont(B3DNINT(0.75 * rect.Height()), 0, 0, 0, FW_MEDIUM, 0, 0, 0, DEFAULT_CHARSET, OUT_CHARACTER_PRECIS, CLIP_CHARACTER_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, mWinApp->mScopeStatus.GetBigFontName()); mBigBoldFont.CreateFont(B3DNINT(0.75 * rect.Height()), 0, 0, 0, FW_BOLD, 0, 0, 0, DEFAULT_CHARSET, OUT_CHARACTER_PRECIS, CLIP_CHARACTER_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, mWinApp->mScopeStatus.GetBigFontName()); m_butCloseRight.SetFont(mWinApp->GetLittleFont(&m_butCloseRight)); mSecondColPanel = 4; SetupPanelTables(sIdTable, sLeftTable, sTopTable, mNumInPanel, mPanelStart, sHeightTable); mNumUsedSlots = 0; mNumMMMcombos = mMGTasks->GetNumMMMstateCombos(); mNumFinalCombos = mMGTasks->GetNumFinalStateCombos(); RepackStatesIfNeeded(mNumMMMcombos, &mParams.MMMstateNums[0], &mParams.MMMstateNames[0]); RepackStatesIfNeeded(mNumFinalCombos, &mParams.finalStateNums[0], &mParams.finalStateNames[0]); LoadAllComboBoxes(); m_strPrefix = mMGTasks->GetPrefix(); // Determine if any frame-saving camera has movable frame directory, otherwise drop mDropFrameOption = true; for (cam = 0; cam < mWinApp->GetNumActiveCameras(); cam++) { if (mWinApp->mCamera->IsDirectDetector(&camParams[activeList[cam]]) || (camParams[activeList[cam]].canTakeFrames & 1)) { mWinApp->mCamera->GetCameraFrameFolder(&camParams[activeList[cam]], noSubdirs, movable); if (movable) { mDropFrameOption = false; break; } } } mSingleGridMode = !mScope->GetScopeHasAutoloader(); if (mSingleGridMode) { mParams.appendNames = false; } ParamsToDialog(); UpdateData(false); mPanelStates[5] = mParams.acquireLMMs; mPanelStates[7] = mParams.acquireMMMs; mPanelStates[9] = mParams.runFinalAcq; SetDlgItemText(IDC_BUT_MG_SETUP, mPanelStates[3] ? "-" : "+"); SetDlgItemText(IDC_BUT_MG_LOW_MAG_MAPS, mPanelStates[5] ? "-" : "+"); SetDlgItemText(IDC_BUT_MG_MEDIUM_MAG_MAPS, mPanelStates[7] ? "-" : "+"); SetDlgItemText(IDC_BUT_MG_FINAL_ACQ, mPanelStates[9] ? "-" : "+"); mBoldFont = mWinApp->GetBoldFont(&m_statMgSetup); m_statMgSetup.SetFont(&mBiggerFont); m_butTakeLMMs.SetFont(mParams.acquireLMMs ? &mBigBoldFont : &mBiggerFont); m_butTakeMMMs.SetFont(mParams.acquireMMMs ? &mBigBoldFont : &mBiggerFont); m_butRunFinalAcq.SetFont(mParams.runFinalAcq ? &mBigBoldFont : &mBiggerFont); ManagePanels(); EnableDlgItem(IDC_BUT_LOAD_GRID, false); EnableDlgItem(IDC_BUT_OPEN_NAV, false); EnableDlgItem(IDC_BUT_REALIGN_TO_GRID_MAP, false); if (mSingleGridMode) { InitForSingleGrid(); } CheckIfAnyUndoneToRun(); UpdateEnables(); UpdateCurrentDir(); SetRootname(); SetDefID(45678); // Disable OK from being default button for non-modal return TRUE; } void CMultiGridDlg::OnOK() { CString errStr; SyncToMasterParams(); if (!mMGTasks->GetNamesLocked()) mMGTasks->SetPrefix(m_strPrefix); if (mNumUsedSlots) mMGTasks->SaveSessionFile(errStr); OnCancel(); } // Inform managing module of closing, or store placement and NULL out pointer // right here void CMultiGridDlg::OnCancel() { mWinApp->mNavHelper->GetMultiGridPlacement(); mWinApp->mNavHelper->mMultiGridDlg = NULL; if (mWinApp->mNavHelper->mStateDlg) mWinApp->mNavHelper->mStateDlg->Update(); DestroyWindow(); } void CMultiGridDlg::PostNcDestroy() { delete this; CDialog::PostNcDestroy(); } // This is called on external close like exiting, so make sure settings saved void CMultiGridDlg::CloseWindow() { OnOK(); } BOOL CMultiGridDlg::PreTranslateMessage(MSG* pMsg) { if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_RETURN) SetFocus(); return CDialog::PreTranslateMessage(pMsg); } void CMultiGridDlg::OnPaint() { if (mOnStageDlgIndex >= 0) { CWnd *wnd = GetDlgItem(IDC_EDIT_MULGRID_NAME1 + mOnStageDlgIndex); CPaintDC dc(this); DrawButtonOutline(dc, wnd, 2, RGB(0, 255, 0), -2); } CBaseDlg::OnPaint(); } /* * MESSAGES AND ROUTINES FOR GRID SETUP */ // Option to append names void CMultiGridDlg::OnCheckMgAppendName() { UPDATE_DATA_TRUE; SetRootname(); mWinApp->RestoreViewFocus(); } /* * Get the names from FEI autoloader or cartridge table and set up user names */ void CMultiGridDlg::OnButMgGetNames() { CString names, str, nameArr[MAX_LOADER_SLOTS]; JeolCartridgeData jcd; ShortVec statVec; int status, numSlots = 1, slot = 1, highest = 0, ind, numEmpty = 0; int maybeStage = -1, onStage = -1; if (FEIscope) { for (slot = 1; slot <= numSlots; slot++) { // Call with argument to get number of slots AND skip getting name if (!mScope->CassetteSlotStatus(slot, status, names, &numSlots)) return; B3DCLAMP(numSlots, 1, MAX_DLG_SLOTS); statVec.push_back(status); if (status == 1) highest = slot; } // Now try to get all the names names = ""; if (!mWinApp->mScope->CassetteSlotStatus(0, status, names) && !names.IsEmpty()) { AfxMessageBox(names, MB_EXCLAME); return; } for (slot = 0; slot < numSlots; slot++) { if (!names.IsEmpty()) { // Copy the names into the array ind = names.Find("\n"); if (ind < 0) { nameArr[slot] = names; } else { nameArr[slot] = names.Left(ind); names = names.Mid(ind + 1); } if (nameArr[slot] == "!NONAME!") nameArr[slot] = ""; if (statVec[slot] != 1 && !nameArr[slot].IsEmpty()) { numEmpty++; maybeStage = slot; } } else { // Or just see if there is one empty slot below the highest if (statVec[slot] != 1 && slot < highest) { numEmpty++; maybeStage = slot; } } } // Deal with figuring out what grid is on the stage, as this impacts how many slots // to show if (numEmpty == 1) { str.Format("Is the grid from slot %d loaded on the stage?", maybeStage + 1); if (AfxMessageBox(str, MB_QUESTION) != IDYES) maybeStage = -1; } else maybeStage = -1; if (maybeStage < 0) { maybeStage = highest + 1; if (KGetOneInt("If there is a grid on the stage, enter the slot it was loaded from;" " if not, enter 0", maybeStage)) maybeStage--; else maybeStage = -1; if (maybeStage >= numSlots) maybeStage = -1; } mCartInfo->RemoveAll(); mNumUsedSlots = 0; // Add to the cartInfo for (slot = 0; slot < numSlots; slot++) { str = nameArr[slot]; // Add a cartridge if it is occupied if (statVec[slot] == 1 || slot == maybeStage) { jcd.Init(); jcd.id = slot + 1; jcd.slot = slot + 1; jcd.station = statVec[slot] == 1 ? JAL_STATION_MAGAZINE : JAL_STATION_STAGE; if (statVec[slot] != 1) onStage = (int)mCartInfo->GetSize(); // Supply string if none if (str.IsEmpty()) str.Format("Car%d", slot + 1); jcd.name = str; mMGTasks->ReplaceBadCharacters(str); jcd.userName = str; mCartInfo->Add(jcd); mNumUsedSlots++; } } } else { // JEOL: fix names for username mNumUsedSlots = (int)mCartInfo->GetSize(); for (ind = 0; ind < mNumUsedSlots; ind++) { JeolCartridgeData &jcdEl = mCartInfo->ElementAt(ind); if (jcdEl.name.IsEmpty()) jcdEl.name.Format("Car%d", jcdEl.id); str = jcdEl.name; mMGTasks->ReplaceBadCharacters(str); jcdEl.userName = str; } } ReloadTable(1, 1); if (onStage >= 0) NewGridOnStage(onStage); CheckIfAnyUndoneToRun(); UpdateEnables(); mMGTasks->SetAdocChanged(true); mWinApp->RestoreViewFocus(); } /* * Load the table with names; resetOrClear 0 to use names as is, 1 to use original * name with replacements, 2 to clear. checkRuns -1 to turn off or 1 to turn on Run buts */ void CMultiGridDlg::ReloadTable(int resetOrClear, int checkRuns) { IntVec order; FloatVec idVec; int slot, ind; CString str; CButton *button; JeolCartridgeData jcd; // Get vector of IDs or inverse FEI IDs and order them for (slot = 0; slot < mNumUsedSlots; slot++) { order.push_back(slot); jcd = mCartInfo->GetAt(slot); idVec.push_back((float)jcd.id); } if (mNumUsedSlots) rsSortIndexedFloats(&idVec[0], &order[0], mNumUsedSlots); // Load the slots from the top in the given order, setting name as indicated mDlgIndToJCDindex.clear(); for (slot = 0; slot < mNumUsedSlots; slot++) { ind = order[JEOLscope ? slot : (mNumUsedSlots - 1) - slot]; JeolCartridgeData &jcdEl = mCartInfo->ElementAt(ind); mDlgIndToJCDindex.push_back(ind); str.Format("%d", ind >= 0 ? jcdEl.id : mNumUsedSlots - slot); SetDlgItemText(IDC_RADIO_MULGRID_SEL1 + slot, str); EnableDlgItem(IDC_CHECK_MULGRID_RUN1 + slot, ind >= 0); EnableDlgItem(IDC_EDIT_MULGRID_NAME1 + slot, ind >= 0); if (checkRuns) { button = (CButton *)GetDlgItem(IDC_CHECK_MULGRID_RUN1 + slot); if (button) { if (checkRuns > 1 && mMGTasks->GetUseCustomOrder()) button->SetCheck(LookupRunOrder(*mCustomRunDlgInds, slot) >= 0 ? BST_CHECKED : BST_UNCHECKED); else button->SetCheck((checkRuns > 0 && !(jcdEl.status & MGSTAT_FLAG_TOO_DARK)) ? BST_CHECKED : BST_UNCHECKED); } } if (ind < 0) { SetDlgItemText(IDC_EDIT_MULGRID_NAME1 + slot, ""); } else { if (resetOrClear) { if (resetOrClear > 1) str = ""; else { str = jcdEl.name; mMGTasks->ReplaceBadCharacters(str); } jcdEl.userName = str; mMGTasks->SetAdocChanged(true); } SetDlgItemText(IDC_EDIT_MULGRID_NAME1 + slot, UserNameWithNote(jcdEl.userName, jcdEl.note)); SetStatusText(ind); } } // open the right side the first time ames are gotten if (mRightIsOpen < 0 && mNumUsedSlots > 0) mRightIsOpen = 1; m_bToggleAll = true; ManagePanels(); DisplayRunOrder(); mNamesChanged = false; } // Return the user name, with option note appended CString CMultiGridDlg::UserNameWithNote(CString &userName, CString ¬e) { CString str = userName; if (!note.IsEmpty()) { str = (str + " ") + (const char)0x97; str += " " + note; } return str; } // Button to start inventory void CMultiGridDlg::OnButMgInventory() { mMGTasks->GetInventory(); mWinApp->RestoreViewFocus(); } // Button to reset the names to cartInfo names void CMultiGridDlg::OnButMgResetNames() { if (!mNamesChanged || (mNamesChanged && AfxMessageBox("Resetting to names from scope " "will lose your name changes\n\nAre you sure you want to do this?", MB_QUESTION) == IDYES)) ReloadTable(1, 0); mWinApp->RestoreViewFocus(); } // Button to clear out the names void CMultiGridDlg::OnButMgClearNames() { if (!mNamesChanged || (mNamesChanged && AfxMessageBox("Clearing the names will throw " "away your name changes\n\nAre you sure you want to do this?", MB_QUESTION) == IDYES)) ReloadTable(2, 0); mWinApp->RestoreViewFocus(); } // Option to use subdirs: change name of frame option void CMultiGridDlg::OnCheckMgUseSubdirs() { mWinApp->RestoreViewFocus(); UPDATE_DATA_TRUE; ManageFrameDirOption(); } // Button to set the working directory void CMultiGridDlg::OnButSetCurrentDir() { mWinApp->RestoreViewFocus(); mWinApp->mDocWnd->OnFileSetCurrentDirectory(); } // New prefix characters are entered: fix them up void CMultiGridDlg::OnEnChangeEditMgPrefix() { UPDATE_DATA_TRUE; mMGTasks->ReplaceBadCharacters(m_strPrefix); SetRootname(); } // A new name is entered in the edit box: fix it up and save void CMultiGridDlg::OnEnKillfocusEditName(UINT nID) { CString str; int ind = nID - IDC_EDIT_MULGRID_NAME1; CEdit *edit = (CEdit *)GetDlgItem(nID); mWinApp->RestoreViewFocus(); if (!edit) return; edit->GetWindowText(str); if (mMGTasks->ReplaceBadCharacters(str)) edit->SetWindowText(str); if (ind >= 0 && ind < (int)mDlgIndToJCDindex.size() && mDlgIndToJCDindex[ind] >= 0) { JeolCartridgeData &jcdEl = FindCartDataForDlgIndex(ind); if (str.Compare(jcdEl.userName)) { mNamesChanged = true; mMGTasks->SetAdocChanged(true); jcdEl.userName = str; } } } // Returns a read-only copy of the jcd at the given dialog row JeolCartridgeData CMultiGridDlg::FindCartDataForDlgIndex(int ind) { static JeolCartridgeData jcd; jcd.slot = -1; if (ind >= 0 && ind < (int)mDlgIndToJCDindex.size() && mDlgIndToJCDindex[ind] >= 0) jcd = mCartInfo->GetAt(mDlgIndToJCDindex[ind]); return jcd; } /* * Return lists of the jcd indexes and slot #s (FEI) or index + 1 in JEOL catalogue ready * for use in loading grid, for custom or default order */ int CMultiGridDlg::GetListOfGridsToRun(ShortVec &jcdInds, ShortVec &slotNums) { JeolCartridgeData jcd; int ind, jcdInd; IntVec dlgInds; jcdInds.clear(); slotNums.clear(); if (mMGTasks->GetUseCustomOrder()) dlgInds = *mCustomRunDlgInds; else DefaultRunDlgIndexes(dlgInds); for (ind = 0; ind < (int)dlgInds.size(); ind++) { jcdInd = mDlgIndToJCDindex[dlgInds[ind]]; jcdInds.push_back(jcdInd); if (FEIscope) { jcd = mCartInfo->GetAt(jcdInd); slotNums.push_back(jcd.slot); } else { slotNums.push_back(jcdInd + 1); } } return (int)jcdInds.size(); } /* * Return ordered dialog indexes for the default order, accounting for grid on stage */ void CMultiGridDlg::DefaultRunDlgIndexes(IntVec &dlgInds) { int loop, ind, indOnStage = -1; short tmp; CButton *button; dlgInds.clear(); for (loop = 0; loop < mNumUsedSlots; loop++) { ind = FEIscope ? mNumUsedSlots - (loop + 1) : loop; button = (CButton *)GetDlgItem(IDC_CHECK_MULGRID_RUN1 + ind); if (button && button->GetCheck() && ind < (int)mDlgIndToJCDindex.size()) { if (mOnStageDlgIndex == ind) indOnStage = (int)dlgInds.size(); dlgInds.push_back(ind); } } if (mMGTasks->GetReferenceCounts() != 0. && indOnStage > 0) { tmp = dlgInds[indOnStage]; for (ind = indOnStage; ind > 0; ind--) dlgInds[ind] = dlgInds[ind - 1]; dlgInds[0] = tmp; } } /* * Set the run checkbox labels with the order numbers for ones to be run */ void CMultiGridDlg::DisplayRunOrder() { IntVec dlgInds; int ind, run; CString str; if (mMGTasks->GetUseCustomOrder()) dlgInds = *mCustomRunDlgInds; else DefaultRunDlgIndexes(dlgInds); for (ind = 0; ind < mNumUsedSlots; ind++) { run = LookupRunOrder(dlgInds, ind) + 1; str = ""; if (run > 0) str.Format("%d", run); SetDlgItemText(IDC_CHECK_MULGRID_RUN1 + ind, str); } } /* * Look up a dialog index in the given run list and return its index there, or -1 */ int CMultiGridDlg::LookupRunOrder(IntVec &runDlgInds, int dlgInd) { for (int ind = 0; ind < (int)runDlgInds.size(); ind++) if (runDlgInds[ind] == dlgInd) return ind; return -1; } /* * Set the rootname in the display given the contents of the prefix * Can't use the routine in MGtasks because the C# component is omitted if the name * is Car# */ void CMultiGridDlg::SetRootname() { m_strRootname = "Root name: " + m_strPrefix; int prefLen = m_strPrefix.GetLength(); char last; int pound, carLen, gridLen; if (prefLen > 1) { last = m_strPrefix.GetAt(prefLen - 1); pound = (last == '_' || last == '-') ? 1 : 0; carLen = prefLen - (3 + pound); gridLen = prefLen - (4 + pound); } // Allow for Car/car and Grid/grid with or without a - or _ if ((prefLen < 3 || !(m_strPrefix.Find("Car") == carLen || m_strPrefix.Find("car") == carLen || m_strPrefix.Find("Grid") == gridLen || m_strPrefix.Find("grid") == gridLen)) && !mSingleGridMode) { if (m_strPrefix.IsEmpty()) m_strRootname = "C"; else m_strRootname += "_C"; } if (!mSingleGridMode) { if (JEOLscope) m_strRootname += "##"; m_strRootname += "##"; } if (m_bAppendNames) m_strRootname += "_name"; UpdateData(false); } /* * Interpret the status flags for a given item in catalogue and set up status text */ void CMultiGridDlg::SetStatusText(int jcdInd) { CString str; JeolCartridgeData jcd = mCartInfo->GetAt(jcdInd); for (int dlin = 0; dlin < mNumUsedSlots; dlin++) { if (mDlgIndToJCDindex[dlin] == jcdInd) { str += jcd.separateState ? 'S' : (const char)0x97; str += (jcd.multiShotParamIndex >= 0 || jcd.holeFinderParamIndex >= 0 || jcd.autoContParamIndex >= 0 || jcd.generalParamIndex >= 0 || jcd.focusPosParamIndex >= 0 || jcd.finalDataParamIndex >= 0) ? 'P' : (const char)0x97; str += ":"; if (jcd.status & MGSTAT_FLAG_TOO_DARK) str += (jcd.status & MGSTAT_FLAG_LM_MAPPED) ? "G-D" : "DA"; else if (jcd.status & MGSTAT_FLAG_ACQ_DONE) str += "AQ"; else if (jcd.status & MGSTAT_FLAG_MMM_DONE) str += (jcd.status & MGSTAT_FLAG_FAILED) ? "M-F" : "MM"; else if (jcd.status & MGSTAT_FLAG_LM_MAPPED) str += (jcd.status & MGSTAT_FLAG_FAILED) ? "G-F" : "GR"; else if (jcd.status & MGSTAT_FLAG_FAILED) str += "FL"; SetDlgItemText(IDC_STAT_MULGRID_STATUS1 + dlin, str); return; } } } /* * Routine that can be called whenever there is a different grid on the stage so it can * manage the bolding of the name and mOnStageDlgIndex */ void CMultiGridDlg::NewGridOnStage(int jcdInd) { int id, ind, oldInd = mOnStageDlgIndex; CEdit *edit; JeolCartridgeData jcd; if (jcdInd < 0) jcdInd = mScope->FindCartridgeAtStage(id); // Manipulate font of name string: the ID would be not evident when only one digit AND // didn't seem to work, coloring outside the button didn't seem to work if (mOnStageDlgIndex >= 0) { edit = (CEdit *)GetDlgItem(IDC_EDIT_MULGRID_NAME1 + mOnStageDlgIndex); if (edit) { edit->SetFont(m_statMgPrefix.GetFont()); edit->Invalidate(); } mOnStageDlgIndex = -1; } if (jcdInd < 0) { mMGTasks->SetLoadedGridIsAligned(0); return; } for (ind = 0; ind < mNumUsedSlots; ind++) { if (mDlgIndToJCDindex[ind] == jcdInd) { edit = (CEdit *)GetDlgItem(IDC_EDIT_MULGRID_NAME1 + ind); if (edit) { edit->SetFont(mBoldFont); edit->Invalidate(); } mOnStageDlgIndex = ind; jcd = mCartInfo->GetAt(jcdInd); mSelGridOnStage = jcd.station == JAL_STATION_STAGE; if (ind != oldInd) mMGTasks->SetLoadedGridIsAligned(0); UpdateEnables(); break; } } DisplayRunOrder(); Invalidate(); } /* * Set up for a single grid: add the dummy item to catalogue, make it selected & on stage */ void CMultiGridDlg::InitForSingleGrid() { JeolCartridgeData jcd; mNumUsedSlots = 1; jcd.Init(); jcd.name = jcd.userName = "TheOneGrid"; jcd.id = jcd.slot = 1; jcd.station = JAL_STATION_STAGE; mCartInfo->RemoveAll(); mCartInfo->Add(jcd); CButton *button = (CButton *)GetDlgItem(IDC_RADIO_MULGRID_SEL1); if (button) button->SetCheck(BST_CHECKED); mSelectedGrid = 0; ReloadTable(1, 1); NewGridOnStage(0); } /* * UPDATING, TRANSFERRING PARAMETERS */ /* * Update enable status of just about everything; set text for a few items */ void CMultiGridDlg::UpdateEnables() { ShortVec dlgInds, slotNums; JeolCartridgeData jcd; int ind, noTaskList[] = {IDC_CHECK_RUN_LMMS, IDC_RLMM_SEARCH, IDC_RLMM_VIEW, IDC_RLMM_CUR_OR_STATE, IDC_CHECK_SET_LMM_STATE, IDC_CHECK_REMOVE_OBJ, IDC_CHECK_SET_CONDENSER, IDC_RFULL_GRID_MONT, IDC_RNUM_MONT_PIECES, IDC_CHECK_USE_OVERLAP, IDC_CHECK_AUTOCONTOUR, IDC_BUT_SETUP_LMM_MONT, IDC_CHECK_TAKE_MMMS, IDC_RMMM_SEARCH, IDC_RMMM_VIEW, IDC_RMMM_CUR_OR_STATE, IDC_COMBO_MMM_STATE1, IDC_COMBO_MMM_STATE2, IDC_COMBO_MMM_STATE3, IDC_RFIXED_MONT, IDC_COMBO_MMM_STATE4, IDC_RSINGLE_IMAGE, IDC_RPOLYGON_MONT, IDC_BUT_SETUP_MAPPING, IDC_CHECK_RUN_FINAL_ACQ, IDC_BUT_SETUP_FINAL_ACQ, IDC_COMBO_FINAL_STATE1, IDC_COMBO_FINAL_STATE2, IDC_COMBO_FINAL_STATE3, IDC_COMBO_FINAL_STATE4}; bool locked = mMGTasks->GetNamesLocked(); BOOL justTasks = mWinApp->DoingTasks(); bool suspended = mMGTasks->GetSuspendedMulGrid(); BOOL tasks = justTasks || suspended; bool acqStatesEnabled = !tasks && (mSelectedGrid >= 0 || !m_bSetFinalByGrid) && mNumUsedSlots > 0; CString filename; EnableDlgItem(IDC_BUT_MG_GET_NAMES, (FEIscope || mCartInfo->GetSize() > 0) && !tasks && !locked); EnableDlgItem(IDC_BUT_MG_CLEAR, mNumUsedSlots > 0 && !tasks && !locked); EnableDlgItem(IDC_BUT_MG_RESET_NAMES, mNumUsedSlots > 0 && !tasks && !locked); EnableDlgItem(IDC_BUT_MG_INVENTORY, !tasks && !locked); EnableDlgItem(IDC_BUT_SET_CURRENT_DIR, !tasks && !locked); EnableDlgItem(IDC_CHECK_MG_USE_SUBDIRS, !tasks && !locked); EnableDlgItem(IDC_CHECK_MG_APPEND_NAME, !tasks && !locked); EnableDlgItem(IDC_EDIT_MG_PREFIX, !tasks && !locked); EnableDlgItem(IDC_CHECK_TOGGLE_ALL, mNumUsedSlots > 0 && !tasks && !mSettingOrder); EnableDlgItem(IDC_BUT_SET_ORDER, mNumUsedSlots > 0 && !tasks); EnableDlgItem(IDC_BUT_RESET_ORDER, mNumUsedSlots > 0 && !tasks && mMGTasks->GetUseCustomOrder()); EnableDlgItem(IDC_EDIT_GRID_NOTE, mNumUsedSlots > 0 && !justTasks && locked && mSelectedGrid >= 0); EnableDlgItem(IDC_BUT_LOAD_GRID, mNumUsedSlots > 0 && !tasks && mSelectedGrid >= 0 && !mSelGridOnStage); if (!tasks) filename = NavFileIfExistsAndNotLoaded(); EnableDlgItem(IDC_BUT_OPEN_NAV, !tasks && !filename.IsEmpty()); EnableDlgItem(IDC_BUT_SET_GRID_TYPE, mNumUsedSlots > 0 && !tasks && mSelectedGrid >= 0); if (mNumUsedSlots > 0 && !tasks && mSelectedGrid >= 0 && mSelGridOnStage) { jcd = FindCartDataForDlgIndex(mSelectedGrid); EnableDlgItem(IDC_BUT_REALIGN_TO_GRID_MAP, jcd.slot >= 0 && (jcd.status & MGSTAT_FLAG_LM_MAPPED)); } else EnableDlgItem(IDC_BUT_REALIGN_TO_GRID_MAP, false); EnableDlgItem(IDC_COMBO_LMM_STATE, m_bSetLMMstate && !tasks); EnableDlgItem(IDC_EDIT_CONDENSER, m_bSetCondenser && !tasks); EnableDlgItem(IDC_EDIT_MONT_XPCS, m_iLMMmontType > 0 && !tasks); EnableDlgItem(IDC_EDIT_MONT_NUM_YPCS, m_iLMMmontType > 0 && !tasks); EnableDlgItem(IDC_BUT_SETUP_AUTOCONT2, m_bAutocontour && !tasks); EnableDlgItem(IDC_BUT_SETUP_POLYMONT, m_iSingleVsPolyMont > 0 && !tasks); EnableDlgItem(IDC_BUT_START_RUN, ((m_bTakeLMMs || m_bTakeMMMs || m_bRunFinalAcq) && !tasks && GetListOfGridsToRun(dlgInds, slotNums) > 0 && (!mSingleGridMode || !m_strPrefix.IsEmpty())) || (suspended && !justTasks)); SetDlgItemText(IDC_BUT_START_RUN, suspended ? "End Run" : "Start Run"); SetDlgItemText(IDC_BUT_RUN_UNDONE, suspended ? "Resume Run" : "Run Undone"); EnableDlgItem(IDC_BUT_RUN_UNDONE, (mEnableRunUndone || suspended) && !justTasks); EnableDlgItem(IDC_EDIT_OVERLAP, m_bUseMontOverlap && !tasks); for (ind = 0; ind < sizeof(noTaskList) / sizeof(int); ind++) EnableDlgItem(noTaskList[ind], !tasks); for (ind = 0; ind < mNumUsedSlots; ind++) { EnableDlgItem(IDC_EDIT_MULGRID_NAME1 + ind, !tasks && !locked && !mSingleGridMode); EnableDlgItem(IDC_RADIO_MULGRID_SEL1 + ind, !tasks && !mSingleGridMode); EnableDlgItem(IDC_CHECK_MULGRID_RUN1 + ind, !tasks); } EnableDlgItem(IDC_COMBO_FINAL_STATE1, acqStatesEnabled); EnableDlgItem(IDC_COMBO_FINAL_STATE2, acqStatesEnabled); EnableDlgItem(IDC_COMBO_FINAL_STATE3, acqStatesEnabled); EnableDlgItem(IDC_COMBO_FINAL_STATE4, acqStatesEnabled); EnableDlgItem(IDC_CHECK_SET_FINAL_BY_GRID, !tasks && mNumUsedSlots > 0); EnableDlgItem(IDC_BUT_REVERT_TO_GLOBAL, !tasks && mSelectedGrid >= 0 && m_bSetFinalByGrid && mNumUsedSlots > 0); } /* * For the first step being done, checks if there are some done and some not done */ void CMultiGridDlg::CheckIfAnyUndoneToRun() { int grid, numDone = 0, numRun = 0, flag = 0; ShortVec jcdInds, slotNums; JeolCartridgeData jcd; mEnableRunUndone = false; if (m_bTakeLMMs) flag = MGSTAT_FLAG_LM_MAPPED; else if (m_bTakeMMMs) flag = MGSTAT_FLAG_MMM_DONE; else if (m_butRunFinalAcq) flag = MGSTAT_FLAG_ACQ_DONE; if (flag) { numRun = GetListOfGridsToRun(jcdInds, slotNums); for (grid = 0; grid < numRun; grid++) { jcd = mCartInfo->GetAt(jcdInds[grid]); if (jcd.status & flag) numDone++; } mEnableRunUndone = numRun > 0 && numDone > 0 && numDone < numRun; } } // Get the name of the frame location option set right void CMultiGridDlg::ManageFrameDirOption() { SetDlgItemText(IDC_CHECK_FRAMES_UNDER_SESSION, m_bUseSubdirs ? "Make frame directories under grid directories" : "Make frame directories under session directory"); } // Copy in master params and move them to dialog void CMultiGridDlg::UpdateSettings() { mParams = *mMasterParams; ParamsToDialog(); UpdateData(false); } /* * Update the current directory with the program-wide current dir or the locked-in working * directory */ void CMultiGridDlg::UpdateCurrentDir() { CRect rect; CDC *pDC = m_statCurrentDir.GetDC(); CString file = mMGTasks->GetNamesLocked() ? mMGTasks->GetWorkingDir() : mWinApp->mDocWnd->GetInitialDir(); int maxWidth; CString current = mMGTasks->GetNamesLocked() ? "Session" : "Current"; m_statCurrentDir.GetClientRect(rect); maxWidth = 18 * rect.Width() / 20; m_strCurrentDir = current + " dir: " + file; while ((pDC->GetTextExtent(m_strCurrentDir)).cx > maxWidth && file.GetLength() > 5) { file = file.Mid(1); m_strCurrentDir = current + " dir: ..." + file; } UpdateData(false); } /* * Adjust panel display after reloading IDs to drop in lower part of table */ void CMultiGridDlg::ManagePanels() { BOOL states[MAX_MULGRID_PANELS]; int ind; UINT singleDrops[] = {IDC_BUT_SET_GRID_TYPE, IDC_BUT_LOAD_GRID, IDC_BUT_MG_INVENTORY, IDC_BUT_MG_GET_NAMES, IDC_CHECK_MG_APPEND_NAME, IDC_BUT_MG_RESET_NAMES, IDC_BUT_MG_CLEAR, IDC_CHECK_SET_FINAL_BY_GRID, IDC_BUT_REVERT_TO_GLOBAL, IDC_CHECK_TOGGLE_ALL, IDC_BUT_RESET_ORDER, IDC_BUT_SET_ORDER, IDC_STAT_NOTE, IDC_EDIT_GRID_NOTE}; UINT MMMcomboIDs[4] = {IDC_COMBO_MMM_STATE1, IDC_COMBO_MMM_STATE2, IDC_COMBO_MMM_STATE3, IDC_COMBO_MMM_STATE4}; UINT finalComboIDs[4] = {IDC_COMBO_FINAL_STATE1, IDC_COMBO_FINAL_STATE2, IDC_COMBO_FINAL_STATE3, IDC_COMBO_FINAL_STATE4}; for (ind = 0; ind < MAX_MULGRID_PANELS; ind++) states[ind] = mPanelStates[ind]; if (mRightIsOpen <= 0) for (ind = 4; ind < 10; ind++) states[ind] = false; SetDlgItemText(IDC_BUT_CLOSE_RIGHT, mRightIsOpen > 0 ? "Close Right" : "Open Right"); mIDsToDrop.clear(); for (int ind = mNumUsedSlots; ind < MAX_DLG_SLOTS; ind++) { mIDsToDrop.push_back(IDC_CHECK_MULGRID_RUN1 + ind); mIDsToDrop.push_back(IDC_RADIO_MULGRID_SEL1 + ind); mIDsToDrop.push_back(IDC_EDIT_MULGRID_NAME1 + ind); mIDsToDrop.push_back(IDC_STAT_MULGRID_STATUS1 + ind); } DropComboBoxes(mNumMMMcombos, &MMMcomboIDs[0], IDC_STAT_SET_MMM_STATES); DropComboBoxes(mNumFinalCombos, &finalComboIDs[0], IDC_STAT_SET_FINAL_STATES); if (mDropFrameOption) mIDsToDrop.push_back(IDC_CHECK_FRAMES_UNDER_SESSION); if (mSingleGridMode) { for (ind = 0; ind < sizeof(singleDrops) / sizeof(UINT); ind++) mIDsToDrop.push_back(singleDrops[ind]); } AdjustPanels(states, sIdTable, sLeftTable, sTopTable, mNumInPanel, mPanelStart, 0, sHeightTable); } /* * Copy parameters from the local structure to the dialog */ void CMultiGridDlg::ParamsToDialog() { BOOL locked = mMGTasks->GetNamesLocked(); m_bAppendNames = locked ? mMGTasks->GetAppendNames() : mParams.appendNames; m_bUseSubdirs = locked ? mMGTasks->GetUseSubdirs() : mParams.useSubdirectory; m_bSetLMMstate = mParams.setLMMstate; m_iLMMacquireType = mParams.LMMstateType; m_bRemoveObjective = mParams.removeObjectiveAp; m_bSetCondenser = mParams.setCondenserAp; m_iCondenserSize = mParams.condenserApSize; m_iLMMmontType = mParams.LMMmontType; m_iXpieces = mParams.LMMnumXpieces; m_iYpieces = mParams.LMMnumYpieces; m_bUseMontOverlap = mParams.setLMMoverlap; m_iMontOverlap = mParams.LMMoverlapPct; m_bAutocontour = mParams.autocontour; m_iMMMacquireType = mParams.MMMstateType; m_bTakeLMMs = mParams.acquireLMMs; m_bTakeMMMs = mParams.acquireMMMs; m_bRunFinalAcq = mParams.runFinalAcq; m_iSingleVsPolyMont = mParams.MMMimageType; m_bFramesUnderSession = mParams.framesUnderSession; SetAllComboBoxesFromNameOrNum(); ManageFrameDirOption(); UpdateData(false); } /* * Unload the dialog into the local parameters */ void CMultiGridDlg::DialogToParams() { UPDATE_DATA_TRUE; if (!mMGTasks->GetNamesLocked()) { mParams.appendNames = m_bAppendNames; mParams.useSubdirectory = m_bUseSubdirs; } mParams.setLMMstate = m_bSetLMMstate; mParams.LMMstateType = m_iLMMacquireType; GetStateFromComboBox(m_comboLMMstate, mParams.LMMstateNum, mParams.LMMstateName, 0); mParams.removeObjectiveAp = m_bRemoveObjective; mParams.setCondenserAp = m_bSetCondenser; mParams.condenserApSize = m_iCondenserSize; mParams.LMMmontType = m_iLMMmontType; mParams.LMMnumXpieces = m_iXpieces; mParams.LMMnumYpieces = m_iYpieces; mParams.setLMMoverlap = m_bUseMontOverlap; mParams.LMMoverlapPct = m_iMontOverlap; mParams.autocontour = m_bAutocontour; mParams.MMMstateType = m_iMMMacquireType; mParams.acquireLMMs = m_bTakeLMMs; mParams.acquireMMMs = m_bTakeMMMs; mParams.runFinalAcq = m_bRunFinalAcq; mParams.MMMimageType = m_iSingleVsPolyMont; mParams.framesUnderSession = m_bFramesUnderSession; GetStateFromComboBox(m_comboMMMstate1, mParams.MMMstateNums[0], mParams.MMMstateNames[0], 1); GetStateFromComboBox(m_comboMMMstate2, mParams.MMMstateNums[1], mParams.MMMstateNames[1], 1); GetStateFromComboBox(m_comboMMMstate3, mParams.MMMstateNums[2], mParams.MMMstateNames[2], 1); GetStateFromComboBox(m_comboMMMstate4, mParams.MMMstateNums[3], mParams.MMMstateNames[3], 1); if (!m_bSetFinalByGrid) { GetFinalStateFomCombos(&mParams.finalStateNums[0], &mParams.finalStateNames[0], -1); } } /* * Get final states from combo boxes into param or grid jcd arrays */ void CMultiGridDlg::GetFinalStateFomCombos(int *stateNums, CString *stateNames, int skipInd) { if (skipInd != 0) GetStateFromComboBox(m_comboFinalState1, stateNums[0], stateNames[0], 1); if (skipInd != 1) GetStateFromComboBox(m_comboFinalState2, stateNums[1], stateNames[1], 1); if (skipInd != 2) GetStateFromComboBox(m_comboFinalState3, stateNums[2], stateNames[2], 1); if (skipInd != 3) GetStateFromComboBox(m_comboFinalState4, stateNums[3], stateNames[3], 1); } /* * Sync: unload and copy to master for use elsewhere */ void CMultiGridDlg::SyncToMasterParams() { UPDATE_DATA_TRUE; DialogToParams(); *mMasterParams = mParams; } /* * MANAGING COMBO BOXES AND STATES */ /* * Sets the selection in all the combo boxes */ void CMultiGridDlg::SetAllComboBoxesFromNameOrNum() { SetComboBoxFromNameOrNum(m_comboLMMstate, mParams.LMMstateNum, mParams.LMMstateName, 0); SetComboBoxFromNameOrNum(m_comboMMMstate1, mParams.MMMstateNums[0], mParams.MMMstateNames[0], 1); SetComboBoxFromNameOrNum(m_comboMMMstate2, mParams.MMMstateNums[1], mParams.MMMstateNames[1], 1); SetComboBoxFromNameOrNum(m_comboMMMstate3, mParams.MMMstateNums[2], mParams.MMMstateNames[2], 1); SetComboBoxFromNameOrNum(m_comboMMMstate4, mParams.MMMstateNums[3], mParams.MMMstateNames[3], 1); SetFinalStateComboBoxes(); } /* * Sets the selection for final acq boxes which can come from individual grids */ void CMultiGridDlg::SetFinalStateComboBoxes() { int *stateNums = &mParams.finalStateNums[0]; int numCombos = mNumFinalCombos; CString *stateNames = &mParams.finalStateNames[0]; if (m_bSetFinalByGrid && mSelectedGrid >= 0) { JeolCartridgeData &jcdEl = mCartInfo->ElementAt(mDlgIndToJCDindex[mSelectedGrid]); if (jcdEl.separateState) { stateNums = &jcdEl.acqStateNums[0]; stateNames = &jcdEl.acqStateNames[0]; } RepackStatesIfNeeded(mNumFinalCombos, stateNums, stateNames); if (numCombos < mNumFinalCombos) ManagePanels(); } SetComboBoxFromNameOrNum(m_comboFinalState1, stateNums[0], stateNames[0], 1); SetComboBoxFromNameOrNum(m_comboFinalState2, stateNums[1], stateNames[1], 1); SetComboBoxFromNameOrNum(m_comboFinalState3, stateNums[2], stateNames[2], 1); SetComboBoxFromNameOrNum(m_comboFinalState4, stateNums[3], stateNames[3], 1); } /* * Find the highest state used, repack them if this is more than the number of boxes * set by property, and increase that number of boxes if needed */ void CMultiGridDlg::RepackStatesIfNeeded(int &numBoxes, int *stateNums, CString *stateNames) { int ind, highest = 0, out = 0; for (ind = 0; ind < 4; ind++) if (stateNums[ind] >= 0) highest = ind; if (highest >= numBoxes) { for (ind = 0; ind < 4; ind++) { if (stateNums[ind] >= 0) { stateNums[out] = stateNums[ind]; stateNames[out++] = stateNames[ind]; } } for (ind = out; ind < 4; ind++) { stateNums[ind] = -1; stateNames[ind] = ""; } ACCUM_MAX(numBoxes, out); mMGTasks->SetAdocChanged(true); } } /* * Drop the combo boxes above the given number */ void CMultiGridDlg::DropComboBoxes(int numBoxes, UINT *comboIDs, UINT statID) { int ind; for (ind = numBoxes; ind < 4; ind++) mIDsToDrop.push_back(comboIDs[ind]); SetDlgItemText(statID, numBoxes > 1 ? "States:" : "State:"); if (!numBoxes) mIDsToDrop.push_back(statID); } /* * Given the nominal number and possible name of a state, find the right state to select * in the combo box */ void CMultiGridDlg::SetComboBoxFromNameOrNum(CComboBox &combo, int &num, CString &name, int addForNone) { StateParams *state; int ind, selInd = -1, numStates = (int)mStateArray->GetSize(); if (numStates) { // If there is a name, look it up by name and make sure it is unique if (!name.IsEmpty()) { ind = FindUniqueStateFromName(name); selInd = ind < 0 ? -1 : (ind + addForNone); } // By number - make sure its legal if (selInd < 0) { selInd = num + addForNone; B3DCLAMP(selInd, 0, numStates + addForNone - 1); } // Given the number now, get the current name - it will pass back into params num = selInd - addForNone; if (num >= 0) { state = mStateArray->GetAt(num); name = state->name; } else name = ""; } else { // No states, set up for base item in box. num = -addForNone; name = ""; selInd = addForNone - 1; } combo.SetCurSel(selInd); } /* * Find all the states that match a stored name and return index if there is just one */ int CMultiGridDlg::FindUniqueStateFromName(CString &name) { StateParams *state; int ind, numMatch = 0, stateInd = -1; for (ind = 0; ind < (int)mStateArray->GetSize(); ind++) { state = mStateArray->GetAt(ind); if (state->name == name) { if (!numMatch) stateInd = ind; numMatch++; } } return (numMatch != 1) ? stateInd : -1; } /* * Get selected state index and name from a combo box */ void CMultiGridDlg::GetStateFromComboBox(CComboBox &combo, int &num, CString &name, int addForNone) { StateParams *state; num = combo.GetCurSel() - addForNone; B3DCLAMP(num, -addForNone, (int)mStateArray->GetSize() - 1); if (num < 0) name = ""; else if (mStateArray->GetSize() > 0) { state = mStateArray->GetAt(num); name = state->name; } } /* * Load the current states into the combo box */ void CMultiGridDlg::LoadStatesInComboBox(CComboBox &combo, bool addNone) { CString str, fullStr, loadStr; StateParams *state; CRect rect; CDC *pDC = combo.GetDC(); int ind, jnd, token, minusOne = -1, maxWidth, numStates = (int)mStateArray->GetSize(); if (!numStates) { combo.EnableWindow(false); return; } if (addNone) combo.AddString("None"); for (ind = 0; ind < numStates; ind++) { state = mStateArray->GetAt(ind); CStateDlg::StateToListString(state, fullStr, " ", ind, &minusOne, 1, false); loadStr.Format("%d:", ind + 1); for (token = 0; token < 4; token++) { jnd = fullStr.Find(" "); if ((token % 2) == 0 || state->name.IsEmpty() || (token == 1 && fullStr.Left(jnd) == "0")) { loadStr += " " + fullStr.Left(jnd); if (token == 2) loadStr += "x"; } if (token == 0 && state->montMapConSet) loadStr += "M"; fullStr = fullStr.Mid(jnd + 1); } if (!state->name.IsEmpty()) loadStr += ": " + state->name; combo.GetClientRect(rect); maxWidth = 17 * rect.Width() / 20; if (pDC->GetTextExtent(loadStr).cx > maxWidth) { while ((pDC->GetTextExtent(loadStr + "...")).cx > maxWidth && loadStr.GetLength() > 5) loadStr = loadStr.Left(loadStr.GetLength() - 1); loadStr += "..."; } combo.AddString((LPCTSTR)loadStr); } combo.ReleaseDC(pDC); SetDropDownHeight(&combo, B3DMIN(MAX_DROPDOWN_TO_SHOW, numStates)); } /* * Load all the combo boxes */ void CMultiGridDlg::LoadAllComboBoxes() { LoadStatesInComboBox(m_comboLMMstate, false); LoadStatesInComboBox(m_comboMMMstate1, true); LoadStatesInComboBox(m_comboMMMstate2, true); LoadStatesInComboBox(m_comboMMMstate3, true); LoadStatesInComboBox(m_comboMMMstate4, true); LoadStatesInComboBox(m_comboFinalState1, true); LoadStatesInComboBox(m_comboFinalState2, true); LoadStatesInComboBox(m_comboFinalState3, true); LoadStatesInComboBox(m_comboFinalState4, true); } /* * Check the selection in a combo box against others, make sure it doesn't create an * illegal situation and revert if it does */ void CMultiGridDlg::ProcessMultiStateCombo(CComboBox &combo, int *stateNums, CString *stateNames, int index, int gridID) { StateParams *state, *othState; int cmb, oth, numLD = 0, numNon = 0, camera = -1, prevNum = stateNums[index]; CString prevName = stateNames[index]; CString gridPref; bool sameArea = false; GetStateFromComboBox(combo, stateNums[index], stateNames[index], 1); mWinApp->RestoreViewFocus(); if (stateNums[index] < 0) return; if (gridID > 0) gridPref.Format("For grid # %d: ", gridID); for (cmb = 0; cmb < 4; cmb++) { if (stateNums[cmb] >= 0 && stateNums[cmb] < (int)mStateArray->GetSize()) { state = mStateArray->GetAt(stateNums[cmb]); if (state->lowDose) numLD++; else numNon++; if (camera < 0) camera = state->camIndex; else if (camera != state->camIndex) break; for (oth = 0; oth < cmb && state->lowDose; oth++) { if (stateNums[oth] >= 0 && stateNums[oth] < (int)mStateArray->GetSize()) { othState = mStateArray->GetAt(stateNums[oth]); if (othState->lowDose == state->lowDose) { sameArea = true; break; } } } } } if (!(numNon > 1 || (numNon && numLD) || (camera >= 0 && camera != state->camIndex) || sameArea)) return; if (numNon > 1) AfxMessageBox(gridPref + "Only one non-Low Dose state can be selected", MB_EXCLAME); else if (numNon && numLD) AfxMessageBox(gridPref + "You cannot select both Low Dose and non-Low Dose states", MB_EXCLAME); else if (sameArea) AfxMessageBox(gridPref + "You cannot select more than one state in the same Low Dose" " area", MB_EXCLAME); else AfxMessageBox(gridPref + "All selected states for one phase must be for the same " "camera", MB_EXCLAME); stateNames[index] = prevName; stateNums[index] = prevNum; SetComboBoxFromNameOrNum(combo, stateNums[index], stateNames[index], 1); } /* * Set either the combo boxes or separate state flag for grid when show grid states is on */ void CMultiGridDlg::HandlePerGridStateChange() { if (mSelectedGrid >= 0) { JeolCartridgeData &jcdEl = mCartInfo->ElementAt(mDlgIndToJCDindex[mSelectedGrid]); // If it already has states, set the combo boxes from them if (jcdEl.separateState) { SetFinalStateComboBoxes(); } else { // Otherwise set from current values in combos jcdEl.separateState = 1; GetFinalStateFomCombos(&jcdEl.acqStateNums[0], &jcdEl.acqStateNames[0], -1); SetStatusText(mDlgIndToJCDindex[mSelectedGrid]); mMGTasks->SetAdocChanged(true); } } UpdateEnables(); } /* * MESSAGE HANDLERS FOR THE ACTION SECTIONS OF THE DIALOG */ // Open-close setup section void CMultiGridDlg::OnButMgSetup() { mPanelStates[3] = !mPanelStates[3]; SetDlgItemText(IDC_BUT_MG_SETUP, mPanelStates[3] ? "-" : "+"); ManagePanels(); mWinApp->RestoreViewFocus(); } // Open/close low mag map section void CMultiGridDlg::OnButMgLowMagMaps() { mPanelStates[5] = !mPanelStates[5]; SetDlgItemText(IDC_BUT_MG_LOW_MAG_MAPS, mPanelStates[5] ? "-" : "+"); ManagePanels(); mWinApp->RestoreViewFocus(); } // Open/close medium mag map section void CMultiGridDlg::OnButMgMediumMagMaps() { mPanelStates[7] = !mPanelStates[7]; SetDlgItemText(IDC_BUT_MG_MEDIUM_MAG_MAPS, mPanelStates[7] ? "-" : "+"); ManagePanels(); mWinApp->RestoreViewFocus(); } // open/close final acquisition section void CMultiGridDlg::OnButMgFinalAcq() { mPanelStates[9] = !mPanelStates[9]; SetDlgItemText(IDC_BUT_MG_FINAL_ACQ, mPanelStates[9] ? "-" : "+"); ManagePanels(); mWinApp->RestoreViewFocus(); } // Button to open or close right side void CMultiGridDlg::OnButCloseRight() { mRightIsOpen = mRightIsOpen > 0 ? 0 : 1; ManagePanels(); mWinApp->RestoreViewFocus(); } // Close everything, or reopen to saved state void CMultiGridDlg::OnButCloseAll() { int ind; SetDlgItemText(IDC_BUT_CLOSE_ALL, mClosedAll ? "-" : "+"); for (ind = 1; ind < MAX_MULGRID_PANELS; ind++) { if (mClosedAll) { mPanelStates[ind] = mSavedPanelStates[ind]; } else { mSavedPanelStates[ind] = mPanelStates[ind]; mPanelStates[ind] = false; } } mClosedAll = !mClosedAll; ManagePanels(); mWinApp->RestoreViewFocus(); } // The actual checkbox for running grid maps void CMultiGridDlg::OnCheckRunLmms() { UPDATE_DATA_TRUE; mPanelStates[5] = m_bTakeLMMs; SetDlgItemText(IDC_BUT_MG_LOW_MAG_MAPS, mPanelStates[5] ? "-" : "+"); m_butTakeLMMs.SetFont(m_bTakeLMMs ? &mBigBoldFont : &mBiggerFont); ManagePanels(); mWinApp->RestoreViewFocus(); CheckIfAnyUndoneToRun(); UpdateEnables(); } // The actual checkbox for running medium mag maps void CMultiGridDlg::OnCheckTakeMmms() { UPDATE_DATA_TRUE; mPanelStates[7] = m_bTakeMMMs; SetDlgItemText(IDC_BUT_MG_MEDIUM_MAG_MAPS, mPanelStates[7] ? "-" : "+"); m_butTakeMMMs.SetFont(m_bTakeMMMs ? &mBigBoldFont : &mBiggerFont); ManagePanels(); mWinApp->RestoreViewFocus(); CheckIfAnyUndoneToRun(); UpdateEnables(); } // The actual checkbox for running final acquisition void CMultiGridDlg::OnCheckRunFinalAcq() { UPDATE_DATA_TRUE; mPanelStates[9] = m_bRunFinalAcq; SetDlgItemText(IDC_BUT_MG_FINAL_ACQ, mPanelStates[9] ? "-" : "+"); m_butRunFinalAcq.SetFont(m_bRunFinalAcq ? &mBigBoldFont : &mBiggerFont); ManagePanels(); mWinApp->RestoreViewFocus(); CheckIfAnyUndoneToRun(); UpdateEnables(); } // Open autocontour setup dialog void CMultiGridDlg::OnButSetupAutocont() { int ind, *showGroup; int *storedGroups = mMGTasks->GetAutoContGroups(); if (storedGroups) { showGroup = mWinApp->mNavHelper->mAutoContouringDlg->GetShowGroup(); for (ind = 0; ind < MAX_AUTOCONT_GROUPS; ind++) showGroup[ind] = storedGroups[ind]; } mWinApp->mNavHelper->OpenAutoContouring(true); mWinApp->RestoreViewFocus(); } // A button for selecting the grid to act on is pressed void CMultiGridDlg::OnRadioMulgridSelect(UINT nID) { CButton *button; JeolCartridgeData jcd; CString filename; int runInd, numAdd; jcd.slot = -1; button = (CButton *)GetDlgItem(nID); // Make button unchecked or checked (pushed) if (mSelectedGrid == nID - IDC_RADIO_MULGRID_SEL1) { if (button) button->SetCheck(BST_UNCHECKED); mSelectedGrid = -1; } else { if (button) button->SetCheck(BST_CHECKED); mSelectedGrid = nID - IDC_RADIO_MULGRID_SEL1; jcd = FindCartDataForDlgIndex(mSelectedGrid); if (mSettingOrder) { runInd = LookupRunOrder(*mCustomRunDlgInds, mSelectedGrid); if (runInd >= 0) { VEC_REMOVE_AT((*mCustomRunDlgInds), runInd); mWasAddedToOrder[mSelectedGrid] = 0; numAdd = GetNumAddedToOrder(); mCustomRunDlgInds->insert(mCustomRunDlgInds->begin() + numAdd, mSelectedGrid); mWasAddedToOrder[mSelectedGrid] = 1; if (numAdd + 1 == (int)mCustomRunDlgInds->size()) OnButSetOrder(); } DisplayRunOrder(); } } if (m_bSetFinalByGrid) HandlePerGridStateChange(); else EnableDlgItem(IDC_BUT_REVERT_TO_GLOBAL, false); if (mSelectedGrid < 0) m_strNote = ""; else m_strNote = jcd.note; EnableDlgItem(IDC_EDIT_GRID_NOTE, mMGTasks->GetNamesLocked() && mSelectedGrid >= 0); UpdateData(false); // See if it is grid on stage and set load, open and realign buttons mSelGridOnStage = jcd.slot >= 0 && jcd.station == JAL_STATION_STAGE; EnableDlgItem(IDC_BUT_LOAD_GRID, jcd.slot >= 0 && !mSelGridOnStage); EnableDlgItem(IDC_BUT_REALIGN_TO_GRID_MAP, jcd.slot >= 0 && mSelGridOnStage && (jcd.status & MGSTAT_FLAG_LM_MAPPED)); filename = NavFileIfExistsAndNotLoaded(); EnableDlgItem(IDC_BUT_OPEN_NAV, !filename.IsEmpty()); EnableDlgItem(IDC_BUT_SET_GRID_TYPE, jcd.slot >= 0); if (mWinApp->mNavHelper->mMGSettingsDlg) mWinApp->mNavHelper->mMGSettingsDlg->SetJcdIndex(mSelectedGrid < 0 ? -1 : mDlgIndToJCDindex[mSelectedGrid]); if (filename && GetAsyncKeyState(VK_CONTROL) / 2 != 0) { mWinApp->mNavigator->LoadNavFile(false, false, &filename); UpdateEnables(); } m_statCurrentDir.SetFocus(); mWinApp->RestoreViewFocus(); } // A checkbox for running a grid is pressed void CMultiGridDlg::OnCheckMulgridRun(UINT nID) { int numAdded, runInd, dlgInd = nID - IDC_CHECK_MULGRID_RUN1; UPDATE_DATA_TRUE; if (mMGTasks->GetUseCustomOrder()) { CButton *button = (CButton *)GetDlgItem(nID); if (button) { if (button->GetCheck() == BST_CHECKED) { // Checking button: insert it in custom list if setting, or add to end if (mSettingOrder) { numAdded = GetNumAddedToOrder(); mCustomRunDlgInds->insert(mCustomRunDlgInds->begin() + numAdded, dlgInd); mWasAddedToOrder[dlgInd] = 1; } else { mCustomRunDlgInds->push_back(dlgInd); } } else { // Unchecking: find in list and remove runInd = LookupRunOrder(*mCustomRunDlgInds, dlgInd); if (runInd >= 0) VEC_REMOVE_AT((*mCustomRunDlgInds), runInd); if (mSettingOrder) mWasAddedToOrder[dlgInd] = 0; } } } CheckIfAnyUndoneToRun(); UpdateEnables(); DisplayRunOrder(); mWinApp->RestoreViewFocus(); } // Toggle all run checkboxes on or off void CMultiGridDlg::OnCheckToggleAll() { CButton *button; int loop, ind; UPDATE_DATA_TRUE; for (loop = 0; loop < mNumUsedSlots; loop++) { ind = FEIscope ? mNumUsedSlots - (loop + 1) : loop; button = (CButton *)GetDlgItem(IDC_CHECK_MULGRID_RUN1 + ind); if (button) { if (m_bToggleAll && mMGTasks->GetUseCustomOrder() && LookupRunOrder(*mCustomRunDlgInds, ind) < 0) mCustomRunDlgInds->push_back(ind); button->SetCheck(m_bToggleAll ? BST_CHECKED : BST_UNCHECKED); } } if (!m_bToggleAll) mCustomRunDlgInds->clear(); CheckIfAnyUndoneToRun(); UpdateEnables(); DisplayRunOrder(); mWinApp->RestoreViewFocus(); } // Start procedure to set order, or end it void CMultiGridDlg::OnButSetOrder() { mSettingOrder = !mSettingOrder; SetDlgItemText(IDC_BUT_SET_ORDER, mSettingOrder ? "Stop Setting" : "Set Order"); if (mSettingOrder) { if (!mMGTasks->GetUseCustomOrder()) { mMGTasks->SetUseCustomOrder(true); DefaultRunDlgIndexes(*mCustomRunDlgInds); } CLEAR_RESIZE(mWasAddedToOrder, short, mNumUsedSlots); } UpdateEnables(); mWinApp->RestoreViewFocus(); } // Reset custom order void CMultiGridDlg::OnButResetOrder() { if (mSettingOrder) OnButSetOrder(); mMGTasks->SetUseCustomOrder(false); DisplayRunOrder(); UpdateEnables(); mWinApp->RestoreViewFocus(); } // Count the nunber of grids added to the order list int CMultiGridDlg::GetNumAddedToOrder() { int num = 0, ind; if (!mSettingOrder) return (int)mCustomRunDlgInds->size(); for (ind = 0; ind < mNumUsedSlots; ind++) if (mWasAddedToOrder[ind]) num++; return num; } // The note has lost focus, process the change void CMultiGridDlg::OnEnKillfocusEditGridNote() { UPDATE_DATA_TRUE; mWinApp->RestoreViewFocus(); if (mSelectedGrid < 0) return; int jcdInd = mDlgIndToJCDindex[mSelectedGrid]; JeolCartridgeData &jcdEl = mCartInfo->ElementAt(jcdInd); jcdEl.note = m_strNote; mMGTasks->SetAdocChanged(true); SetDlgItemText(IDC_EDIT_MULGRID_NAME1 + mSelectedGrid, UserNameWithNote(jcdEl.userName, m_strNote)); } // Open navigator file void CMultiGridDlg::OnButOpenNav() { CFileStatus status; CString filename = NavFileIfExistsAndNotLoaded(); if (!filename.IsEmpty()) mWinApp->mNavigator->LoadNavFile(false, false, &filename); mWinApp->RestoreViewFocus(); UpdateEnables(); } // Get name of nav file if it is needed for loading CString CMultiGridDlg::NavFileIfExistsAndNotLoaded() { CString filename; if (mSelectedGrid < 0 || !mMGTasks->GetNamesLocked()) return filename; filename = mMGTasks->FullGridFilePath(-mDlgIndToJCDindex[mSelectedGrid] - 1, ".nav"); if (UtilFileExists(filename) && filename != mWinApp->mNavigator->GetCurrentNavFile()) return filename; return ""; } // Load selected grid void CMultiGridDlg::OnButLoadGrid() { JeolCartridgeData jcd; mWinApp->RestoreViewFocus(); if (mSelectedGrid < 0) return; int jcdInd = mDlgIndToJCDindex[mSelectedGrid]; jcd = mCartInfo->GetAt(jcdInd); mMGTasks->LoadOrUnloadGrid(FEIscope ? jcd.slot : jcdInd + 1, MG_USER_LOAD); } // Realign to the grid map void CMultiGridDlg::OnButRealignToGridMap() { CString errStr; mWinApp->RestoreViewFocus(); if (mMGTasks->RealignToGridMap(mDlgIndToJCDindex[mSelectedGrid], true, errStr) > 0) AfxMessageBox("Failed to realign to grid map: " + errStr); } // Set some individual grid processing parameters void CMultiGridDlg::OnButSetGridType() { mWinApp->RestoreViewFocus(); if (mSelectedGrid < 0) return; mWinApp->mNavHelper->OpenMGSettingsDlg(mDlgIndToJCDindex[mSelectedGrid]); } // Radio buttons for what to use for imaging LMM void CMultiGridDlg::OnRadioLMMSearch() { UPDATE_DATA_TRUE; mWinApp->RestoreViewFocus(); } // Checkbox to enable setting/using LMM state void CMultiGridDlg::OnCheckSetLmmState() { UPDATE_DATA_TRUE; EnableDlgItem(IDC_COMBO_LMM_STATE, m_bSetLMMstate); mWinApp->RestoreViewFocus(); } // Checkbox to enable setting condenser void CMultiGridDlg::OnCheckSetCondenser() { UPDATE_DATA_TRUE; EnableDlgItem(IDC_EDIT_CONDENSER, m_bSetCondenser); mWinApp->RestoreViewFocus(); } // New condenser aperture size entered void CMultiGridDlg::OnEnKillfocusEditCondenser() { UPDATE_DATA_TRUE; mWinApp->RestoreViewFocus(); } // Select autocontouring void CMultiGridDlg::OnCheckAutocontour() { UPDATE_DATA_TRUE; EnableDlgItem(IDC_BUT_SETUP_AUTOCONT2, m_bAutocontour); mWinApp->RestoreViewFocus(); } // Button to set up the LM montage void CMultiGridDlg::OnButSetupLmmMont() { UPDATE_DATA_TRUE; DoSetupLMMmont(false); mWinApp->RestoreViewFocus(); } // Button to use specific overlap void CMultiGridDlg::OnCheckUseOverlap() { UPDATE_DATA_TRUE; EnableDlgItem(IDC_EDIT_OVERLAP, m_bUseMontOverlap); mWinApp->RestoreViewFocus(); } // New percent overlap entered void CMultiGridDlg::OnEnKillfocusEditOverlap() { UPDATE_DATA_TRUE; mWinApp->RestoreViewFocus(); } // New # of X pieces entered void CMultiGridDlg::OnEnKillfocusEditMontXpcs() { UPDATE_DATA_TRUE; mWinApp->RestoreViewFocus(); } // New # of Y pieces entered void CMultiGridDlg::OnEnKillfocusEditMontNumYpcs() { UPDATE_DATA_TRUE; mWinApp->RestoreViewFocus(); } // Radio buttons to select what kind of montage to take void CMultiGridDlg::OnRfullGridMont() { UPDATE_DATA_TRUE; mWinApp->RestoreViewFocus(); UpdateEnables(); } // New state selected in LMM combo box void CMultiGridDlg::OnSelendokComboLmmState() { mWinApp->RestoreViewFocus(); GetStateFromComboBox(m_comboLMMstate, mParams.LMMstateNum, mParams.LMMstateName, 0); } // New state selected in MMM combo boxes void CMultiGridDlg::OnSelendokComboMmmState1() { ProcessMultiStateCombo(m_comboMMMstate1, mParams.MMMstateNums, mParams.MMMstateNames, 0, -1); } void CMultiGridDlg::OnSelendokComboMmmState2() { ProcessMultiStateCombo(m_comboMMMstate2, mParams.MMMstateNums, mParams.MMMstateNames, 1, -1); } void CMultiGridDlg::OnSelendokComboMmmState3() { ProcessMultiStateCombo(m_comboMMMstate3, mParams.MMMstateNums, mParams.MMMstateNames, 2, -1); } void CMultiGridDlg::OnSelendokComboMmmState4() { ProcessMultiStateCombo(m_comboMMMstate4, mParams.MMMstateNums, mParams.MMMstateNames, 3, -1); } // New state selected in final acquire combo boxes void CMultiGridDlg::OnSelendokComboFinalState1() { ProcessFinalStateCombo(m_comboFinalState1, 0); } void CMultiGridDlg::OnSelendokComboFinalState2() { ProcessFinalStateCombo(m_comboFinalState2, 1); } void CMultiGridDlg::OnSelendokComboFinalState3() { ProcessFinalStateCombo(m_comboFinalState3, 2); } void CMultiGridDlg::OnSelendokComboFinalState4() { ProcessFinalStateCombo(m_comboFinalState4, 3); } /* * For a final state combo box change, need to set arrays for global or per grid values */ void CMultiGridDlg::ProcessFinalStateCombo(CComboBox &combo, int index) { int *stateNums = mParams.finalStateNums; CString *stateNames = mParams.finalStateNames; JeolCartridgeData &jcdEl = mCartInfo->ElementAt( mDlgIndToJCDindex[B3DMAX(0, mSelectedGrid)]); int gridID = -1; if (mSelectedGrid >= 0 && m_bSetFinalByGrid) { stateNums = jcdEl.acqStateNums; stateNames = jcdEl.acqStateNames; // If separate state was not on before, turn it on, get all the states but this one // from the other combos, and take this (previous) state from global params // This should happen only after a a revert if (!jcdEl.separateState) { jcdEl.separateState = 1; GetFinalStateFomCombos(stateNums, stateNames, index); jcdEl.acqStateNums[index] = mParams.finalStateNums[index]; jcdEl.acqStateNames[index] = mParams.finalStateNames[index]; SetStatusText(mDlgIndToJCDindex[mSelectedGrid]); } } ProcessMultiStateCombo(combo, stateNums, stateNames, index, gridID); mMGTasks->SetAdocChanged(true); } // Check box to set state grid by grid void CMultiGridDlg::OnCheckSetFinalByGrid() { UPDATE_DATA_TRUE; HandlePerGridStateChange(); mWinApp->RestoreViewFocus(); } // Button to revert state of current grid to global void CMultiGridDlg::OnButRevertToGlobal() { mWinApp->RestoreViewFocus(); if (mSelectedGrid < 0) return; JeolCartridgeData &jcdEl = mCartInfo->ElementAt(mDlgIndToJCDindex[mSelectedGrid]); jcdEl.separateState = 0; for (int ind = 0; ind < 4; ind++) { jcdEl.acqStateNums[ind] = 0; jcdEl.acqStateNames[ind] = ""; } SetFinalStateComboBoxes(); SetStatusText(mDlgIndToJCDindex[mSelectedGrid]); EnableDlgItem(IDC_BUT_REVERT_TO_GLOBAL, false); mMGTasks->SetAdocChanged(true); } // Check for frame dir under session/grid dir void CMultiGridDlg::OnCheckFramesUnderSession() { UpdateData(true); mWinApp->RestoreViewFocus(); } // Button to open nav acquire for final acquisition params void CMultiGridDlg::OnButSetupFinalAcq() { mWinApp->mNavigator->AcquireAreas(NAVACQ_SRC_MG_SET_ACQ, false, false); mWinApp->RestoreViewFocus(); } // Button to open nav acquire for mapping params void CMultiGridDlg::OnButSetupMapping() { mWinApp->mNavigator->AcquireAreas(NAVACQ_SRC_MG_SET_MMM, false, false); mWinApp->RestoreViewFocus(); } // Setup button for MMM montage, polygon or fixed void CMultiGridDlg::OnButSetupPolymont() { SetupMMMacquire(false); mWinApp->RestoreViewFocus(); } // Radio buttons for single image, polygon, or fixed montage void CMultiGridDlg::OnRsingleImage() { UPDATE_DATA_TRUE; EnableDlgItem(IDC_BUT_SETUP_POLYMONT, m_iSingleVsPolyMont > 0); mWinApp->RestoreViewFocus(); } // Radio buttons for image acquisition type of MMM void CMultiGridDlg::OnRmmmSearch() { UPDATE_DATA_TRUE; mWinApp->RestoreViewFocus(); } /* * SETUP AND SUPPORT FUNCTIONS */ /* * Set up the grid montage initially or when going to run */ int CMultiGridDlg::DoSetupLMMmont(bool skipDlg) { BOOL lowDose = mWinApp->LowDoseMode(); bool refind = false; int ind, ldArea = -1, stateMag = 0, camera = mWinApp->GetCurrentCamera(); int consNum, err; float overlapFrac; LowDoseParams *ldp; ControlSet *conSet; MontParam *montP = mMGTasks->GetGridMontParam(); CString str; StateParams *state; CMontageSetupDlg montDlg; if (m_bUseMontOverlap) { montP->minMicronsOverlap = 1.f; montP->minOverlapFactor = (float)(m_iMontOverlap / 100.); } // If there is a state, first make sure its still where it should be if (m_bSetLMMstate) { state = GetOrRefindState(mParams.LMMstateNum, mParams.LMMstateName, "the state for grid mapping", m_comboLMMstate); if (!state) return 1; // Set low dose and its area from state lowDose = state->lowDose != 0; ldArea = -1; if (lowDose) ldArea = mWinApp->mNavHelper->AreaFromStateLowDoseValue(state, NULL); // Insist the state have something to do with the designated acquisition if ((m_iLMMacquireType == 0 && ldArea != SEARCH_AREA) || (m_iLMMacquireType == 1 && ldArea != VIEW_CONSET)) { str.Format("You selected to acquire with %s but to set a %s.\n" "Resolve this discrepancy before setting up the montage", m_iLMMacquireType ? "View" : "Search", lowDose ? "state for a different Low Dose area" : "non-Low Dose state"); AfxMessageBox(str, MB_EXCLAME); return 1; } // Get camera and mag from state either way if (lowDose) { montP->magIndex = state->ldParams.magIndex; montP->useMontMapParams = ldArea == RECORD_CONSET && state->montMapConSet; } else { montP->magIndex = state->magIndex; montP->useMontMapParams = state->montMapConSet; } camera = state->camIndex; montP->binning = state->binning; stateMag = montP->magIndex; mLMneedsLowDose = 0; } else { // No state: View or Search means low dose, otherwise current mode determines if LD if (m_iLMMacquireType == 0) { ldArea = SEARCH_AREA; lowDose = true; } else if (m_iLMMacquireType == 1) { ldArea = VIEW_CONSET; lowDose = true; } else if (lowDose) { // If current mode is LD, ldArea = mScope->GetLowDoseArea(); if (ldArea < 0) { if (montP->useSearchInLowDose) ldArea = SEARCH_AREA; else if (montP->useViewInLowDose) ldArea = VIEW_CONSET; else if (montP->useMontMapParams) ldArea = RECORD_CONSET; } if (ldArea < 0) { AfxMessageBox("You selected to used the current state and Low Dose\n" "mode is on, but there is neither a current low dose area\n" "nor do the current montage parameters specify to use View or Search " "in Low Dose.\n" "Resolve this problem before setting up the montage", MB_EXCLAME); return 1; } } else { // Non low dose: get mag index and that is it montP->magIndex = mScope->GetMagIndex(); } if (lowDose) { ldp = mWinApp->GetLowDoseParams() + ldArea; montP->magIndex = ldp->magIndex; } // Set the binning consNum = MontageConSetNum(montP, true, lowDose ? 1 : 0); conSet = mWinApp->GetConSets() + consNum; montP->binning = conSet->binning; mLMneedsLowDose = lowDose ? 1 : -1; } montP->useViewInLowDose = ldArea == VIEW_CONSET; montP->useSearchInLowDose = ldArea == SEARCH_AREA; ind = mWinApp->LookupActiveCamera(camera); if (ind < 0) { AfxMessageBox("The camera for the state to be set is not in the active list", MB_EXCLAME); return 1; } montP->cameraIndex = ind; montP->setupInLowDose = lowDose; montP->skipOutsidePoly = false; montP->skipCorrelations = false; montP->ignoreSkipList = false; montP->warnedConSetBin = true; overlapFrac = m_bUseMontOverlap ? (float)(m_iMontOverlap / 100.) : 0.f; if (m_iLMMmontType == 0) { // Setup full montage err = mWinApp->mNavigator->FullMontage(skipDlg, overlapFrac, SETUPMONT_MG_FULL_GRID); if (!err && stateMag > 0 && montP->magIndex != stateMag) { str.Format("You selected to set a state at %dx but changed the mag to %d" " in Montage Setup\n\nDo you want to proceed with these settings?", MagForCamera(camera, stateMag), MagForCamera(camera, montP->magIndex)); if (AfxMessageBox(str, MB_QUESTION) != IDYES) err = 1; } mGridMontSetAtXpcs = 0; } else { // Setup specific piece number montP->xNframes = m_iXpieces; montP->yNframes = m_iYpieces; if (m_bSetLMMstate) mWinApp->mDocWnd->MontParamInitFromFrame(montP, camera, state->xFrame, state->yFrame, overlapFrac); else mWinApp->mDocWnd->MontParamInitFromConSet(montP, consNum, overlapFrac); montP->moveStage = true; err = 0; if (!skipDlg) { montDlg.mForMultiGridMap = SETUPMONT_MG_LM_NBYN; montDlg.mSizeLocked = false; montDlg.mParam = *montP; err = montDlg.DoModal() != IDOK ? 1 : 0; if (!err) *montP = montDlg.mParam; } mGridMontSetAtXpcs = m_iXpieces; mGridMontSetAtYpcs = m_iYpieces; } mGridMontSetupOK = err == 0; if (!err) { mGridMontSetupState = mParams.LMMstateNum; mGridMontSetupOverlap = m_bUseMontOverlap ? m_iMontOverlap : 0; mGridMontSetupAcqType = m_iLMMacquireType; if (mMGTasks->SaveSessionFile(str) > 0) AfxMessageBox(str, MB_EXCLAME); } return err; } /* * Look for state by its index, and if name doesn't matc, look for it by name * and correct the index */ StateParams *CMultiGridDlg::GetOrRefindState(int &stateNum, CString &stateName, const char *descrip, CComboBox &combo) { StateParams *state; bool refind = false; CString str, str2; int ind; if (stateNum >= (int)mStateArray->GetSize()) { refind = true; } else { state = mStateArray->GetAt(stateNum); if (state->name != stateName) refind = true; } if (refind) { // Look for it again from the name if possible if (stateName.IsEmpty()) ind = -1; else ind = FindUniqueStateFromName(stateName); // Bail out if can't identify it with confidence if (ind < 0) { str.Format("The set of states seems to have changed since state # %d ", stateNum + 1); if (!stateName.IsEmpty()) str += "(" + stateName + ") "; str += "was selected for "; str += descrip; str += ".\nYou need to check the selection of this state" " before proceeding.\n\nDo you want to reload the combo box " "with the current states first?"; if (AfxMessageBox(str, MB_QUESTION) == IDYES) { LoadAllComboBoxes(); SetAllComboBoxesFromNameOrNum(); } return NULL; } stateNum = ind; state = mStateArray->GetAt(ind); } return state; } /* * For MMM or final acquire, check validity of states: one camera, one non-LD or multiple * LD states are allowed. This has all been checked when combo boxes were set... */ int CMultiGridDlg::CheckMultipleStates(CComboBox **comboArr, int *stateNums, CString *stateNames, CString descrip, int &numStates, int &camera, StateParams **states, int *lowDose, int *magInds) { int retVal = 0, ind, jnd, numNon = 0, numLD = 0; StateParams *state; camera = -1; numStates = 0; for (ind = 0; ind < 4; ind++) { if (stateNums[ind] >= 0) { state = GetOrRefindState(stateNums[ind], stateNames[ind], descrip, *(comboArr[ind])); if (!state) return 1; if (state->lowDose) { numLD++; magInds[numStates] = state->ldParams.magIndex; for (jnd = 0; jnd < numStates; jnd++) { if (state->lowDose == lowDose[jnd]) { AfxMessageBox("You have selected more that one state of the same Low Dose " "type for " + descrip + ", which makes no sense", MB_EXCLAME); return 1; } } } else { numNon++; magInds[numStates] = state->magIndex; } if (camera < 0) camera = state->camIndex; else if (camera != state->camIndex) break; states[numStates] = state; lowDose[numStates++] = state->lowDose; } } if (!(numNon > 1 || (numNon && numLD) || (camera >= 0 && camera != state->camIndex))) return 0; if (numNon > 1) AfxMessageBox("Only one non-Low Dose state can be selected for " + descrip, MB_EXCLAME); else if (numNon && numLD) AfxMessageBox("You cannot select both Low Dose and non-Low Dose states for " + descrip, MB_EXCLAME); else AfxMessageBox("All selected states for " + descrip + " must be for the same camera", MB_EXCLAME); return 1; } /* * Take the list of states and other settings and determine what set would be used for * montaging, low dose state, and the mag and binning for it */ void CMultiGridDlg::DeduceStateForMMM(int numStates, int camera, StateParams **states, int *lowDose, int *magInd, bool &useLD, bool &useSearch, bool &useView, int &useMontMap, int &useCamera, int &useMag, int &useBin, int &stateForMont) { LowDoseParams *ldParams; BOOL curLD = mWinApp->LowDoseMode(); MontParam *montP = mMGTasks->GetMMMmontParam(); ControlSet *conSets; int ind, area; useCamera = mWinApp->GetCurrentCamera(); useMag = mScope->GetMagIndex(); useLD = false; useView = false; useSearch = false; useMontMap = 0; stateForMont = -1; // In Low dose if acquire type is set in LD or if in LD or if low dose state(s) are set useLD = m_iMMMacquireType < 2 || (m_iMMMacquireType == 2 && ((curLD && !numStates) || (numStates && lowDose[0]))); // Use search if specified or if doing montage and it is that way in dialog; // same way with View useSearch = m_iMMMacquireType == 0 || (useLD && m_iMMMacquireType != 1 && montP->useSearchInLowDose && m_iSingleVsPolyMont); useView = m_iMMMacquireType == 1 || (useLD && m_iMMMacquireType != 2 && montP->useViewInLowDose && m_iSingleVsPolyMont); // Leave mont-map flag alone outside low dose unless there is a state being set, either // mont map or not. In LD, turn it off if using S or V if (m_iSingleVsPolyMont) { if (m_iMMMacquireType == 2 && !useLD && numStates) useMontMap = states[0]->montMapConSet ? 1 : -1; if (useLD && (useSearch || useView)) useMontMap = -1; } if (numStates && useCamera != camera) ldParams = mWinApp->GetLDParamsForCamera(camera); else ldParams = mWinApp->GetLowDoseParams(); // If states being set, use the camera for that after getting the right conSets if (numStates && useCamera != camera) conSets = mWinApp->GetCamConSets() + camera * MAX_CONSETS; else conSets = mWinApp->GetConSets(); if (numStates) useCamera = camera; // If in LD, set default mag index and binning based on LD params of selected camera // Then loop though states and if one is set for the acquisition mode, use its mag if (useLD) { if (useView) { useMag = ldParams[VIEW_CONSET].magIndex; useBin = conSets[VIEW_CONSET].binning; } else if (useSearch) { useMag = ldParams[SEARCH_AREA].magIndex; useBin = conSets[SEARCH_CONSET].binning; } else { useMag = ldParams[RECORD_CONSET].magIndex; useBin = conSets[RECORD_CONSET].binning; } for (ind = 0; ind < numStates; ind++) { area = mWinApp->mNavHelper->AreaFromStateLowDoseValue(states[ind], NULL); if ((useView && area == VIEW_CONSET) || (useSearch && area == SEARCH_AREA) || (!useView && !useSearch && area == RECORD_CONSET)) break; } if (ind < numStates) { useMag = magInd[ind]; useBin = states[ind]->binning; stateForMont = ind; // Set mont map one way or another if a Record state is set and not using V or S if (area == RECORD_CONSET) useMontMap = states[ind]->montMapConSet ? 1 : -1; } } else if (numStates) { // non-LD, use the mag from state if set useMag = states[0]->magIndex; useBin = states[0]->binning; stateForMont = 0; } else { useBin = conSets[(useMontMap > 0 || (m_iSingleVsPolyMont && useMontMap == 0 && montP->useMontMapParams)) ? MONT_USER_CONSET : RECORD_CONSET].binning; } } /* * Analyze parameters and do everything needed to set up for taking MMM's, which may * involve montage setup */ int CMultiGridDlg::SetupMMMacquire(bool skipDlg) { CMapDrawItem *item; CString str; CMontageSetupDlg montDlg; MontParam *montP = mMGTasks->GetMMMmontParam(); AutoContourParams *acParams = mWinApp->mNavHelper->GetAutocontourParams(); float itemSize = 60.; CComboBox *comboArr[4] = {&m_comboMMMstate1, &m_comboMMMstate2, &m_comboMMMstate3, &m_comboMMMstate4}; bool useLD, useSearch, useView; int useMag, useCamera, useMontMap, useBin, err = 0, actCam, stateForMont; int indForMont = -1; StateParams *stateArr[4]; int stateLowDose[4], stateMagInds[4], numStates, stateCamera; // Check the states if (CheckMultipleStates(comboArr, mParams.MMMstateNums, mParams.MMMstateNames, "medium-mag maps", numStates, stateCamera, stateArr, stateLowDose, stateMagInds)) return 1; if (numStates && !stateLowDose[0] && m_iMMMacquireType < 2) { AfxMessageBox("You selected medium mag map acquisition with a Low-Dose\n" "area but are setting a non-Low Dose state.\n" "This makes no sense and needs to be fixed before proceeding", MB_EXCLAME); return 1; } // Get the state for acquisition DeduceStateForMMM(numStates, stateCamera, stateArr, stateLowDose, stateMagInds, useLD, useSearch, useView, useMontMap, useCamera, useMag, useBin, stateForMont); if (useMontMap > 0 && m_iSingleVsPolyMont == 0) { AfxMessageBox("You selected single-image for medium mag map acquisition\n" "but set a Mont-Map state which will not be used for that.\n" "This makes no sense and needs to be fixed before proceeding", MB_EXCLAME); return 1; } mMMMneedsLowDose = useLD ? 1 : -1; if (numStates) mMMMneedsLowDose = 0; if (m_iSingleVsPolyMont && stateForMont >= 0) indForMont = mParams.MMMstateNums[stateForMont]; // If "skipDlg" is set it is being done for running, so check and return if OK if (skipDlg && mMMMsetupOK && mMMMsetupAcqType == m_iMMMacquireType && mMMMsetupMontType == m_iSingleVsPolyMont && mMMMsetupStateForMont == indForMont) return 0; mMMMsetupOK = false; if (m_iSingleVsPolyMont > 1) skipDlg = false; // Make sure camera is OK actCam = mWinApp->LookupActiveCamera(useCamera); if (actCam < 0) { AfxMessageBox("The camera for the state to be set is not in the active list", MB_EXCLAME); return 1; } // For montages: set the parameter set and low dose and other things that should be set if (m_iSingleVsPolyMont) { montP->useViewInLowDose = useView; montP->useSearchInLowDose = useSearch; if (useMontMap) montP->useMontMapParams = useMontMap > 0; montP->cameraIndex = actCam; montP->setupInLowDose = useLD; montP->skipOutsidePoly = false; montP->skipCorrelations = false; montP->ignoreSkipList = false; montP->warnedConSetBin = true; montP->binning = useBin; montP->magIndex = useMag; montDlg.mForMultiGridMap = SETUPMONT_MG_POLYGON; if (!mMMMmontWasSetup) montP->moveStage = true; if (!skipDlg) montDlg.mSizeLocked = false; // For polygon montage, make a square in an item; use autocont range if appropriate if (m_iSingleVsPolyMont == 1) { if (m_bAutocontour) { mWinApp->mNavHelper->mAutoContouringDlg->SyncToMasterParams(); itemSize = (acParams->minSize + acParams->maxSize) / 2.f; } item = new CMapDrawItem; item->AppendPoint(0., 0.); item->AppendPoint(itemSize, 0.); item->AppendPoint(itemSize, itemSize); item->AppendPoint(0., itemSize); item->mStageX = itemSize / 2.f; item->mStageY = itemSize / 2.f; if (!skipDlg) { montDlg.mParam = *montP; montDlg.mForMultiGridMap = SETUPMONT_MG_POLYGON; montDlg.mDummyAreaSize = itemSize; } // Set up the montage err = mWinApp->mNavigator->SetupMontage(item, skipDlg ? NULL : &montDlg, skipDlg, 0., SETUPMONT_MG_POLYGON); delete item; if (!err && !skipDlg) *montP = montDlg.mParam; if (!err && stateForMont && useMag > 0 && montP->magIndex != useMag) { str.Format("You selected to set a state at %dx but changed the mag to %d" " in Montage Setup\n\nDo you want to proceed with these settings?", MagForCamera(useCamera, useMag), MagForCamera(useCamera, montP->magIndex)); if (AfxMessageBox(str, MB_QUESTION) != IDYES) err = 1; } } else { //Fixed nxn: leave # of frames alone if done last time if (!(mMMMmontWasSetup && mMMMsetupMontType == m_iSingleVsPolyMont)) { montP->xNframes = mParams.MMMnumXpieces; montP->yNframes = mParams.MMMnumYpieces; } if (stateForMont >= 0) { mWinApp->mDocWnd->MontParamInitFromFrame(montP, useCamera, stateArr[stateForMont]->xFrame, stateArr[stateForMont]->yFrame, 0.); } else { mWinApp->mDocWnd->MontParamInitFromConSet(montP, MontageConSetNum(montP, true, useLD), 0.); } err = 0; if (!skipDlg) { // Run dialog montDlg.mForMultiGridMap = SETUPMONT_MG_MMM_NBYN; montDlg.mParam = *montP; err = montDlg.DoModal() != IDOK ? 1 : 0; if (!err) { *montP = montDlg.mParam; mParams.MMMnumXpieces = montP->xNframes; mParams.MMMnumYpieces = montP->yNframes; } } } mMMMmontWasSetup = !err; } // Save values so we know if still valid mMMMsetupOK = !err; if (!err) { mMMMsetupAcqType = m_iMMMacquireType; mMMMsetupMontType = m_iSingleVsPolyMont; mMMMsetupStateForMont = indForMont; if (mMGTasks->SaveSessionFile(str) > 0) AfxMessageBox(str, MB_EXCLAME); } return err; } /* * RUNNING ONE OR MORE PHASES */ // Start the run with all checked items void CMultiGridDlg::OnButStartRun() { if (mMGTasks->GetSuspendedMulGrid()) mMGTasks->EndMulGridSeq(); else DoStartRun(false); } // Run undone only: skip ones that have finished first phase selected void CMultiGridDlg::OnButRunUndone() { if (mMGTasks->GetSuspendedMulGrid()) mMGTasks->UserResumeMulGridSeq(); else DoStartRun(true); } /* * Common function to do some final checks and hand off to MGTasks for MORE checks, etc */ void CMultiGridDlg::DoStartRun(bool undoneOnly) { UPDATE_DATA_TRUE; int finalNeedsLowDose = mWinApp->LowDoseMode() ? 1 : -1; CComboBox *comboArr[4] = {&m_comboFinalState1, &m_comboFinalState2, &m_comboFinalState3, &m_comboFinalState4}; StateParams *stateArr[4]; int stateLowDose[4], stateMagInds[4], numStates, stateCamera; mWinApp->RestoreViewFocus(); DialogToParams(); *mMasterParams = mParams; if (m_bTakeLMMs) { if (m_iLMMacquireType != mGridMontSetupAcqType || (mGridMontSetAtXpcs == 0 && m_iLMMmontType) || (!m_iLMMmontType && mGridMontSetAtXpcs > 0) || (m_iLMMmontType && (m_iXpieces != mGridMontSetAtXpcs || m_iYpieces != mGridMontSetAtYpcs)) || mGridMontSetupOverlap != (m_bUseMontOverlap ? m_iMontOverlap : 0) || mGridMontSetupState != mParams.LMMstateNum) mGridMontSetupOK = false; if (!mGridMontSetupOK) { if (DoSetupLMMmont(true)) return; } } if (m_bTakeMMMs) { if (SetupMMMacquire(true)) return; } if (m_bRunFinalAcq) { if (CheckMultipleStates(comboArr, mParams.finalStateNums, mParams.finalStateNames, "final acquisition", numStates, stateCamera, stateArr, stateLowDose, stateMagInds)) return; if (numStates) finalNeedsLowDose = 0; } mMGTasks->StartGridRuns(mLMneedsLowDose, mMMMneedsLowDose, finalNeedsLowDose, stateCamera < 0 ? mWinApp->GetCurrentCamera() : stateCamera, undoneOnly); }