From 78faea4c21208a7219dc11180519b18f0444c5f7 Mon Sep 17 00:00:00 2001 From: H.G. Muller Date: Sat, 7 Apr 2012 15:53:29 +0200 Subject: [PATCH] Switch to using listboxes for engine-selection in WinBoard --- backend.c | 2 + backend.h | 3 +- winboard/resource.h | 3 +- winboard/winboard.c | 12 +++-- winboard/winboard.rc | 7 ++- winboard/wsettings.c | 140 +++++++++++++++++++++++++++++++++---------------- 6 files changed, 112 insertions(+), 55 deletions(-) diff --git a/backend.c b/backend.c index 6772a97..5770e33 100644 --- a/backend.c +++ b/backend.c @@ -898,6 +898,8 @@ FloatToFront(char **list, char *engineLine) ASSIGN(*list, tidy+1); } +char *wbOptions; + void Load (ChessProgramState *cps, int i) { diff --git a/backend.h b/backend.h index 8fc885a..ae2baf5 100644 --- a/backend.h +++ b/backend.h @@ -97,6 +97,7 @@ #include "lists.h" #include "frontend.h" +extern char *wbOptions; extern int gotPremove; extern GameMode gameMode; extern int matchMode; @@ -317,7 +318,7 @@ extern Boolean set_cont_sequence P((char *new_seq)); extern int wrap P((char *dest, char *src, int count, int width, int *lp)); int Explode P((Board board, int fromX, int fromY, int toX, int toY)); -typedef enum { CheckBox, ComboBox, TextBox, Button, Spin, ResetButton, SaveButton, +typedef enum { CheckBox, ComboBox, TextBox, Button, Spin, ResetButton, SaveButton, ListBox, FileName, PathName, Slider, Message, Fractional, Label, Break, EndMark } Control; /* Flags Option.min used for ComboBox: */ diff --git a/winboard/resource.h b/winboard/resource.h index 83d102e..c6a1a7f 100644 --- a/winboard/resource.h +++ b/winboard/resource.h @@ -58,7 +58,7 @@ #define IDM_Comment 173 #define IDM_Debug 174 #define IDM_EditProgs1 175 -#define IDM_EditProgs2 176 +#define IDM_LoadProg1 176 #define IDM_AnalysisMode 177 #define IDM_AnalyzeFile 178 #define IDM_Annotate 179 @@ -627,6 +627,7 @@ #define OPT_ChoosePieceFont 1980 #define OPT_GameListFind 1981 #define OPT_Grid 1983 +#define IDM_LoadProg2 1984 // Next default values for new objects diff --git a/winboard/winboard.c b/winboard/winboard.c index 9cdd4b9..1bea76d 100644 --- a/winboard/winboard.c +++ b/winboard/winboard.c @@ -4997,9 +4997,12 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) EditTagsPopUp(firstChessProgramNames, &firstChessProgramNames); break; - case IDM_EditProgs2: - LoadEnginePopUp(hwndMain); -// EditTagsPopUp(secondChessProgramNames, &secondChessProgramNames); + case IDM_LoadProg1: + LoadEnginePopUp(hwndMain, 0); + break; + + case IDM_LoadProg2: + LoadEnginePopUp(hwndMain, 1); break; case IDM_EditServers: @@ -7858,7 +7861,8 @@ Enables icsEnables[] = { { IDM_MoveNow, MF_BYCOMMAND|MF_GRAYED }, { IDM_Hint, MF_BYCOMMAND|MF_GRAYED }, { IDM_Book, MF_BYCOMMAND|MF_GRAYED }, - { IDM_EditProgs2, MF_BYCOMMAND|MF_GRAYED }, + { IDM_LoadProg1, MF_BYCOMMAND|MF_GRAYED }, + { IDM_LoadProg2, MF_BYCOMMAND|MF_GRAYED }, { IDM_IcsOptions, MF_BYCOMMAND|MF_ENABLED }, { IDM_Engine1Options, MF_BYCOMMAND|MF_GRAYED }, { IDM_Engine2Options, MF_BYCOMMAND|MF_GRAYED }, diff --git a/winboard/winboard.rc b/winboard/winboard.rc index 14496f8..d0752c8 100644 --- a/winboard/winboard.rc +++ b/winboard/winboard.rc @@ -1253,10 +1253,11 @@ BEGIN POPUP "E&ngine" BEGIN MENUITEM "Edit Engine List...", IDM_EditProgs1 - MENUITEM "Load Engine...", IDM_EditProgs2 + MENUITEM "Load &First Engine...", IDM_LoadProg1 + MENUITEM "Load &Second Engine...", IDM_LoadProg2 MENUITEM SEPARATOR - MENUITEM "Engine #&1 Settings...", IDM_Engine1Options - MENUITEM "Engine #&2 Settings...", IDM_Engine2Options + MENUITEM "Engine #&1 Settings...", IDM_Engine1Options + MENUITEM "Engine #&2 Settings...", IDM_Engine2Options MENUITEM SEPARATOR MENUITEM "&Hint...", IDM_Hint MENUITEM "&Book...", IDM_Book diff --git a/winboard/wsettings.c b/winboard/wsettings.c index c74927e..5bbcc30 100644 --- a/winboard/wsettings.c +++ b/winboard/wsettings.c @@ -36,8 +36,7 @@ char title[MSG_SIZ]; char *engineName, *engineDir, *engineChoice, *engineLine, *nickName, *params; Boolean isUCI, hasBook, storeVariant, v1, addToList, useNick, isUCCI; extern Option installOptions[], matchOptions[]; -char *engineNr[] = { N_("First"), N_("Second"), NULL }; -char *engineList[MAXENGINES] = {" "}, *engineMnemonic[MAXENGINES] = {""}; +char *engineList[MAXENGINES] = {""}, *engineMnemonic[MAXENGINES] = {""}; void (*okFunc)(); ChessProgramState *activeCps; Option *activeList; @@ -113,6 +112,7 @@ LayoutOptions(int firstOption, int endOption, char *groupName, Option *optionLis case SaveButton: case Button: buttonList[buttons++] = nextOption; lastType = Button; break; case TextBox: + case ListBox: case FileName: case PathName: case Slider: @@ -127,7 +127,7 @@ LayoutOptions(int firstOption, int endOption, char *groupName, Option *optionLis if(!stop) nextType = Button; // kudge to flush remaining checks and combos undistorted // Take a new line if a spin follows combos or checks, or when we encounter a textbox - if((combos+checks || nextType == TextBox || nextType == FileName || nextType == PathName || nextType == Label) && layout&1) { + if((combos+checks || nextType == TextBox || nextType == ListBox || nextType == FileName || nextType == PathName || nextType == Label) && layout&1) { layoutList[layout++] = -1; } // The last check or combo before a spin will be put on the same line as that spin (prefix) @@ -139,7 +139,7 @@ LayoutOptions(int firstOption, int endOption, char *groupName, Option *optionLis } // if a combo is followed by a textbox, it must stay at the end of the combo/checks list to appear // immediately above the textbox, so treat it as check. (A check would automatically be and remain there.) - if((nextType == TextBox || nextType == FileName || nextType == PathName) && lastType == ComboBox) + if((nextType == TextBox || nextType == ListBox || nextType == FileName || nextType == PathName) && lastType == ComboBox) checkList[checks++] = comboList[--combos]; // Now append the checks behind the (remaining) combos to treat them as one group for(i=0; i< checks; i++) @@ -157,15 +157,26 @@ LayoutOptions(int firstOption, int endOption, char *groupName, Option *optionLis layoutList[layout++] = -1; layoutList[layout++] = comboList[2*right]; } - if(nextType == TextBox || nextType == FileName || nextType == PathName || nextType == Label) { - // A textBox is double width, so must be left-adjusted, and the right column remains empty + if(nextType == ListBox) { + // A listBox will be left-adjusted, and cause rearrangement of the elements before it to the right column breaks[layout/2] = lastType == Button ? 0 : 100; layoutList[layout++] = -1; layoutList[layout++] = nextOption - 1; for(i=optionList[nextOption-1].min; i>0; i--) { // extra high text edit + breaks[layout/2] = -1; layoutList[layout++] = -1; layoutList[layout++] = -1; } + } else + if(nextType == TextBox || nextType == FileName || nextType == PathName || nextType == Label) { + // A textBox is double width, so must be left-adjusted, and the right column remains empty + breaks[layout/2] = lastType == Button ? 0 : 100; + layoutList[layout++] = -1; + layoutList[layout++] = nextOption - 1; + if(optionList[nextOption-1].min) { // extra high text edit: goes right of existing listbox + layout -= 2; // remove + layoutList[layout-2*optionList[nextOption-1].min-2] = nextOption - 1; + } } else if(nextType == Spin) { // A spin will go in the next available position (right to left!). If it had to be prefixed with // a check or combo, this next position must be to the right, and the prefix goes left to it. @@ -312,6 +323,14 @@ SetOptionValues(HWND hDlg, ChessProgramState *cps, Option *optionList) } SendMessage(hwndCombo, CB_SELECTSTRING, (WPARAM) -1, (LPARAM) choices[optionList[j].value]); break; + case ListBox: + choices = (char**) optionList[j].choice; + hwndCombo = GetDlgItem(hDlg, 2001+2*i); + SendMessage(hwndCombo, LB_RESETCONTENT, 0, 0); + for(k=0; k= 0 && (optionList[j].value != new); if(changed) optionList[j].value = new; break; + case ListBox: + if(optionList[j].textValue) + *(int*) optionList[j].textValue = SendDlgItemMessage(hDlg, 2001+2*i, LB_GETCURSEL, 0, 0); case Button: default: break; // are treated instantly, so they have been sent already @@ -482,10 +504,14 @@ LRESULT CALLBACK SettingsProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lPa } if(j < 0) break; if(comboCallback && activeList[j].type == ComboBox && HIWORD(wParam) == CBN_SELCHANGE) { - if(j > 5) break; // Yegh! Must solve problem with more than one ombobox in dialog + if(j > 5) break; // Yegh! Must solve problem with more than one combobox in dialog (*comboCallback)(hDlg); break; } else + if(activeList[j].type == ListBox && HIWORD(wParam) == /*LBN_SELCHANGE*/ LBN_DBLCLK) { + ((ButtonCallback *) activeList[j].target)(hDlg); + break; + } else if( activeList[j].type == SaveButton) GetOptionValues(hDlg, activeCps, activeList); else if( activeList[j].type != Button) break; @@ -532,10 +558,16 @@ void AddOption(int x, int y, Control type, int i) AddControl(x+95, y, 50, 11, 0x0081, ES_AUTOHSCROLL | ES_NUMBER | WS_BORDER | WS_VISIBLE | WS_CHILD | WS_TABSTOP, i+1); break; case TextBox: + extra = 13*activeList[layoutList[i/2]].min; // when extra high, left-align and put description text above it + AddControl(x+(extra?50:0), y+1, 95, 9, 0x0082, SS_ENDELLIPSIS | WS_VISIBLE | WS_CHILD, i); + AddControl(x+(extra?50:95), y+(extra?13:0), extra?105:200, 11+(extra?extra-13:0), 0x0081, ES_AUTOHSCROLL | WS_BORDER | WS_VISIBLE | + WS_CHILD | WS_TABSTOP | (extra ? ES_MULTILINE | ES_WANTRETURN | WS_VSCROLL :0), i+1); + break; + case ListBox: AddControl(x, y+1, 95, 9, 0x0082, SS_ENDELLIPSIS | WS_VISIBLE | WS_CHILD, i); extra = 13*activeList[layoutList[i/2]].min; - AddControl(x+95, y, 200, 11+extra, 0x0081, ES_AUTOHSCROLL | WS_BORDER | WS_VISIBLE | WS_CHILD | WS_TABSTOP | - (extra ? ES_MULTILINE | ES_WANTRETURN | WS_VSCROLL :0), i+1); + AddControl(x, y+13, 105, 11+extra-13, 0x0083, LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_HSCROLL | WS_BORDER | LBS_NOTIFY | + WS_VISIBLE | WS_CHILD | WS_TABSTOP, i+1); break; case Label: extra = activeList[layoutList[i/2]].value; @@ -570,7 +602,7 @@ void AddOption(int x, int y, Control type, int i) void CreateDialogTemplate(int *layoutList, int nr, Option *optionList) { - int i, ii, j, x=1, y=0, buttonRows, breakPoint = -1, k=0; + int i, ii, j, x=1, y=0, maxY=0, buttonRows, breakPoint = -1, k=0; template.header.cdit = 0; template.header.cx = 307; @@ -590,12 +622,15 @@ CreateDialogTemplate(int *layoutList, int nr, Option *optionList) 0x0082, SS_ENDELLIPSIS | WS_VISIBLE | WS_CHILD, 2*(ii+MAX_OPTIONS)); } j = layoutList[i]; - if(j >= 0) + if(j >= 0) { AddOption(x+155-150*(i&1), y+13*(i>>1)+5, optionList[j].type, 2*i); + // listboxes have the special power to adjust the width of the column they are in + if(optionList[j].type == ListBox) x -= optionList[j].value, template.header.cx -= optionList[j].value; + } if(k < groups && ii+1 == boxList[k+1]) { k += 2; y += 4; } - if(ii+1 == breakPoint) { x += 318; y = -13*(breakPoint>>1); } + if(ii+1 >= breakPoint && breaks[ii+1>>1] >= 0) { x += 318; maxY = y+13*(ii+1>>1)+5; y = -13*(ii+1>>1); breakPoint = 1000; } } // add butons at the bottom of dialog window y += 13*(nr>>1)+5; @@ -606,8 +641,9 @@ CreateDialogTemplate(int *layoutList, int nr, Option *optionList) } AddControl(x+225, y+18*(buttonRows-1), 30, 15, 0x0080, BS_PUSHBUTTON | WS_VISIBLE | WS_CHILD | WS_TABSTOP, IDOK-2000); AddControl(x+260, y+18*(buttonRows-1), 40, 15, 0x0080, BS_PUSHBUTTON | WS_VISIBLE | WS_CHILD | WS_TABSTOP, IDCANCEL-2000); + y += 18*buttonRows; if(y < maxY) y = maxY; template.title[8] = optionList == first.option ? '1' : '2'; - template.header.cy = y += 18*buttonRows+2; + template.header.cy = y+2; template.header.style &= ~WS_VSCROLL; } @@ -629,30 +665,36 @@ EngineOptionsPopup(HWND hwnd, ChessProgramState *cps) return; } +int EnterGroup P((HWND hDlg)); + +static int engineNr, selected; + int InstallOK() { + if(selected >= 0) { ASSIGN(engineLine, engineList[selected]); } if(engineLine[0] == '#') { DisplayError(_("Select single engine from the group"), 0); return 0; } if(isUCCI) isUCI = 2; - if(engineChoice[0] == engineNr[0][0]) Load(&first, 0); else Load(&second, 1); + if(!engineNr) Load(&first, 0); else Load(&second, 1); return 1; } Option installOptions[] = { - { 0, 0, 0, NULL, (void*) &engineLine, (char*) engineMnemonic, engineList, ComboBox, N_("Select engine from list:") }, +// { 0, 0, 0, NULL, (void*) &engineLine, (char*) engineMnemonic, engineList, ComboBox, N_("Select engine from list:") }, + { 195, 14, 0, NULL, (void*) &EnterGroup, (char*) &selected, engineMnemonic, ListBox, N_("Select engine from list:") }, { 0, 0, 0, NULL, NULL, NULL, NULL, Label, N_("or specify one below:") }, { 0, 0, 0, NULL, (void*) &nickName, NULL, NULL, TextBox, N_("Nickname (optional):") }, { 0, 0, 0, NULL, (void*) &useNick, NULL, NULL, CheckBox, N_("Use nickname in PGN tag") }, { 0, 0, 32+3, NULL, (void*) &engineName, NULL, NULL, FileName, N_("Engine (*.exe):") }, { 0, 0, 0, NULL, (void*) ¶ms, NULL, NULL, TextBox, N_("command-line parameters:") }, + { 0, 0, 0, NULL, (void*) &wbOptions, NULL, NULL, TextBox, N_("Special WinBoard options:") }, { 0, 0, 0, NULL, (void*) &engineDir, NULL, NULL, PathName, N_("directory:") }, { 95, 0, 0, NULL, NULL, NULL, NULL, Label, N_("(Directory will be derived from engine path when left empty)") }, { 0, 0, 0, NULL, (void*) &addToList, NULL, NULL, CheckBox, N_("Add this engine to the list") }, { 0, 0, 0, NULL, (void*) &hasBook, NULL, NULL, CheckBox, N_("Must not use GUI book") }, + { 0, 0, 0, NULL, (void*) &storeVariant, NULL, NULL, CheckBox, N_("Force current variant with this engine") }, { 0, 0, 0, NULL, (void*) &isUCI, NULL, NULL, CheckBox, N_("UCI") }, { 0, 0, 0, NULL, (void*) &v1, NULL, NULL, CheckBox, N_("WB protocol v1 (skip waiting for features)") }, { 0, 0, 0, NULL, (void*) &isUCCI, NULL, NULL, CheckBox, N_("UCCI / USI (uses specified /uxiAdapter)") }, - { 0, 0, 0, NULL, (void*) &storeVariant, NULL, NULL, CheckBox, N_("Force current variant with this engine") }, - { 0, 0, 2, NULL, (void*) &engineChoice, (char*) engineNr, engineNr, ComboBox, N_("Load mentioned engine as") }, { 0, 1, 0, NULL, (void*) &InstallOK, "", NULL, EndMark , "" } }; @@ -679,32 +721,38 @@ EnterGroup(HWND hDlg) { char buf[MSG_SIZ]; HANDLE hwndCombo = GetDlgItem(hDlg, 2001+2*1); - int i = ComboBox_GetCurSel(hwndCombo); + int i = SendDlgItemMessage(hDlg, 2001+2*1, LB_GETCURSEL, 0, 0); if(i == 0) buf[0] = NULLCHAR; // back to top level else if(engineList[i][0] == '#') safeStrCpy(buf, engineList[i], MSG_SIZ); // group header, open group - else return 0; // normal line, select engine + else { + ASSIGN(engineLine, engineList[i]); + if(isUCCI) isUCI = 2; + if(!engineNr) Load(&first, 0); else Load(&second, 1); + EndDialog( hDlg, 0 ); + return 0; // normal line, select engine + } installOptions[0].max = NamesToList(firstChessProgramNames, engineList, engineMnemonic, buf); // replace list by only the group contents - SendMessage(hwndCombo, CB_RESETCONTENT, 0, 0); - SendMessage(hwndCombo, CB_ADDSTRING, 0, (LPARAM) buf); + SendMessage(hwndCombo, LB_RESETCONTENT, 0, 0); + SendMessage(hwndCombo, LB_ADDSTRING, 0, (LPARAM) buf); for(i=1; i