Skip to content

Commit

Permalink
Bring back multiple accelerator key bindings
Browse files Browse the repository at this point in the history
Fixes: #43
  • Loading branch information
robertabcd committed Oct 31, 2020
1 parent ef79770 commit b2a983c
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 57 deletions.
56 changes: 28 additions & 28 deletions BuildMenu/BuildMenu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,13 @@ class MenuHotkeyUpdater : public MenuVisitor

void VisitMenuItem(CMenu *menu, UINT index) override {
UINT cmd = menu->GetMenuItemID(index);
std::optional<ACCEL> accel = accel_table_->GetByCmd(cmd);
if (accel) {
std::vector<ACCEL> accels = accel_table_->GetByCmd(cmd);
if (!accels.empty()) {
const auto& accel = accels[0];
CString text;
menu->GetMenuString(index, text, MF_BYPOSITION);
text.Append(_T("\t"));
text.Append(HotkeyToStr(accel->fVirt, accel->key));
text.Append(HotkeyToStr(accel.fVirt, accel.key));
menu->ModifyMenu(index, MF_BYPOSITION, cmd, text);
}
}
Expand Down Expand Up @@ -77,48 +78,47 @@ void TraverseMenuPreorder(HMENU hMenu, MenuVisitor *visitor)

void AcceleratorTable::Set(const ACCEL &accel)
{
DeleteByCmd(accel.cmd);
DeleteByKey(accel.fVirt, accel.key);
Delete(accel);
key_to_accel_[Key{ accel.fVirt, accel.key }] = accel;
cmd_to_accel_.emplace(accel.cmd, accel);
key_to_cmd_.emplace(Key{ accel.fVirt, accel.key }, accel.cmd);
}

void AcceleratorTable::DeleteByCmd(WORD cmd)
void AcceleratorTable::Delete(const ACCEL &accel)
{
auto it = cmd_to_accel_.find(cmd);
if (it == cmd_to_accel_.end()) {
return;
}
key_to_cmd_.erase(Key{it->second.fVirt, it->second.key});
cmd_to_accel_.erase(it);
}
Key key = Key{ accel.fVirt, accel.key };

void AcceleratorTable::DeleteByKey(BYTE fVirt, WORD key)
{
auto it = key_to_cmd_.find(Key{ fVirt, key });
if (it == key_to_cmd_.end()) {
auto it = key_to_accel_.find(key);
if (it == key_to_accel_.end())
return;

auto range = cmd_to_accel_.equal_range(it->second.cmd);
for (auto rt = range.first; rt != range.second; rt++) {
if (key == Key{ rt->second.fVirt, rt->second.key }) {
cmd_to_accel_.erase(rt);
break;
}
}
cmd_to_accel_.erase(it->second);
key_to_cmd_.erase(it);

key_to_accel_.erase(it);
}

std::optional<ACCEL> AcceleratorTable::GetByCmd(WORD cmd) const
std::vector<ACCEL> AcceleratorTable::GetByCmd(WORD cmd) const
{
auto it = cmd_to_accel_.find(cmd);
if (it == cmd_to_accel_.end()) {
return std::nullopt;
std::vector<ACCEL> accels;
auto range = cmd_to_accel_.equal_range(cmd);
for (auto it = range.first; it != range.second; it++) {
accels.push_back(it->second);
}
return it->second;
return accels;
}

std::optional<ACCEL> AcceleratorTable::GetByKey(BYTE fVirt, WORD key) const
{
auto it = key_to_cmd_.find(Key{fVirt, key});
if (it == key_to_cmd_.end()) {
auto it = key_to_accel_.find(Key{fVirt, key});
if (it == key_to_accel_.end()) {
return std::nullopt;
}
return cmd_to_accel_.at(it->second);
return it->second;
}

HACCEL AcceleratorTable::CreateHandle() const
Expand Down
9 changes: 4 additions & 5 deletions BuildMenu/BuildMenu.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,8 @@
class AcceleratorTable {
public:
void Set(const ACCEL &accel);
void DeleteByCmd(WORD cmd);
void DeleteByKey(BYTE fVirt, WORD key);
std::optional<ACCEL> GetByCmd(WORD cmd) const;
void Delete(const ACCEL &accel);
std::vector<ACCEL> GetByCmd(WORD cmd) const;
std::optional<ACCEL> GetByKey(BYTE fVirt, WORD key) const;

HACCEL CreateHandle() const;
Expand All @@ -30,8 +29,8 @@ class AcceleratorTable {
private:
using Key = std::pair<BYTE, WORD>;

std::map<WORD, ACCEL> cmd_to_accel_;
std::map<Key, WORD> key_to_cmd_;
std::multimap<WORD, ACCEL> cmd_to_accel_;
std::map<Key, ACCEL> key_to_accel_;
};

class MenuVisitor {
Expand Down
46 changes: 23 additions & 23 deletions Lite/CustomizeDlg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -197,17 +197,27 @@ void CCustomizeDlg::OnApply()

void CCustomizeDlg::OnDel()
{
int sel = key_list_.GetCurSel();
if (sel == -1)
auto* menu_item = menu_tree_.GetSelectedItem();
if (!menu_item)
return;
HotkeyData *data = reinterpret_cast<HotkeyData *>(menu_tree_.GetItemData(menu_item));

int key_sel = key_list_.GetCurSel();
if (key_sel == -1)
return;

// Confirm deletion.
if (MessageBox(LoadString(IDS_DEL_CONFIRM) , NULL, MB_OKCANCEL | MB_ICONQUESTION) != IDOK)
if (MessageBox(LoadString(IDS_DEL_CONFIRM), NULL, MB_OKCANCEL | MB_ICONQUESTION) != IDOK)
return;

hkedit_.Reset();

DeleteHotkeyForID(reinterpret_cast<HotkeyData *>(key_list_.GetItemData(sel)));
std::vector<ACCEL> accels = accel_table_.GetByCmd(data->cmd);
if (key_sel >= 0 && key_sel < accels.size()) {
accel_table_.Delete(accels[key_sel]);
}

UpdateHotkeyDisplay(data);
}

void CCustomizeDlg::OnSelChanged(NMHDR* pNMHDR, LRESULT* pResult)
Expand Down Expand Up @@ -250,15 +260,12 @@ void CCustomizeDlg::UpdateHotkeyDisplay(CCustomizeDlg::HotkeyData *data)

UpdateTreeItemDisplay(data);

std::optional<ACCEL> accel = accel_table_.GetByCmd(data->cmd);
if (accel) {
CString hotkey_text = HotkeyToStr(accel->fVirt, accel->key);
int index = key_list_.AddString(hotkey_text);
key_list_.SetItemData(index, reinterpret_cast<DWORD_PTR>(data));
key_list_.SetCurSel(0);

hkedit_.SetWindowText(hotkey_text);
text_assigned_to_.SetWindowText(menu_tree_.GetItemText(data->hitem));
std::vector<ACCEL> accels = accel_table_.GetByCmd(data->cmd);
if (!accels.empty()) {
for (const auto& accel : accels) {
CString hotkey_text = HotkeyToStr(accel.fVirt, accel.key);
key_list_.AddString(hotkey_text);
}
} else {
btn_delete_hotkey_.EnableWindow(false);
hkedit_.Reset();
Expand All @@ -273,10 +280,10 @@ void CCustomizeDlg::UpdateTreeItemDisplay(CCustomizeDlg::HotkeyData *data)
if ((p = text.Find('\t')) != -1)
text = text.Left(p);

std::optional<ACCEL> accel = accel_table_.GetByCmd(data->cmd);
if (accel) {
std::vector<ACCEL> accel = accel_table_.GetByCmd(data->cmd);
if (!accel.empty()) {
text += '\t';
text += HotkeyToStr(accel->fVirt, accel->key);
text += HotkeyToStr(accel[0].fVirt, accel[0].key);
}
menu_tree_.SetItemText(data->hitem, text);
}
Expand Down Expand Up @@ -310,10 +317,3 @@ CCustomizeDlg::HotkeyData* CCustomizeDlg::HotkeyDataFromKeys(BYTE fVirt, WORD ke
}
return it->second;
}

// 從所有具有相同 ID (hkdel->id) 的選單項目中,移除和 hkdel 相同的熱鍵 (hkdel->fVirt + hkdel->key)
void CCustomizeDlg::DeleteHotkeyForID(CCustomizeDlg::HotkeyData* hkdel)
{
accel_table_.DeleteByCmd(hkdel->cmd);
UpdateHotkeyDisplay(hkdel);
}
1 change: 0 additions & 1 deletion Lite/CustomizeDlg.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@ class CCustomizeDlg : public CDialog
HotkeyData *NewHotkeyData();
void UpdateTreeItemDisplay(HotkeyData *data);
void UpdateHotkeyDisplay(HotkeyData *data);
void DeleteHotkeyForID(HotkeyData *hkdel);
HotkeyData *HotkeyDataFromKeys(BYTE fVirt, WORD key);
void UIWriteAccels();
};
Expand Down

0 comments on commit b2a983c

Please sign in to comment.