Skip to content

Commit

Permalink
Add UI to select favorite schemes, see issue #169.
Browse files Browse the repository at this point in the history
  • Loading branch information
zufuliu committed Mar 30, 2020
1 parent d4ec83b commit 675e065
Show file tree
Hide file tree
Showing 5 changed files with 190 additions and 11 deletions.
3 changes: 2 additions & 1 deletion src/Notepad2.c
Original file line number Diff line number Diff line change
Expand Up @@ -3746,7 +3746,8 @@ LRESULT MsgCommand(HWND hwnd, WPARAM wParam, LPARAM lParam) {
break;

case IDM_VIEW_SCHEME:
Style_SelectLexerDlg(hwndEdit);
case IDM_VIEW_SCHEME_FAVORITE:
Style_SelectLexerDlg(hwndEdit, LOWORD(wParam) == IDM_VIEW_SCHEME_FAVORITE);
break;

case IDM_VIEW_SCHEME_CONFIG:
Expand Down
1 change: 1 addition & 0 deletions src/Notepad2.rc
Original file line number Diff line number Diff line change
Expand Up @@ -469,6 +469,7 @@ BEGIN
BEGIN
MENUITEM "&Syntax Scheme...\tF12", IDM_VIEW_SCHEME
MENUITEM "&Customize Schemes...\tCtrl+F12", IDM_VIEW_SCHEME_CONFIG
MENUITEM "&Favorite Schemes...", IDM_VIEW_SCHEME_FAVORITE
MENUITEM "Use &2nd Global Styles\tShift+F12",IDM_VIEW_USE2NDGLOBALSTYLE
MENUITEM "&Use Default Code Style", IDM_VIEW_USEDEFAULT_CODESTYLE
POPUP "St&yle Theme"
Expand Down
193 changes: 185 additions & 8 deletions src/Styles.c
Original file line number Diff line number Diff line change
Expand Up @@ -3851,7 +3851,7 @@ static void Style_ResetStyle(PEDITLEXER pLex, PEDITSTYLE pStyle) {
lstrcpy(pStyle->szValue, pStyle->pszDefault);
}

static void Style_AddAllLexerToTreeView(HWND hwndTV, BOOL withStyles) {
static HTREEITEM Style_AddAllLexerToTreeView(HWND hwndTV, BOOL withStyles, BOOL withCheckBox) {
struct SchemeGroupInfo groupList[ALL_LEXER_COUNT];
int groupCount = 2;
groupList[0].group = 0;
Expand Down Expand Up @@ -3894,6 +3894,7 @@ static void Style_AddAllLexerToTreeView(HWND hwndTV, BOOL withStyles) {

HTREEITEM hSelNode = NULL;
HTREEITEM hSelParent = NULL;
HTREEITEM hFavoriteNode = NULL;

iLexer = LEXER_INDEX_GENERAL - groupList[0].count;
for (int i = 0; i < groupCount; i++) {
Expand All @@ -3920,6 +3921,18 @@ static void Style_AddAllLexerToTreeView(HWND hwndTV, BOOL withStyles) {
tvis.item.iSelectedImage = folderIcon;
tvis.item.lParam = 0; // group
hParent = (HTREEITEM)TreeView_InsertItem(hwndTV, &tvis);

if (group == 1) {
hFavoriteNode = hParent;
}
if (withCheckBox) {
// remove checkbox
tvis.item.hItem = hParent;
tvis.item.mask = TVIF_STATE;
tvis.item.state = 0;
tvis.item.stateMask = TVIS_STATEIMAGEMASK;
TreeView_SetItem(hwndTV, &(tvis.item));
}
}

if (group <= 1) {
Expand All @@ -3930,6 +3943,19 @@ static void Style_AddAllLexerToTreeView(HWND hwndTV, BOOL withStyles) {
hSelNode = hTreeNode;
hSelParent = hParent;
}
if (withCheckBox) {
if (pLex->iFavoriteOrder) {
TreeView_SetCheckState(hwndTV, hTreeNode, TRUE);
} else if (group == 0) {
TVITEM item;
ZeroMemory(&item, sizeof(item));
item.hItem = hTreeNode;
item.mask = TVIF_STATE;
item.state = 0;
item.stateMask = TVIS_STATEIMAGEMASK;
TreeView_SetItem(hwndTV, &(item));
}
}
}
if (groupList[group + 1].group > 1) {
iLexer = 0;
Expand All @@ -3942,6 +3968,9 @@ static void Style_AddAllLexerToTreeView(HWND hwndTV, BOOL withStyles) {
hSelNode = hTreeNode;
hSelParent = hParent;
}
if (withCheckBox && pLex->iFavoriteOrder) {
TreeView_SetCheckState(hwndTV, hTreeNode, TRUE);
}
}
}

Expand All @@ -3954,6 +3983,7 @@ static void Style_AddAllLexerToTreeView(HWND hwndTV, BOOL withStyles) {
TreeView_EnsureVisible(hwndTV, hSelParent);
}
TreeView_Select(hwndTV, hSelNode, TVGN_CARET);
return hFavoriteNode;
}

//=============================================================================
Expand Down Expand Up @@ -3988,7 +4018,7 @@ static INT_PTR CALLBACK Style_ConfigDlgProc(HWND hwnd, UINT umsg, WPARAM wParam,
hwndTV = GetDlgItem(hwnd, IDC_STYLELIST);
TreeView_SetExtendedStyle(hwndTV, TVS_EX_DOUBLEBUFFER, TVS_EX_DOUBLEBUFFER);
//SetExplorerTheme(hwndTV);
Style_AddAllLexerToTreeView(hwndTV, TRUE);
Style_AddAllLexerToTreeView(hwndTV, TRUE, FALSE);

MultilineEditSetup(hwnd, IDC_STYLEEDIT);
MultilineEditSetup(hwnd, IDC_STYLEVALUE_DEFAULT);
Expand Down Expand Up @@ -4578,22 +4608,148 @@ static PEDITLEXER Lexer_GetFromTreeView(HWND hwndTV) {
return NULL;
}

static void Lexer_OnCheckStateChanged(HWND hwndTV, HTREEITEM hFavoriteNode, HTREEITEM hTreeNode) {
TVITEM item;
ZeroMemory(&item, sizeof(item));
item.mask = TVIF_PARAM;
item.hItem = hTreeNode;
TreeView_GetItem(hwndTV, &item);

const LPARAM lParam = item.lParam;
if (lParam == 0) {
return;
}

// toggle check state
const BOOL checked = !TreeView_GetCheckState(hwndTV, hTreeNode);
HTREEITEM hParent = TreeView_GetParent(hwndTV, hTreeNode);

BOOL found = FALSE;
hTreeNode = TreeView_GetChild(hwndTV, hFavoriteNode);
while (hTreeNode != NULL) {
item.hItem = hTreeNode;
TreeView_GetItem(hwndTV, &item);
if (item.lParam == lParam) {
found = TRUE;
break;
}
hTreeNode = TreeView_GetNextSibling(hwndTV, hTreeNode);
}

// add or remove node in Favorites
PEDITLEXER pLex = (PEDITLEXER)lParam;
if (checked) {
if (!found) {
hTreeNode = Style_AddLexerToTreeView(hwndTV, pLex, hFavoriteNode, FALSE);
TreeView_SetCheckState(hwndTV, hTreeNode, TRUE);
}
TreeView_Expand(hwndTV, hFavoriteNode, TVE_EXPAND);
} else {
pLex->iFavoriteOrder = 0;
if (found) {
TreeView_DeleteItem(hwndTV, hTreeNode);
}

if (hParent == hFavoriteNode) {
// update check state
const int ch = ToUpperA(pLex->pszName[0]);
WCHAR szTitle[4] = {0};
item.mask = TVIF_TEXT;
item.pszText = szTitle;
item.cchTextMax = COUNTOF(szTitle);

hParent = TreeView_GetNextSibling(hwndTV, hParent);
found = FALSE;
while (!found && hParent != NULL) {
item.mask = TVIF_TEXT;
item.hItem = hParent;
TreeView_GetItem(hwndTV, &item);
// test group header
if (ch == szTitle[0]) {
item.mask = TVIF_PARAM;
hTreeNode = TreeView_GetChild(hwndTV, hParent);
while (hTreeNode != NULL) {
item.hItem = hTreeNode;
TreeView_GetItem(hwndTV, &item);
if (item.lParam == lParam) {
found = TRUE;
TreeView_SetCheckState(hwndTV, hTreeNode, checked);
break;
}
hTreeNode = TreeView_GetNextSibling(hwndTV, hTreeNode);
}
}

hParent = TreeView_GetNextSibling(hwndTV, hParent);
}
}
}
}

static void Style_GetFavoriteSchemesFromTreeView(HWND hwndTV, HTREEITEM hFavoriteNode) {
const int maxCch = MAX_FAVORITE_SCHEMES_CONFIG_SIZE - 3; // two digits, one space and NULL
WCHAR *wch = favoriteSchemesConfig;
int len = 0;
int count = 0;

TVITEM item;
ZeroMemory(&item, sizeof(item));
item.mask = TVIF_PARAM;

HTREEITEM hTreeNode = TreeView_GetChild(hwndTV, hFavoriteNode);
while (hTreeNode != NULL) {
item.hItem = hTreeNode;
TreeView_GetItem(hwndTV, &item);
if (item.lParam) {
PEDITLEXER pLex = (PEDITLEXER)item.lParam;
pLex->iFavoriteOrder = MAX_FAVORITE_SCHEMES_COUNT - count;

len += wsprintf(wch + len, L"%i ", pLex->rid - NP2LEX_TEXTFILE);
++count;
if (count == MAX_FAVORITE_SCHEMES_COUNT || len > maxCch) {
break;
}
}
hTreeNode = TreeView_GetNextSibling(hwndTV, hTreeNode);
}

wch[len--] = L'\0';
if (len >= 0) {
wch[len] = L'\0';
}

qsort(pLexArray + LEXER_INDEX_GENERAL, GENERAL_LEXER_COUNT, sizeof(PEDITLEXER), CmpEditLexer);
}

//=============================================================================
//
// Style_SelectLexerDlgProc()
//
static INT_PTR CALLBACK Style_SelectLexerDlgProc(HWND hwnd, UINT umsg, WPARAM wParam, LPARAM lParam) {
static HWND hwndTV;
static HTREEITEM hFavoriteNode;
static int iInternalDefault;

switch (umsg) {
case WM_INITDIALOG: {
SetWindowLongPtr(hwnd, DWLP_USER, lParam);
ResizeDlg_Init(hwnd, cxStyleSelectDlg, cyStyleSelectDlg, IDC_RESIZEGRIP3);

hwndTV = GetDlgItem(hwnd, IDC_STYLELIST);
const BOOL favorite = lParam != 0;
if (favorite) {
SetWindowLongPtr(hwndTV, GWL_STYLE, GetWindowLongPtr(hwndTV, GWL_STYLE) | TVS_CHECKBOXES);
WCHAR szTitle[128];
GetString(IDS_FAVORITE_SCHEMES_TITLE, szTitle, COUNTOF(szTitle));
SetWindowText(hwnd, szTitle);
}

TreeView_SetExtendedStyle(hwndTV, TVS_EX_DOUBLEBUFFER, TVS_EX_DOUBLEBUFFER);
//SetExplorerTheme(hwndTV);
Style_AddAllLexerToTreeView(hwndTV, FALSE);
hFavoriteNode = Style_AddAllLexerToTreeView(hwndTV, FALSE, favorite);
if (favorite) {
TreeView_EnsureVisible(hwndTV, hFavoriteNode);
}

iInternalDefault = pLexArray[iDefaultLexer]->rid;
if (iInternalDefault == pLexCurrent->rid) {
Expand Down Expand Up @@ -4635,6 +4791,21 @@ static INT_PTR CALLBACK Style_SelectLexerDlgProc(HWND hwnd, UINT umsg, WPARAM wP
case WM_NOTIFY:
if (((LPNMHDR)(lParam))->idFrom == IDC_STYLELIST) {
switch (((LPNMHDR)(lParam))->code) {
case NM_CLICK: {
// https://support.microsoft.com/en-us/help/261289/how-to-know-when-the-user-clicks-a-check-box-in-a-treeview-control
TVHITTESTINFO tvht = {0};
DWORD dwpos = GetMessagePos();
tvht.pt.x = GET_X_LPARAM(dwpos);
tvht.pt.y = GET_Y_LPARAM(dwpos);
MapWindowPoints(HWND_DESKTOP, hwndTV, &tvht.pt, 1);

TreeView_HitTest(hwndTV, &tvht);
if (tvht.hItem != NULL && (TVHT_ONITEMSTATEICON & tvht.flags)) {
Lexer_OnCheckStateChanged(hwndTV, hFavoriteNode, tvht.hItem);
}
}
break;

case NM_DBLCLK:
if (Lexer_GetFromTreeView(hwndTV)) {
SendWMCommand(hwnd, IDOK);
Expand Down Expand Up @@ -4671,11 +4842,17 @@ static INT_PTR CALLBACK Style_SelectLexerDlgProc(HWND hwnd, UINT umsg, WPARAM wP

case IDOK: {
PEDITLEXER pLex = Lexer_GetFromTreeView(hwndTV);
const LONG_PTR favorite = GetWindowLongPtr(hwnd, DWLP_USER);
if (pLex != NULL) {
pLexCurrent = pLex;
np2LexLangIndex = 0;
if (!favorite) {
pLexCurrent = pLex;
np2LexLangIndex = 0;
}
iDefaultLexer = Style_GetMatchLexerIndex(iInternalDefault);
}
if (favorite) {
Style_GetFavoriteSchemesFromTreeView(hwndTV, hFavoriteNode);
}

bAutoSelect = IsButtonChecked(hwnd, IDC_AUTOSELECT);
EndDialog(hwnd, IDOK);
Expand All @@ -4695,11 +4872,11 @@ static INT_PTR CALLBACK Style_SelectLexerDlgProc(HWND hwnd, UINT umsg, WPARAM wP
//
// Style_SelectLexerDlg()
//
void Style_SelectLexerDlg(HWND hwnd) {
void Style_SelectLexerDlg(HWND hwnd, BOOL favorite) {
const LPCEDITLEXER pLex = pLexCurrent;
const int langIndex = np2LexLangIndex;
if (IDOK == ThemedDialogBoxParam(g_hInstance, MAKEINTRESOURCE(IDD_STYLESELECT), GetParent(hwnd), Style_SelectLexerDlgProc, 0)) {
const BOOL bLexerChanged = pLex != pLexCurrent || langIndex != np2LexLangIndex;
if (IDOK == ThemedDialogBoxParam(g_hInstance, MAKEINTRESOURCE(IDD_STYLESELECT), GetParent(hwnd), Style_SelectLexerDlgProc, favorite)) {
const BOOL bLexerChanged = !favorite && pLex != pLexCurrent || langIndex != np2LexLangIndex;
if (bLexerChanged) {
Style_SetLexer(pLexCurrent, TRUE);
}
Expand Down
2 changes: 1 addition & 1 deletion src/Styles.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,4 +96,4 @@ void Style_SetStyles(int iStyle, LPCWSTR lpszStyle);

int Style_GetLexerIconId(LPCEDITLEXER pLex);
void Style_ConfigDlg(HWND hwnd);
void Style_SelectLexerDlg(HWND hwnd);
void Style_SelectLexerDlg(HWND hwnd, BOOL favorite);
2 changes: 1 addition & 1 deletion src/resource.h
Original file line number Diff line number Diff line change
Expand Up @@ -556,7 +556,7 @@
#define IDM_VIEW_DEFAULT_TEXT_FONT 40421
#define IDM_VIEW_MARKOCCURRENCES_CASE 40422
#define IDM_VIEW_REUSEWINDOW 40423
// 40424
#define IDM_VIEW_SCHEME_FAVORITE 40424
#define IDM_VIEW_ALWAYSONTOP 40425 // Alt+T
#define IDM_VIEW_MINTOTRAY 40426
#define IDM_VIEW_TRANSPARENT 40427 // Ctrl+0
Expand Down

0 comments on commit 675e065

Please sign in to comment.