DEADSOFTWARE

Holmes: better UI hotkeys; fitting windows to screen
[d2df-sdl.git] / src / game / g_holmes.pas
index 79c4349a32a98180e1be54c1ee5524f99d5b2a16..e23c43563bdc9f86ecea403d1577b74d3b2aae38 100644 (file)
@@ -24,7 +24,7 @@ uses
   g_textures, g_basic, e_graphics, g_phys, g_grid, g_player, g_monsters,
   g_window, g_map, g_triggers, g_items, g_game, g_panel, g_console, g_gfx,
   xprofiler,
-  sdlcarcass, glgfx, gh_ui;
+  sdlcarcass, glgfx, gh_ui_common, gh_ui;
 
 
 procedure g_Holmes_Draw ();
@@ -108,8 +108,9 @@ procedure createLayersWindow (); forward;
 procedure createOutlinesWindow (); forward;
 
 
-procedure toggleLayersWindowCB (me: TUIControl; checked: Integer);
+procedure toggleLayersWindowCB (me: TUIControl);
 begin
+  showLayersWindow := not showLayersWindow;
   if showLayersWindow then
   begin
     if (winLayers = nil) then createLayersWindow();
@@ -121,9 +122,9 @@ begin
   end;
 end;
 
-
-procedure toggleOutlineWindowCB (me: TUIControl; checked: Integer);
+procedure toggleOutlineWindowCB (me: TUIControl);
 begin
+  showOutlineWindow := not showOutlineWindow;
   if showOutlineWindow then
   begin
     if (winOutlines = nil) then createOutlinesWindow();
@@ -137,17 +138,102 @@ end;
 
 
 procedure createHelpWindow ();
+  procedure addHelpEmptyLine ();
+  var
+    stx: TUIStaticText;
+  begin
+    stx := TUIStaticText.Create();
+    stx.flExpand := true;
+    stx.halign := 0; // center
+    stx.text := '';
+    stx.header := false;
+    stx.line := false;
+    winHelp.appendChild(stx);
+  end;
+
+  procedure addHelpCaptionLine (const txt: AnsiString);
+  var
+    stx: TUIStaticText;
+  begin
+    stx := TUIStaticText.Create();
+    stx.flExpand := true;
+    stx.halign := 0; // center
+    stx.text := txt;
+    stx.header := true;
+    stx.line := true;
+    winHelp.appendChild(stx);
+  end;
+
+  procedure addHelpCaption (const txt: AnsiString);
+  var
+    stx: TUIStaticText;
+  begin
+    stx := TUIStaticText.Create();
+    stx.flExpand := true;
+    stx.halign := 0; // center
+    stx.text := txt;
+    stx.header := true;
+    stx.line := false;
+    winHelp.appendChild(stx);
+  end;
+
+  procedure addHelpKeyMouse (const key, txt, grp: AnsiString);
+  var
+    box: TUIHBox;
+    span: TUISpan;
+    stx: TUIStaticText;
+  begin
+    box := TUIHBox.Create();
+    box.flExpand := true;
+      // key
+      stx := TUIStaticText.Create();
+      stx.flExpand := true;
+      stx.halign := 1; // right
+      stx.valign := 0; // center
+      stx.text := key;
+      stx.header := true;
+      stx.line := false;
+      stx.flHGroup := grp;
+      box.appendChild(stx);
+      // span
+      span := TUISpan.Create();
+      span.flDefaultSize := TLaySize.Create(4, 1);
+      span.flExpand := true;
+      box.appendChild(span);
+      // text
+      stx := TUIStaticText.Create();
+      stx.flExpand := true;
+      stx.halign := -1; // left
+      stx.valign := 0; // center
+      stx.text := txt;
+      stx.header := false;
+      stx.line := false;
+      box.appendChild(stx);
+    winHelp.appendChild(box);
+  end;
+
+  procedure addHelpKey (const key, txt: AnsiString); begin addHelpKeyMouse(key, txt, 'help-keys'); end;
+  procedure addHelpMouse (const key, txt: AnsiString); begin addHelpKeyMouse(key, txt, 'help-mouse'); end;
+
 var
-  llb: TUISimpleText;
   slist: array of AnsiString = nil;
   cmd: PHolmesCommand;
   bind: THolmesBinding;
-  f, maxkeylen: Integer;
+  f: Integer;
+  {
+  llb: TUISimpleText;
+  maxkeylen: Integer;
   s: AnsiString;
+  }
 begin
+  winHelp := TUITopWindow.Create('Holmes Help');
+  winHelp.escClose := true;
+  winHelp.flHoriz := false;
+
+  // keyboard
   for cmd in cmdlist do cmd.helpmark := false;
 
-  maxkeylen := 0;
+  //maxkeylen := 0;
   for bind in keybinds do
   begin
     if (Length(bind.key) = 0) then continue;
@@ -156,7 +242,7 @@ begin
       if (Length(cmd.help) > 0) then
       begin
         cmd.helpmark := true;
-        if (maxkeylen < Length(bind.key)) then maxkeylen := Length(bind.key);
+        //if (maxkeylen < Length(bind.key)) then maxkeylen := Length(bind.key);
       end;
     end;
   end;
@@ -164,7 +250,7 @@ begin
   for cmd in cmdlist do
   begin
     if not cmd.helpmark then continue;
-    if (Length(cmd.help) = 0) then continue;
+    if (Length(cmd.help) = 0) then begin cmd.helpmark := false; continue; end;
     f := 0;
     while (f < Length(slist)) and (CompareText(slist[f], cmd.section) <> 0) do Inc(f);
     if (f = Length(slist)) then
@@ -174,11 +260,14 @@ begin
     end;
   end;
 
-  llb := TUISimpleText.Create(0, 0);
+  addHelpCaptionLine('KEYBOARD');
+  //llb := TUISimpleText.Create(0, 0);
   for f := 0 to High(slist) do
   begin
-    if (f > 0) then llb.appendItem('');
-    llb.appendItem(slist[f], true, true);
+    //if (f > 0) then llb.appendItem('');
+    if (f > 0) then addHelpEmptyLine();
+    //llb.appendItem(slist[f], true, true);
+    addHelpCaption(slist[f]);
     for cmd in cmdlist do
     begin
       if not cmd.helpmark then continue;
@@ -188,16 +277,20 @@ begin
         if (Length(bind.key) = 0) then continue;
         if (cmd.name = bind.cmdName) then
         begin
-          s := bind.key;
-          while (Length(s) < maxkeylen) do s += ' ';
-          s := '  '+s+' -- '+cmd.help;
-          llb.appendItem(s);
+          //s := bind.key;
+          //while (Length(s) < maxkeylen) do s += ' ';
+          //s := '  '+s+' -- '+cmd.help;
+          //llb.appendItem(s);
+          addHelpMouse(bind.key, cmd.help);
         end;
       end;
     end;
   end;
 
-  maxkeylen := 0;
+  // mouse
+  for cmd in cmdlist do cmd.helpmark := false;
+
+  //maxkeylen := 0;
   for bind in msbinds do
   begin
     if (Length(bind.key) = 0) then continue;
@@ -206,13 +299,15 @@ begin
       if (Length(cmd.help) > 0) then
       begin
         cmd.helpmark := true;
-        if (maxkeylen < Length(bind.key)) then maxkeylen := Length(bind.key);
+        //if (maxkeylen < Length(bind.key)) then maxkeylen := Length(bind.key);
       end;
     end;
   end;
 
-  llb.appendItem('');
-  llb.appendItem('mouse', true, true);
+  //llb.appendItem('');
+  //llb.appendItem('mouse', true, true);
+  if (f > 0) then addHelpEmptyLine();
+  addHelpCaptionLine('MOUSE');
   for bind in msbinds do
   begin
     if (Length(bind.key) = 0) then continue;
@@ -220,84 +315,146 @@ begin
     begin
       if (Length(cmd.help) > 0) then
       begin
-        s := bind.key;
-        while (Length(s) < maxkeylen) do s += ' ';
-        s := '  '+s+' -- '+cmd.help;
-        llb.appendItem(s);
+        //s := bind.key;
+        //while (Length(s) < maxkeylen) do s += ' ';
+        //s := '  '+s+' -- '+cmd.help;
+        //llb.appendItem(s);
+        addHelpKey(bind.key, cmd.help);
       end;
     end;
   end;
 
-  winHelp := TUITopWindow.Create('Holmes Help', 10, 10);
-  winHelp.escClose := true;
-  winHelp.appendChild(llb);
+  //winHelp.appendChild(llb);
+
+  uiLayoutCtl(winHelp);
   winHelp.centerInScreen();
 end;
 
 
-procedure winLayersClosed (me: TUIControl; dummy: Integer); begin showLayersWindow := false; end;
-procedure winOutlinesClosed (me: TUIControl; dummy: Integer); begin showOutlineWindow := false; end;
+procedure winLayersClosed (me: TUIControl); begin showLayersWindow := false; end;
+procedure winOutlinesClosed (me: TUIControl); begin showOutlineWindow := false; end;
+
+procedure addCheckBox (parent: TUIControl; const text: AnsiString; pvar: PBoolean);
+var
+  cb: TUICheckBox;
+begin
+  cb := TUICheckBox.Create();
+  cb.flExpand := true;
+  cb.setVar(pvar);
+  cb.text := text;
+  parent.appendChild(cb);
+end;
+
+procedure addButton (parent: TUIControl; const text: AnsiString; cb: TUIControl.TActionCB);
+var
+  but: TUIButton;
+begin
+  but := TUIButton.Create();
+  //but.flExpand := true;
+  but.actionCB := cb;
+  but.text := text;
+  parent.appendChild(but);
+end;
+
 
 procedure createLayersWindow ();
 var
-  llb: TUICBListBox;
+  box: TUIVBox;
 begin
-  llb := TUICBListBox.Create(0, 0);
-  llb.appendItem('background', @g_rlayer_back);
-  llb.appendItem('steps', @g_rlayer_step);
-  llb.appendItem('walls', @g_rlayer_wall);
-  llb.appendItem('doors', @g_rlayer_door);
-  llb.appendItem('acid1', @g_rlayer_acid1);
-  llb.appendItem('acid2', @g_rlayer_acid2);
-  llb.appendItem('water', @g_rlayer_water);
-  llb.appendItem('foreground', @g_rlayer_fore);
-  winLayers := TUITopWindow.Create('layers', 10, 10);
+  winLayers := TUITopWindow.Create('layers');
+  winLayers.flHoriz := false;
+  winLayers.x0 := 10;
+  winLayers.y0 := 10;
+  winLayers.flHoriz := false;
   winLayers.escClose := true;
-  winLayers.appendChild(llb);
   winLayers.closeCB := winLayersClosed;
+
+  box := TUIVBox.Create();
+    addCheckBox(box, '~background', @g_rlayer_back);
+    addCheckBox(box, '~steps', @g_rlayer_step);
+    addCheckBox(box, '~walls', @g_rlayer_wall);
+    addCheckBox(box, '~doors', @g_rlayer_door);
+    addCheckBox(box, 'acid~1', @g_rlayer_acid1);
+    addCheckBox(box, 'acid~2', @g_rlayer_acid2);
+    addCheckBox(box, 'wate~r', @g_rlayer_water);
+    addCheckBox(box, '~foreground', @g_rlayer_fore);
+  winLayers.appendChild(box);
+
+  uiLayoutCtl(winLayers);
 end;
 
 
 procedure createOutlinesWindow ();
 var
-  llb: TUICBListBox;
+  box: TUIVBox;
 begin
-  llb := TUICBListBox.Create(0, 0);
-  llb.appendItem('background', @g_ol_rlayer_back);
-  llb.appendItem('steps', @g_ol_rlayer_step);
-  llb.appendItem('walls', @g_ol_rlayer_wall);
-  llb.appendItem('doors', @g_ol_rlayer_door);
-  llb.appendItem('acid1', @g_ol_rlayer_acid1);
-  llb.appendItem('acid2', @g_ol_rlayer_acid2);
-  llb.appendItem('water', @g_ol_rlayer_water);
-  llb.appendItem('foreground', @g_ol_rlayer_fore);
-  llb.appendItem('OPTIONS', nil);
-  llb.appendItem('fill walls', @g_ol_fill_walls);
-  llb.appendItem('contours', @g_ol_nice);
-  winOutlines := TUITopWindow.Create('outlines', 100, 10);
+  winOutlines := TUITopWindow.Create('outlines');
+  winOutlines.flHoriz := false;
+  winOutlines.x0 := 100;
+  winOutlines.y0 := 30;
+  winOutlines.flHoriz := false;
   winOutlines.escClose := true;
-  winOutlines.appendChild(llb);
   winOutlines.closeCB := winOutlinesClosed;
+
+  box := TUIVBox.Create();
+  box.hasFrame := true;
+  box.caption := 'layers';
+    addCheckBox(box, '~background', @g_ol_rlayer_back);
+    addCheckBox(box, '~steps', @g_ol_rlayer_step);
+    addCheckBox(box, '~walls', @g_ol_rlayer_wall);
+    addCheckBox(box, '~doors', @g_ol_rlayer_door);
+    addCheckBox(box, 'acid~1', @g_ol_rlayer_acid1);
+    addCheckBox(box, 'acid~2', @g_ol_rlayer_acid2);
+    addCheckBox(box, 'wate~r', @g_ol_rlayer_water);
+    addCheckBox(box, '~foreground', @g_ol_rlayer_fore);
+  winOutlines.appendChild(box);
+
+  box := TUIVBox.Create();
+  box.hasFrame := true;
+  box.caption := 'options';
+    addCheckBox(box, 'fi~ll walls', @g_ol_fill_walls);
+    addCheckBox(box, 'con~tours', @g_ol_nice);
+  winOutlines.appendChild(box);
+
+  uiLayoutCtl(winOutlines);
 end;
 
 
 procedure createOptionsWindow ();
 var
-  llb: TUICBListBox;
+  box: TUIBox;
+  span: TUISpan;
 begin
-  llb := TUICBListBox.Create(0, 0);
-  llb.appendItem('map grid', @showGrid);
-  llb.appendItem('cursor position on map', @showMapCurPos);
-  llb.appendItem('monster info', @showMonsInfo);
-  llb.appendItem('monster LOS to player', @showMonsLOS2Plr);
-  llb.appendItem('monster cells (SLOW!)', @showAllMonsCells);
-  llb.appendItem('draw triggers (SLOW!)', @showTriggers);
-  llb.appendItem('WINDOWS', nil);
-  llb.appendItem('layers window', @showLayersWindow, toggleLayersWindowCB);
-  llb.appendItem('outline window', @showOutlineWindow, toggleOutlineWindowCB);
-  winOptions := TUITopWindow.Create('Holmes Options', 100, 100);
+  winOptions := TUITopWindow.Create('Holmes Options');
+  winOptions.flHoriz := false;
+  winOptions.flHoriz := false;
   winOptions.escClose := true;
-  winOptions.appendChild(llb);
+
+  box := TUIVBox.Create();
+  box.hasFrame := true;
+  box.caption := 'visual';
+    addCheckBox(box, 'map ~grid', @showGrid);
+    addCheckBox(box, 'cursor ~position on map', @showMapCurPos);
+    addCheckBox(box, '~monster info', @showMonsInfo);
+    addCheckBox(box, 'monster LO~S to player', @showMonsLOS2Plr);
+    addCheckBox(box, 'monster ~cells (SLOW!)', @showAllMonsCells);
+    addCheckBox(box, 'draw ~triggers (SLOW!)', @showTriggers);
+  winOptions.appendChild(box);
+
+  box := TUIHBox.Create();
+  box.hasFrame := true;
+  box.caption := 'windows';
+  box.captionAlign := 0;
+  box.flAlign := 0;
+    addButton(box, '~layers', toggleLayersWindowCB);
+    span := TUISpan.Create();
+      span.flExpand := true;
+      span.flDefaultSize := TLaySize.Create(4, 1);
+      box.appendChild(span);
+    addButton(box, '~outline', toggleOutlineWindowCB);
+  winOptions.appendChild(box);
+
+  uiLayoutCtl(winOptions);
   winOptions.centerInScreen();
 end;
 
@@ -305,13 +462,15 @@ end;
 procedure toggleLayersWindow (arg: Integer=-1);
 begin
   if (arg < 0) then showLayersWindow := not showLayersWindow else showLayersWindow := (arg > 0);
-  toggleLayersWindowCB(nil, 0);
+  showLayersWindow := not showLayersWindow; // hack for callback
+  toggleLayersWindowCB(nil);
 end;
 
 procedure toggleOutlineWindow (arg: Integer=-1);
 begin
   if (arg < 0) then showOutlineWindow := not showOutlineWindow else showOutlineWindow := (arg > 0);
-  toggleOutlineWindowCB(nil, 0);
+  showOutlineWindow := not showOutlineWindow; // hack for callback
+  toggleOutlineWindowCB(nil);
 end;
 
 procedure toggleHelpWindow (arg: Integer=-1);