YFX_BRANCH注释

YFX_BRANCH
Feixiu Yao 1 year ago
parent 5e5c5aa9c7
commit 541a642a52

@ -16,291 +16,331 @@
#include "lastRecentFileList.h"
#include "menuCmdID.h"
#include "localization.h"
void LastRecentFileList::initMenu(HMENU hMenu, int idBase, int posBase, Accelerator *pAccelerator, bool doSubMenu)
// 引入LastRecentFileList类的头文件
#include "lastRecentFileList.h"
// 引入菜单命令ID的头文件
#include "menuCmdID.h"
// 引入本地化的头文件,可能用于支持多语言
#include "localization.h"
// LastRecentFileList类的initMenu函数
void LastRecentFileList::initMenu(HMENU hMenu, int idBase, int posBase, Accelerator* pAccelerator, bool doSubMenu)
{
if (doSubMenu)
{
_hParentMenu = hMenu;
_hMenu = ::CreatePopupMenu();
}
else
{
_hParentMenu = NULL;
_hMenu = hMenu;
}
_idBase = idBase;
_posBase = posBase;
_pAccelerator = pAccelerator;
_nativeLangEncoding = NPP_CP_WIN_1252;
for (size_t i = 0 ; i < sizeof(_idFreeArray) ; ++i)
_idFreeArray[i] = true;
// 如果doSubMenu为真表示需要创建一个弹出菜单
if (doSubMenu)
{
// 设置父菜单句柄
_hParentMenu = hMenu;
// 创建一个新的弹出菜单
_hMenu = ::CreatePopupMenu();
}
// 如果doSubMenu为假表示直接使用传入的菜单句柄
else
{
// 设置父菜单句柄为NULL表示主菜单
_hParentMenu = NULL;
// 使用传入的菜单句柄作为当前菜单
_hMenu = hMenu;
}
// 设置ID的基础值
_idBase = idBase;
// 设置位置的基础值
_posBase = posBase;
// 设置指向Accelerator对象的指针用于处理键盘快捷键等加速功能
_pAccelerator = pAccelerator;
// 设置本地化语言编码为Windows的1252编码这是一种西欧语言编码
_nativeLangEncoding = NPP_CP_WIN_1252;
// 初始化idFreeArray数组所有元素都设置为true表示ID可用
for (size_t i = 0; i < sizeof(_idFreeArray); ++i)
_idFreeArray[i] = true;
}
// LastRecentFileList类的switchMode函数用于切换模式
void LastRecentFileList::switchMode()
{
//Remove all menu items
::RemoveMenu(_hMenu, IDM_FILE_RESTORELASTCLOSEDFILE, MF_BYCOMMAND);
::RemoveMenu(_hMenu, IDM_OPEN_ALL_RECENT_FILE, MF_BYCOMMAND);
::RemoveMenu(_hMenu, IDM_CLEAN_RECENT_FILE_LIST, MF_BYCOMMAND);
for (int i = 0; i < _size; ++i)
{
::RemoveMenu(_hMenu, _lrfl.at(i)._id, MF_BYCOMMAND);
}
if (_hParentMenu == NULL) // mode main menu
{ if (_size > 0)
{
::RemoveMenu(_hMenu, _posBase, MF_BYPOSITION);
::RemoveMenu(_hMenu, _posBase, MF_BYPOSITION);
}
// switch to sub-menu mode
_hParentMenu = _hMenu;
_hMenu = ::CreatePopupMenu();
::RemoveMenu(_hMenu, _posBase+1, MF_BYPOSITION);
}
else // mode sub-menu
{
if (_size > 0)
{
::RemoveMenu(_hParentMenu, _posBase, MF_BYPOSITION);
::RemoveMenu(_hParentMenu, _posBase, MF_BYPOSITION);
}
// switch to main menu mode
::DestroyMenu(_hMenu);
_hMenu = _hParentMenu;
_hParentMenu = NULL;
}
_hasSeparators = false;
// 从菜单中移除所有相关菜单项
::RemoveMenu(_hMenu, IDM_FILE_RESTORELASTCLOSEDFILE, MF_BYCOMMAND);
::RemoveMenu(_hMenu, IDM_OPEN_ALL_RECENT_FILE, MF_BYCOMMAND);
::RemoveMenu(_hMenu, IDM_CLEAN_RECENT_FILE_LIST, MF_BYCOMMAND);
// 遍历最近打开文件列表,移除所有菜单项
for (int i = 0; i < _size; ++i)
{
::RemoveMenu(_hMenu, _lrfl.at(i)._id, MF_BYCOMMAND);
}
// 根据_hParentMenu的值判断当前模式主菜单模式或子菜单模式
if (_hParentMenu == NULL) // mode main menu主菜单模式
{
if (_size > 0) // 如果最近打开文件列表不为空
{
// 从主菜单中移除一些特定的菜单项(具体移除哪些项未给出)
::RemoveMenu(_hMenu, _posBase, MF_BYPOSITION);
::RemoveMenu(_hMenu, _posBase, MF_BYPOSITION);
}
// 切换到子菜单模式创建一个新的弹出菜单作为当前菜单并设置_hParentMenu为当前菜单即新创建的弹出菜单
// 同时移除一些特定的菜单项(具体移除哪些项未给出)
_hParentMenu = _hMenu;
_hMenu = ::CreatePopupMenu();
::RemoveMenu(_hMenu, _posBase + 1, MF_BYPOSITION);
}
else // mode sub-menu子菜单模式
{
if (_size > 0) // 如果最近打开文件列表不为空
{
// 从子菜单中移除一些特定的菜单项(具体移除哪些项未给出)
::RemoveMenu(_hParentMenu, _posBase, MF_BYPOSITION);
::RemoveMenu(_hParentMenu, _posBase, MF_BYPOSITION);
}
// switch to main menu mode
::DestroyMenu(_hMenu);
_hMenu = _hParentMenu;
_hParentMenu = NULL;
}
_hasSeparators = false;
}
void LastRecentFileList::updateMenu()
{
NppParameters& nppParam = NppParameters::getInstance();
if (!_hasSeparators && _size > 0)
{
//add separators
NativeLangSpeaker *pNativeLangSpeaker = nppParam.getNativeLangSpeaker();
generic_string recentFileList = pNativeLangSpeaker->getSubMenuEntryName("file-recentFiles");
generic_string openRecentClosedFile = pNativeLangSpeaker->getNativeLangMenuString(IDM_FILE_RESTORELASTCLOSEDFILE);
generic_string openAllFiles = pNativeLangSpeaker->getNativeLangMenuString(IDM_OPEN_ALL_RECENT_FILE);
generic_string cleanFileList = pNativeLangSpeaker->getNativeLangMenuString(IDM_CLEAN_RECENT_FILE_LIST);
if (recentFileList == TEXT(""))
recentFileList = TEXT("&Recent Files");
if (openRecentClosedFile == TEXT(""))
openRecentClosedFile = TEXT("Restore Recent Closed File");
if (openAllFiles == TEXT(""))
openAllFiles = TEXT("Open All Recent Files");
if (cleanFileList == TEXT(""))
cleanFileList = TEXT("Empty Recent Files List");
if (!isSubMenuMode())
::InsertMenu(_hMenu, _posBase + 0, MF_BYPOSITION, static_cast<UINT_PTR>(-1), 0);
::InsertMenu(_hMenu, _posBase + 1, MF_BYPOSITION, IDM_FILE_RESTORELASTCLOSEDFILE, openRecentClosedFile.c_str());
::InsertMenu(_hMenu, _posBase + 2, MF_BYPOSITION, IDM_OPEN_ALL_RECENT_FILE, openAllFiles.c_str());
::InsertMenu(_hMenu, _posBase + 3, MF_BYPOSITION, IDM_CLEAN_RECENT_FILE_LIST, cleanFileList.c_str());
::InsertMenu(_hMenu, _posBase + 4, MF_BYPOSITION, static_cast<UINT_PTR>(-1), 0);
_hasSeparators = true;
if (isSubMenuMode())
{
::InsertMenu(_hParentMenu, _posBase + 0, MF_BYPOSITION | MF_POPUP, reinterpret_cast<UINT_PTR>(_hMenu), (LPCTSTR)recentFileList.c_str());
::InsertMenu(_hParentMenu, _posBase + 1, MF_BYPOSITION, static_cast<UINT_PTR>(-1), 0);
}
}
else if (_hasSeparators && _size == 0) //remove separators
{
::RemoveMenu(_hMenu, _posBase + 4, MF_BYPOSITION);
::RemoveMenu(_hMenu, IDM_CLEAN_RECENT_FILE_LIST, MF_BYCOMMAND);
::RemoveMenu(_hMenu, IDM_OPEN_ALL_RECENT_FILE, MF_BYCOMMAND);
::RemoveMenu(_hMenu, IDM_FILE_RESTORELASTCLOSEDFILE, MF_BYCOMMAND);
::RemoveMenu(_hMenu, _posBase + 0, MF_BYPOSITION);
_hasSeparators = false;
if (isSubMenuMode())
{
// Remove "Recent Files" Entry and the separator from the main menu
::RemoveMenu(_hParentMenu, _posBase + 1, MF_BYPOSITION);
::RemoveMenu(_hParentMenu, _posBase + 0, MF_BYPOSITION);
// Remove the last left separator from the submenu
::RemoveMenu(_hMenu, 0, MF_BYPOSITION);
}
}
_pAccelerator->updateFullMenu();
//Remove all menu items
for (int i = 0; i < _size; ++i)
{
::RemoveMenu(_hMenu, _lrfl.at(i)._id, MF_BYCOMMAND);
}
//Then readd them, so everything stays in sync
for (int j = 0; j < _size; ++j)
{
generic_string strBuffer(BuildMenuFileName(nppParam.getRecentFileCustomLength(), j, _lrfl.at(j)._name));
::InsertMenu(_hMenu, _posBase + j, MF_BYPOSITION, _lrfl.at(j)._id, strBuffer.c_str());
}
}
// 获取 NppParameters 的单例实例
NppParameters& nppParam = NppParameters::getInstance();
// 检查是否没有分隔符且大小大于0满足条件则进入下面的 if 语句块
if (!_hasSeparators && _size > 0)
{
// 获取本地化语言的发言人对象
NativeLangSpeaker* pNativeLangSpeaker = nppParam.getNativeLangSpeaker();
// 从发言人对象中获取一些本地化菜单字符串
generic_string recentFileList = pNativeLangSpeaker->getSubMenuEntryName("file-recentFiles");
generic_string openRecentClosedFile = pNativeLangSpeaker->getNativeLangMenuString(IDM_FILE_RESTORELASTCLOSEDFILE);
generic_string openAllFiles = pNativeLangSpeaker->getNativeLangMenuString(IDM_OPEN_ALL_RECENT_FILE);
generic_string cleanFileList = pNativeLangSpeaker->getNativeLangMenuString(IDM_CLEAN_RECENT_FILE_LIST);
// 如果获取的字符串为空,则使用默认的字符串进行初始化
if (recentFileList == TEXT(""))
recentFileList = TEXT("&Recent Files");
if (openRecentClosedFile == TEXT(""))
openRecentClosedFile = TEXT("Restore Recent Closed File");
if (openAllFiles == TEXT(""))
openAllFiles = TEXT("Open All Recent Files");
if (cleanFileList == TEXT(""))
cleanFileList = TEXT("Empty Recent Files List");
// 如果当前不是子菜单模式,则在菜单中插入一个分隔符
if (!isSubMenuMode())
::InsertMenu(_hMenu, _posBase + 0, MF_BYPOSITION, static_cast<UINT_PTR>(-1), 0);
// 在菜单中插入四个子菜单项,分别是恢复最近关闭的文件、打开所有最近文件、清空最近文件列表和另一个分隔符
::InsertMenu(_hMenu, _posBase + 1, MF_BYPOSITION, IDM_FILE_RESTORELASTCLOSEDFILE, openRecentClosedFile.c_str());
::InsertMenu(_hMenu, _posBase + 2, MF_BYPOSITION, IDM_OPEN_ALL_RECENT_FILE, openAllFiles.c_str());
::InsertMenu(_hMenu, _posBase + 3, MF_BYPOSITION, IDM_CLEAN_RECENT_FILE_LIST, cleanFileList.c_str());
::InsertMenu(_hMenu, _posBase + 4, MF_BYPOSITION, static_cast<UINT_PTR>(-1), 0); // 插入分隔符
// 设置标志表示已有分隔符
_hasSeparators = true;
// 如果当前是子菜单模式,则在父菜单中插入子菜单和分隔符
if (isSubMenuMode())
{
::InsertMenu(_hParentMenu, _posBase + 0, MF_BYPOSITION | MF_POPUP, reinterpret_cast<UINT_PTR>(_hMenu), (LPCTSTR)recentFileList.c_str());
::InsertMenu(_hParentMenu, _posBase + 1, MF_BYPOSITION, static_cast<UINT_PTR>(-1), 0); // 插入分隔符
}
}
else if (_hasSeparators && _size == 0) // 当已有分隔符且大小为0时进入下面的 if 语句块,用于移除分隔符和菜单项
{
// 从菜单中移除一个分隔符和清空最近文件列表的菜单项
::RemoveMenu(_hMenu, _posBase + 4, MF_BYPOSITION);
::RemoveMenu(_hMenu, IDM_CLEAN_RECENT_FILE_LIST, MF_BYCOMMAND);
::RemoveMenu(_hMenu, IDM_OPEN_ALL_RECENT_FILE, MF_BYCOMMAND);
::RemoveMenu(_hMenu, IDM_FILE_RESTORELASTCLOSEDFILE, MF_BYCOMMAND);
::RemoveMenu(_hMenu, _posBase + 0, MF_BYPOSITION);
_hasSeparators = false;
if (isSubMenuMode())
{
// Remove "Recent Files" Entry and the separator from the main menu
::RemoveMenu(_hParentMenu, _posBase + 1, MF_BYPOSITION);
::RemoveMenu(_hParentMenu, _posBase + 0, MF_BYPOSITION);
// Remove the last left separator from the submenu
::RemoveMenu(_hMenu, 0, MF_BYPOSITION);
}
}
_pAccelerator->updateFullMenu();
//Remove all menu items
for (int i = 0; i < _size; ++i)
{
::RemoveMenu(_hMenu, _lrfl.at(i)._id, MF_BYCOMMAND);
}
//Then readd them, so everything stays in sync
for (int j = 0; j < _size; ++j)
{
generic_string strBuffer(BuildMenuFileName(nppParam.getRecentFileCustomLength(), j, _lrfl.at(j)._name));
::InsertMenu(_hMenu, _posBase + j, MF_BYPOSITION, _lrfl.at(j)._id, strBuffer.c_str());
}
void LastRecentFileList::add(const TCHAR *fn)
}
// 向最近的文件列表中添加一个文件名。如果达到用户定义的最大限制或列表被锁定,则不会添加。
// 如果文件名已存在,则会先将其移除再添加。
void LastRecentFileList::add(const TCHAR* fn)
{
if (_userMax == 0 || _locked)
return;
RecentItem itemToAdd(fn);
int index = find(fn);
if (index != -1)
{
//already in list, bump upwards
remove(index);
}
if (_size == _userMax)
{
itemToAdd._id = _lrfl.back()._id;
_lrfl.pop_back(); //remove oldest
}
else
{
itemToAdd._id = popFirstAvailableID();
++_size;
}
_lrfl.push_front(itemToAdd);
updateMenu();
if (_userMax == 0 || _locked) // 如果用户定义的最大数量为0或列表被锁定直接返回不进行添加
return;
RecentItem itemToAdd(fn); // 创建一个新的RecentItem对象使用传入的文件名初始化
int index = find(fn); // 查找该文件名在列表中的索引
if (index != -1) // 如果找到
{
// 如果文件名已存在,先将其移除,然后重新添加
remove(index);
}
if (_size == _userMax) // 如果列表已满
{
itemToAdd._id = _lrfl.back()._id; // 使用最后一个元素的ID初始化新元素的ID
_lrfl.pop_back(); // 移除列表中的最后一个元素(即最旧的一个)
}
else // 如果列表未满
{
itemToAdd._id = popFirstAvailableID(); // 获取第一个可用的ID并初始化新元素的ID
++_size; // 增加列表的大小
}
_lrfl.push_front(itemToAdd); // 在列表的前面添加新元素
updateMenu(); // 更新菜单
}
void LastRecentFileList::remove(const TCHAR *fn)
{
int index = find(fn);
if (index != -1)
remove(index);
// 根据文件名从最近的文件列表中移除一个文件。如果找到,则移除;否则什么也不做。
void LastRecentFileList::remove(const TCHAR* fn)
{
int index = find(fn); // 查找文件名在列表中的索引
if (index != -1) // 如果找到
remove(index); // 移除该元素
}
void LastRecentFileList::remove(size_t index)
// 根据索引从最近的文件列表中移除一个文件。如果索引有效,则移除;否则什么也不做。
void LastRecentFileList::remove(size_t index)
{
if (_size == 0 || _locked)
return;
if (index < _lrfl.size())
{
::RemoveMenu(_hMenu, _lrfl.at(index)._id, MF_BYCOMMAND);
setAvailable(_lrfl.at(index)._id);
_lrfl.erase(_lrfl.begin() + index);
--_size;
updateMenu();
}
if (_size == 0 || _locked) // 如果列表为空或被锁定,直接返回,不进行移除操作
return;
if (index < _lrfl.size()) // 如果索引有效
{
::RemoveMenu(_hMenu, _lrfl.at(index)._id, MF_BYCOMMAND); // 从菜单中移除该ID对应的菜单项
setAvailable(_lrfl.at(index)._id); // 将该ID标记为可用可能是为了下次添加时重复使用
_lrfl.erase(_lrfl.begin() + index); // 从列表中移除该元素
--_size; // 减少列表的大小
updateMenu(); // 更新菜单
}
}
void LastRecentFileList::clear()
// 清空最近的文件列表。所有文件名和ID都会被移除菜单也会相应地更新。
void LastRecentFileList::clear()
{
if (_size == 0)
return;
for (int i = (_size-1); i >= 0; i--)
{
::RemoveMenu(_hMenu, _lrfl.at(i)._id, MF_BYCOMMAND);
setAvailable(_lrfl.at(i)._id);
_lrfl.erase(_lrfl.begin() + i);
}
_size = 0;
updateMenu();
if (_size == 0) // 如果列表为空,直接返回,不进行任何操作
return;
for (int i = (_size - 1); i >= 0; i--) // 从后向前遍历列表,因为移除元素会影响后续元素的索引
{
::RemoveMenu(_hMenu, _lrfl.at(i)._id, MF_BYCOMMAND); // 从菜单中移除该ID对应的菜单项
setAvailable(_lrfl.at(i)._id); // 将该ID标记为可用可能是为了下次添加时重复使用
_lrfl.erase(_lrfl.begin() + i); // 从列表中移除该元素
}
_size = 0; // 将列表大小设置为0
updateMenu(); // 更新菜单
}
LastRecentFileList
generic_string & LastRecentFileList::getItem(int id)
cpp
// 根据ID从最近的文件列表中获取一个文件名。如果找到则返回对应的文件名否则返回列表中的第一个文件名。
generic_string& LastRecentFileList::getItem(int id)
{
int i = 0;
for (; i < _size; ++i)
{
if (_lrfl.at(i)._id == id)
break;
}
if (i == _size)
i = 0;
return _lrfl.at(i)._name; //if not found, return first
int i = 0; // 从索引0开始查找因为如果ID不存在可能会返回第一个文件名作为默认值。
for (; i < _size; ++i) // 遍历整个列表查找匹配的ID。如果找不到i会等于_size此时i会被重新设置为0。这是一个后备计划以防ID不存在于列表
{
if (_lrfl.at(i)._id == id) // 如果找到匹配的ID
break;
}
if (i == _size) // 如果遍历完整个列表都没有找到匹配的ID
i = 0; // 将索引重置为0这样可以从列表的第一个元素开始返回文件名作为默认值
return _lrfl.at(i)._name; // 返回找到的文件名或默认文件名
}
generic_string & LastRecentFileList::getIndex(int index)
// 根据索引从最近的文件列表中获取一个文件名。如果索引有效,则返回对应的文件名;否则返回列表中的第一个文件名。
generic_string& LastRecentFileList::getIndex(int index)
{
return _lrfl.at(index)._name; //if not found, return first
return _lrfl.at(index)._name; // 返回找到的文件名或默认文件名
}
// 设置用户定义的最大最近文件列表大小。如果当前列表大小大于新设置的大小,则移除最旧的文件直到列表大小等于新设置的大小。
void LastRecentFileList::setUserMaxNbLRF(int size)
{
_userMax = size;
if (_size > _userMax)
{ //start popping items
int toPop = _size-_userMax;
while (toPop > 0)
{
::RemoveMenu(_hMenu, _lrfl.back()._id, MF_BYCOMMAND);
setAvailable(_lrfl.back()._id);
_lrfl.pop_back();
toPop--;
_size--;
}
updateMenu();
_size = _userMax;
}
_userMax = size; // 设置用户定义的最大列表大小
if (_size > _userMax) // 如果当前列表大小大于新设置的大小
{
int toPop = _size - _userMax; // 计算需要移除的文件数量
while (toPop > 0) // 当还有文件需要移除时
{
::RemoveMenu(_hMenu, _lrfl.back()._id, MF_BYCOMMAND); // 从菜单中移除该ID对应的菜单项
setAvailable(_lrfl.back()._id); // 将该ID标记为可用可能是为了下次添加时重复使用
_lrfl.pop_back(); // 从列表中移除该元素
toPop--; // 减少剩余需要移除的文件数量
_size--; // 减少当前列表大小
}
updateMenu(); // 更新菜单
_size = _userMax; // 将当前列表大小设置为新设置的大小
}
}
// 将最近的文件列表保存到配置文件中。保存的文件名顺序与加载时相同。
void LastRecentFileList::saveLRFL()
{
NppParameters& nppParams = NppParameters::getInstance();
if (nppParams.writeRecentFileHistorySettings(_userMax))
{
for (int i = _size - 1; i >= 0; i--) //reverse order: so loading goes in correct order
{
nppParams.writeHistory(_lrfl.at(i)._name.c_str());
}
}
NppParameters& nppParams = NppParameters::getInstance(); // 获取NppParameters的实例引用
if (nppParams.writeRecentFileHistorySettings(_userMax)) // 如果成功写入最近的文件历史设置
{
for (int i = _size - 1; i >= 0; i--) // 按照从后往前的顺序保存文件名,确保加载时的顺序正确
{
nppParams.writeHistory(_lrfl.at(i)._name.c_str()); // 将文件名写入配置文件的历史记录部分
}
}
}
int LastRecentFileList::find(const TCHAR *fn)
// 在最近的文件列表中查找指定的文件名。
int LastRecentFileList::find(const TCHAR* fn)
{
for (int i = 0; i < _size; ++i)
{
if (OrdinalIgnoreCaseCompareStrings(_lrfl.at(i)._name.c_str(), fn) == 0)
{
return i;
}
}
return -1;
for (int i = 0; i < _size; ++i) // 遍历整个列表
{
if (OrdinalIgnoreCaseCompareStrings(_lrfl.at(i)._name.c_str(), fn) == 0) // 如果找到匹配的文件名(忽略大小写)
{
return i; // 返回该文件在列表中的索引
}
}
return -1; // 如果未找到,返回-1
}
int LastRecentFileList::popFirstAvailableID()
// 弹出第一个可用的ID。
int LastRecentFileList::popFirstAvailableID()
{
for (int i = 0 ; i < NB_MAX_LRF_FILE ; ++i)
{
if (_idFreeArray[i])
{
_idFreeArray[i] = false;
return i + _idBase;
}
}
return 0;
for (int i = 0; i < NB_MAX_LRF_FILE; ++i) // 遍历所有可能的ID
{
if (_idFreeArray[i]) // 如果该ID可用未被使用
{
_idFreeArray[i] = false; // 标记该ID为已使用
return i + _idBase; // 返回该ID的值从_idBase开始计算
}
}
return 0; // 如果所有ID都已使用返回0或默认值
}
// 设置指定的ID为可用。
void LastRecentFileList::setAvailable(int id)
{
int index = id - _idBase;
_idFreeArray[index] = true;
int index = id - _idBase; // 根据ID计算其在_idFreeArray中的索引
_idFreeArray[index] = true; // 将该索引对应的值设置为true表示该ID可用
}

Loading…
Cancel
Save