Mercurial > vba-linux
view src/win32/AccelEditor.cpp @ 2:3549bbe597ed
adding makefile.am
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 03 Mar 2012 10:31:47 -0600 |
parents | f9f4f1b99eed |
children |
line wrap: on
line source
1 // AccelEditor.cpp : implementation file2 //4 #include "stdafx.h"5 #include "resource.h"6 #include "AccelEditor.h"7 #include "CmdAccelOb.h"8 #include "VBA.h"10 /////////////////////////////////////////////////////////////////////////////11 // AccelEditor dialog13 AccelEditor::AccelEditor(CWnd *pParent, CMenu *pMenu, CAcceleratorManager *pExtMgr)14 : ResizeDlg(AccelEditor::IDD, pParent), m_pMenuSrc(pMenu), m_pExtMgr(pExtMgr)15 {16 //{{AFX_DATA_INIT(AccelEditor)17 // NOTE: the ClassWizard will add member initialization here18 //}}AFX_DATA_INIT19 }21 BOOL AccelEditor::IsModified() const22 {23 return m_modified;24 }26 const CAcceleratorManager &AccelEditor::GetResultMangager() const27 {28 return m_result;29 }31 void AccelEditor::DoDataExchange(CDataExchange *pDX)32 {33 CDialog::DoDataExchange(pDX);34 //{{AFX_DATA_MAP(AccelEditor)35 DDX_Control(pDX, IDC_CURRENTS, m_currents);36 DDX_Control(pDX, IDC_ALREADY_AFFECTED, m_alreadyAffected);37 DDX_Control(pDX, IDC_COMMANDS, m_commands);38 DDX_Control(pDX, IDC_EDIT_KEY, m_key);39 DDX_Control(pDX, IDC_ACCELEDIT_AUTOTIMEOUT, m_timeout);40 DDX_Control(pDX, IDC_ACCELEDIT_PROGRESSBAR, m_progress);41 //}}AFX_DATA_MAP42 }44 BEGIN_MESSAGE_MAP(AccelEditor, CDialog)45 //{{AFX_MSG_MAP(AccelEditor)46 ON_BN_CLICKED(ID_OK, &AccelEditor::OnOk)47 ON_BN_CLICKED(ID_CANCEL, &AccelEditor::OnCancel)48 ON_BN_CLICKED(IDC_ACCELEDIT_APPLY, &AccelEditor::OnApply)49 ON_BN_CLICKED(IDC_RESET, &AccelEditor::OnReset)50 ON_BN_CLICKED(IDC_ASSIGN, &AccelEditor::OnAssign)51 ON_BN_CLICKED(IDC_REMOVE, &AccelEditor::OnRemove)52 ON_BN_CLICKED(IDC_ACCELEDIT_REPLACE, &AccelEditor::OnReplace)53 ON_CONTROL(EN_CHANGE, IDC_EDIT_KEY, &AccelEditor::OnKeyboardEditChange)54 ON_CONTROL(EN_KILLFOCUS, IDC_EDIT_KEY, &AccelEditor::OnKeyboardEditKillfocus)55 ON_CONTROL(EN_SETFOCUS, IDC_ACCELEDIT_AUTOTIMEOUT, &AccelEditor::OnTimeoutEditSetfocus)56 ON_CONTROL(EN_KILLFOCUS, IDC_ACCELEDIT_AUTOTIMEOUT, &AccelEditor::OnTimeoutEditKillfocus)57 ON_NOTIFY(TVN_SELCHANGED, IDC_COMMANDS, &AccelEditor::OnTvnSelchangedCommands)58 //ON_NOTIFY(LVN_ITEMCHANGED, IDC_CURRENTS, &AccelEditor::OnListItemChanged)59 ON_NOTIFY(NM_DBLCLK, IDC_CURRENTS, &AccelEditor::OnListDblClick)60 ON_NOTIFY(NM_CLICK, IDC_CURRENTS, &AccelEditor::OnListClick)61 ON_WM_TIMER()62 //}}AFX_MSG_MAP63 END_MESSAGE_MAP()65 /////////////////////////////////////////////////////////////////////////////66 // AccelEditor message handlers68 BOOL AccelEditor::OnInitDialog()69 {70 CDialog::OnInitDialog();72 DIALOG_SIZER_START(sz)73 DIALOG_SIZER_ENTRY(ID_OK, DS_MoveX)74 DIALOG_SIZER_ENTRY(ID_CANCEL, DS_MoveX)75 DIALOG_SIZER_ENTRY(IDC_ACCELEDIT_APPLY, DS_MoveX)76 DIALOG_SIZER_ENTRY(IDC_ASSIGN, DS_MoveX)77 DIALOG_SIZER_ENTRY(IDC_REMOVE, DS_MoveX)78 DIALOG_SIZER_ENTRY(IDC_ACCELEDIT_REPLACE, DS_MoveX)79 DIALOG_SIZER_ENTRY(IDC_COMMANDS, DS_SizeX | DS_SizeY)80 DIALOG_SIZER_ENTRY(IDC_CURRENTS, DS_MoveX | DS_SizeY)81 DIALOG_SIZER_ENTRY(IDC_EDIT_KEY, DS_MoveX | DS_MoveY)82 DIALOG_SIZER_ENTRY(IDC_EDIT_KEY, DS_MoveX | DS_MoveY)83 DIALOG_SIZER_ENTRY(IDC_STATIC2, DS_MoveY)84 DIALOG_SIZER_ENTRY(IDC_STATIC3, DS_MoveX | DS_MoveY)85 DIALOG_SIZER_ENTRY(IDC_STATIC4, DS_MoveX | DS_MoveY)86 DIALOG_SIZER_ENTRY(IDC_STATIC5, DS_MoveX | DS_MoveY)87 DIALOG_SIZER_ENTRY(IDC_ACCELEDIT_AUTOTIMEOUT, DS_SizeX | DS_MoveY)88 DIALOG_SIZER_END()89 SetData(sz,90 TRUE,91 HKEY_CURRENT_USER,92 "Software\\Emulators\\VisualBoyAdvance\\Viewer\\AccelEditor",93 NULL);95 if (m_pExtMgr)96 m_result = m_mgr = *m_pExtMgr;98 m_currents.SetExtendedStyle(LVS_EX_FULLROWSELECT);99 m_currents.InsertColumn(0, "Keys");100 m_currents.SetColumnWidth(0, LVSCW_AUTOSIZE_USEHEADER);101 InitCommands();102 m_autoMode = AUTO_REPLACE;103 m_modified = FALSE;104 m_timeoutValue = 1000;105 CString timeoutStr;106 timeoutStr.Format("%d", m_timeoutValue);107 m_timeout.SetWindowText(timeoutStr);108 m_progress.SetPos(0);110 GetDlgItem(IDC_ACCELEDIT_APPLY)->EnableWindow(FALSE);111 return TRUE; // return TRUE unless you set the focus to a control112 // EXCEPTION: OCX Property Pages should return FALSE113 }115 void AccelEditor::AddCommandsFromTable()116 {117 POSITION pos = m_mgr.m_mapAccelString.GetStartPosition();118 while (pos != NULL)119 {120 CString command;121 WORD wID;122 m_mgr.m_mapAccelString.GetNextAssoc(pos, command, wID);123 int nPos = command.Find('\\');125 if (nPos == 0) // skip menu commands126 {127 continue;128 }130 HTREEITEM newItem = TVI_ROOT;131 #if 0132 /*133 while (nPos != -1)134 {135 newItem = m_commands.InsertItem(command.Left(nPos), newItem);136 command.Delete(0, nPos + 1);137 nPos = command.Find('\\');138 }139 */140 #endif141 newItem = m_commands.InsertItem(command, newItem);142 m_commands.SetItemData(newItem, wID);143 m_hItems.AddTail(newItem);144 }145 }147 // recursive calls148 void AccelEditor::AddCommandsFromMenu(CMenu *pMenu, HTREEITEM hParent)149 {150 UINT nIndexMax = pMenu->GetMenuItemCount();151 for (UINT nIndex = 0; nIndex < nIndexMax; ++nIndex)152 {153 UINT nID = pMenu->GetMenuItemID(nIndex);154 if (nID == 0)155 continue; // menu separator or invalid cmd - ignore it157 if (nID == (UINT)-1)158 {159 // possibly a submenu160 CMenu *pSubMenu = pMenu->GetSubMenu(nIndex);161 if (pSubMenu != NULL)162 {163 CString tempStr;164 pMenu->GetMenuString(nIndex, tempStr, MF_BYPOSITION);165 tempStr.Remove('&');166 HTREEITEM newItem = m_commands.InsertItem(tempStr, hParent);167 AddCommandsFromMenu(pSubMenu, newItem);168 }169 }170 else171 {172 // normal menu item173 // generate the strings174 CString command;175 pMenu->GetMenuString(nIndex, command, MF_BYPOSITION);176 int nPos = command.ReverseFind('\t');177 if (nPos != -1)178 {179 command.Delete(nPos, command.GetLength() - nPos);180 }181 command.Remove('&');182 HTREEITEM newItem = m_commands.InsertItem(command, hParent);183 m_commands.SetItemData(newItem, nID);184 m_hItems.AddTail(newItem);185 }186 }187 }189 void AccelEditor::InitCommands()190 {191 m_commands.DeleteAllItems();192 m_hItems.RemoveAll();193 m_alreadyAffected.SetWindowText("");195 AddCommandsFromMenu(m_pMenuSrc, TVI_ROOT);196 AddCommandsFromTable();197 }199 BOOL AccelEditor::PreTranslateMessage(MSG *pMsg)200 {201 CWnd *pFocus = GetFocus();202 if (pFocus == &m_currents)203 {204 if (pMsg->message == WM_KEYDOWN)205 {206 switch (pMsg->wParam)207 {208 case VK_ESCAPE:209 m_currents.SetItemState(-1, 0, LVIS_SELECTED);210 CheckListSelections();211 break;212 case VK_RETURN:213 case VK_INSERT:214 // kludge to workaround CKeyboardEdit::PreTranslateMessage()215 break;216 case VK_DELETE:217 case VK_BACK:218 OnRemove();219 break;220 case VK_F6:221 case VK_LEFT:222 m_commands.SetFocus();223 break;224 case VK_RIGHT:225 GetDlgItem(ID_OK)->SetFocus();226 default:227 return ResizeDlg::PreTranslateMessage(pMsg);228 }229 return TRUE;230 }231 else if (pMsg->message == WM_KEYUP) // kludge to workaround CKeyboardEdit::PreTranslateMessage()232 {233 switch (pMsg->wParam)234 {235 case VK_RETURN:236 OnEdit();237 break;238 case VK_INSERT:239 OnNew();240 break;241 default:242 return ResizeDlg::PreTranslateMessage(pMsg);243 }244 return TRUE;245 }246 }247 else if (pFocus == &m_commands)248 {249 if (pMsg->message == WM_KEYDOWN)250 {251 switch (pMsg->wParam)252 {253 case VK_F6:254 m_currents.SetFocus();255 break;256 case VK_RIGHT:257 if (!m_commands.ItemHasChildren(m_commands.GetSelectedItem()))258 {259 m_currents.SetFocus();260 break;261 }262 // fall through263 default:264 return ResizeDlg::PreTranslateMessage(pMsg);265 }266 return TRUE;267 }268 }270 return ResizeDlg::PreTranslateMessage(pMsg);271 }273 void AccelEditor::OnOk()274 {275 OnApply();276 // OnTimeoutEditKillfocus();277 EndDialog(TRUE);278 }280 void AccelEditor::OnCancel()281 {282 // OnTimeoutEditKillfocus();283 // EndDialog(m_modified);284 EndDialog(FALSE); // this allows the caller to cancel even if the user has Apply'ed285 }287 void AccelEditor::OnApply()288 {289 m_result = m_mgr;290 GetDlgItem(IDC_ACCELEDIT_APPLY)->EnableWindow(FALSE);291 }293 void AccelEditor::OnReset()294 {295 m_mgr.Default(); /// FIXME accelerator reset NYI296 systemMessage(297 0,298 "The \"Reset All Accelerators\" feature is currently unimplemented.\nYou can achieve the same result by closing VBA, opening up your \"vba.ini\" file, deleting the line that starts with \"keyboard\", then reopening VBA.");299 InitCommands(); // update the listboxes.300 }302 void AccelEditor::OnAssign()303 {304 if (CheckAffected())305 return;307 // get the currently selected group308 HTREEITEM hItem = m_commands.GetSelectedItem();309 if (hItem == NULL)310 return; // abort312 // Get the object who manage the accels list, associated to the command.313 WORD wIDCommand = LOWORD(m_commands.GetItemData(hItem));315 CCmdAccelOb *pCmdAccel;316 if (m_mgr.m_mapAccelTable.Lookup(wIDCommand, pCmdAccel) != TRUE)317 return;319 WORD wKey;320 bool bCtrl, bAlt, bShift;321 if (!m_key.GetAccelKey(wKey, bCtrl, bAlt, bShift))322 return; // no valid key, abort324 BYTE cVirt = 0;325 if (bCtrl)326 cVirt |= FCONTROL;327 if (bAlt)328 cVirt |= FALT;329 if (bShift)330 cVirt |= FSHIFT;332 cVirt |= FVIRTKEY;334 // Create the new key...335 CAccelsOb *pAccel = new CAccelsOb(cVirt, wKey, false);336 ASSERT(pAccel != NULL);337 // ...and add in the list.338 pCmdAccel->m_Accels.AddTail(pAccel);340 // Update the listbox.341 CString szBuffer;342 pAccel->GetString(szBuffer);344 int index = m_currents.GetNextItem(-1, LVNI_SELECTED);345 if (index < 0)346 index = 0;347 m_currents.InsertItem(index, szBuffer);348 m_currents.SetItemData(index, reinterpret_cast<DWORD>(pAccel));349 m_currents.SetItemState(-1, 0, LVIS_SELECTED); // deselect other items first350 m_currents.SetItemState(index, LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LVIS_SELECTED);351 GetDlgItem(IDC_REMOVE)->EnableWindow(TRUE);352 GetDlgItem(IDC_ACCELEDIT_REPLACE)->EnableWindow(TRUE);354 // Reset the key editor.355 // m_key.ResetKey();357 m_modified = TRUE;358 GetDlgItem(IDC_ACCELEDIT_APPLY)->EnableWindow(TRUE);359 }361 void AccelEditor::OnRemove()362 {363 // Some controls364 POSITION selected = m_currents.GetFirstSelectedItemPosition();365 if (selected == NULL)366 return;368 HTREEITEM hItem = m_commands.GetSelectedItem();369 if (hItem == NULL)370 return;372 // Ref to the ID command373 WORD wIDCommand = LOWORD(m_commands.GetItemData(hItem));375 // Run through the accels, and control if it can be deleted.376 CCmdAccelOb *pCmdAccel;377 if (m_mgr.m_mapAccelTable.Lookup(wIDCommand, pCmdAccel) == TRUE)378 {379 POSITION pos = pCmdAccel->m_Accels.GetHeadPosition();380 POSITION PrevPos;381 while (pos != NULL)382 {383 PrevPos = pos;384 CAccelsOb *pAccel = pCmdAccel->m_Accels.GetNext(pos);385 do386 {387 int indexCurrent = m_currents.GetNextSelectedItem(selected);388 CAccelsOb *pAccelCurrent = reinterpret_cast<CAccelsOb *>(m_currents.GetItemData(indexCurrent));389 if (pAccel == pAccelCurrent)390 {391 if (!pAccel->m_bLocked)392 {393 // not locked, so we delete the key394 pCmdAccel->m_Accels.RemoveAt(PrevPos);395 delete pAccel;396 // and update the listboxes/key editor/static text397 m_currents.DeleteItem(indexCurrent);398 m_modified = TRUE;399 break;400 }401 else402 {403 systemMessage(0, "Unable to remove this locked accelerator: ", m_currents.GetItemText(indexCurrent, KEY_COLUMN));404 m_currents.SetItemState(indexCurrent, 0, LVIS_SELECTED); // deselect it405 break;406 }407 }408 }409 while (selected != NULL);411 selected = m_currents.GetFirstSelectedItemPosition();412 if (selected == NULL) // the normal exit of this function413 {414 m_currents.SetItemState(m_currents.GetNextItem(-1, LVIS_FOCUSED), LVIS_SELECTED, LVIS_SELECTED);415 if (m_currents.GetSelectedCount() == 0)416 {417 GetDlgItem(IDC_REMOVE)->EnableWindow(FALSE);418 GetDlgItem(IDC_ACCELEDIT_REPLACE)->EnableWindow(FALSE);419 }420 GetDlgItem(IDC_ACCELEDIT_APPLY)->EnableWindow(m_modified);421 return;422 }423 }424 systemMessage(0, "internal error (AccelEditor::Remove : pAccel unavailable)");425 return;426 }427 systemMessage(0, "internal error (AccelEditor::Remove : Lookup failed)");428 }430 void AccelEditor::OnReplace()431 {432 if (CheckAffected())433 return;434 OnRemove();435 OnAssign();436 }438 void AccelEditor::OnNew()439 {440 m_autoMode = AUTO_NEW;441 m_key.SetFocus();442 }444 void AccelEditor::OnEdit()445 {446 m_autoMode = AUTO_REPLACE;447 m_key.SetFocus();448 }450 BOOL AccelEditor::CheckAffected()451 {452 m_alreadyAffected.SetWindowText("");454 WORD wKey;455 bool bCtrl, bAlt, bShift;456 if (!m_key.GetAccelKey(wKey, bCtrl, bAlt, bShift))457 return TRUE; // no valid key, abort459 POSITION posItem = m_hItems.GetHeadPosition();460 while (posItem != NULL)461 {462 HTREEITEM hItem = m_hItems.GetNext(posItem);463 WORD wIDCommand2 = LOWORD(m_commands.GetItemData(hItem));465 CCmdAccelOb *pCmdAccel;466 m_mgr.m_mapAccelTable.Lookup(wIDCommand2, pCmdAccel);468 POSITION pos = pCmdAccel->m_Accels.GetHeadPosition();469 while (pos != NULL)470 {471 CAccelsOb *pAccel = pCmdAccel->m_Accels.GetNext(pos);472 if (pAccel->IsEqual(wKey, bCtrl, bAlt, bShift))473 {474 // the key is already affected (in the same or other command)475 // (the parts that were commented out allow for a one-to-many mapping,476 // which is only disabled because the MFC stuff that automagically activates the commands477 // doesn't seem to be capable of activating more than one command per accelerator...)478 m_alreadyAffected.SetWindowText(pCmdAccel->m_szCommand);479 return TRUE;480 }481 }482 }484 return FALSE;485 }487 BOOL AccelEditor::CheckJammed()488 {489 WORD jam;490 if (m_key.GetJamKey(jam))491 {492 // these go first, or the timer would be set again493 m_key.ResetKey();494 m_key.SetWindowText("Interrupted");495 if (m_currents.IsWindowEnabled())496 m_currents.SetFocus();497 else498 m_commands.SetFocus();499 return TRUE;500 }501 return FALSE;502 }504 BOOL AccelEditor::CheckListSelections()505 {506 BOOL result = m_currents.GetFirstSelectedItemPosition() ? TRUE : FALSE;508 GetDlgItem(IDC_REMOVE)->EnableWindow(result);509 GetDlgItem(IDC_ACCELEDIT_REPLACE)->EnableWindow(result);511 return result;512 }514 void AccelEditor::OnTvnSelchangedCommands(NMHDR *pNMHDR, LRESULT *pResult)515 {516 // LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);518 // TODO: Add your control notification handler code here519 // Check if some commands exist.520 HTREEITEM hItem = m_commands.GetSelectedItem();521 if (hItem == NULL)522 return;524 m_currents.DeleteAllItems();526 WORD wIDCommand = LOWORD(m_commands.GetItemData(hItem));527 CCmdAccelOb *pCmdAccel;528 if (m_mgr.m_mapAccelTable.Lookup(wIDCommand, pCmdAccel))529 {530 CAccelsOb *pAccel;531 CString szBuffer;532 POSITION pos = pCmdAccel->m_Accels.GetHeadPosition();534 // Add the keys to the 'currents keys' listbox.535 while (pos != NULL)536 {537 pAccel = pCmdAccel->m_Accels.GetNext(pos);538 pAccel->GetString(szBuffer);539 int index = m_currents.InsertItem(m_currents.GetItemCount(), szBuffer);540 // and a pointer to the accel object.541 m_currents.SetItemData(index, (DWORD)pAccel);542 }544 m_currents.SetItemState(0, LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LVIS_SELECTED);545 GetDlgItem(IDC_ASSIGN)->EnableWindow(TRUE);546 m_currents.EnableWindow(TRUE);547 }548 else549 {550 GetDlgItem(IDC_ASSIGN)->EnableWindow(FALSE);551 m_currents.EnableWindow(FALSE);552 }554 // Init the key editor555 // m_pKey->ResetKey();556 // m_alreadyAffected.SetWindowText("");558 CheckListSelections();560 *pResult = 0;561 }563 /*564 void AccelEditor::OnListItemChanged(NMHDR *pNMHDR, LRESULT *pResult)565 {566 NMLISTVIEW *pNMListView = reinterpret_cast<NMLISTVIEW *>(pNMHDR);567 if (pNMListView->uChanged == LVIF_STATE)568 {569 if ((pNMListView->uOldState & LVIS_SELECTED) && !(pNMListView->uNewState & LVIS_SELECTED))570 {571 }572 }574 *pResult = 0;575 }576 */578 void AccelEditor::OnListClick(NMHDR *pNMHDR, LRESULT *pResult)579 {580 CheckListSelections();581 *pResult = 0;582 }584 void AccelEditor::OnListDblClick(NMHDR *pNMHDR, LRESULT *pResult)585 {586 if (m_currents.GetFirstSelectedItemPosition())587 OnEdit();588 else589 OnNew();590 *pResult = 0;591 }593 void AccelEditor::OnKeyboardEditChange()594 {595 if (!m_key.IsDefined())596 return;598 // if (CheckJammed())599 // return;601 OnKeyboardEditKillfocus();602 CheckAffected();603 if (m_timeoutValue == 0)604 return;606 m_progress.SetRange32(0, m_timeoutValue);607 SetTimer(1, 50, NULL);608 }610 void AccelEditor::OnKeyboardEditKillfocus()611 {612 KillTimer(1);613 m_timer = 0;614 m_progress.SetPos(0);615 m_progress.SetBarColor(RGB(128, 0, 255));616 }618 void AccelEditor::OnTimeoutEditSetfocus()619 {620 m_timeout.PostMessage(EM_SETSEL, 0, -1);621 }623 void AccelEditor::OnTimeoutEditKillfocus()624 {625 CString str;626 m_timeout.GetWindowText(str);627 m_timeoutValue = atoi(str);628 m_autoMode = AUTO_REPLACE;629 }631 void AccelEditor::OnTimer(UINT_PTR nIDEvent)632 {633 if (nIDEvent == 1)634 {635 m_timer += 50;636 if (m_timer >= m_timeoutValue)637 {638 m_progress.SetPos(m_timeoutValue);639 m_progress.SetBarColor(RGB(255, 255, 0));640 if (m_autoMode == AUTO_NEW)641 {642 OnAssign();643 }644 else645 {646 OnReplace();647 }648 if (m_currents.IsWindowEnabled())649 m_currents.SetFocus();650 else651 m_commands.SetFocus();652 return;653 }654 UINT green = (m_timer * 255 / m_timeoutValue) ;655 m_progress.SetBarColor(RGB(128 + green / 2, green, 255 - green));656 m_progress.SetPos(m_timer);657 }658 }