DEADSOFTWARE

gui: "yes/no" menu refactored to ease further changes
[d2df-sdl.git] / src / game / g_gui.pas
index 34436a6458ed56d0239f25fb459586e591e1c41d..08ecee3316b007a783f681974e47f58785f7fbe3 100644 (file)
@@ -65,7 +65,7 @@ type
     wParam: LongInt;
     lParam: LongInt;
   end;
+
   TFontType = (FONT_TEXTURE, FONT_CHAR);
 
   TFont = class(TObject)
@@ -82,16 +82,16 @@ type
   end;
 
   TGUIControl = class;
+  TGUIWindow = class;
 
   TOnKeyDownEvent = procedure(Key: Byte);
+  TOnKeyDownEventEx = procedure(win: TGUIWindow; Key: Byte);
   TOnCloseEvent = procedure;
   TOnShowEvent = procedure;
   TOnClickEvent = procedure;
   TOnChangeEvent = procedure(Sender: TGUIControl);
   TOnEnterEvent = procedure(Sender: TGUIControl);
 
-  TGUIWindow = class;
-
   TGUIControl = class
   private
     FX, FY: Integer;
@@ -102,7 +102,7 @@ type
     constructor Create;
     procedure OnMessage(var Msg: TMessage); virtual;
     procedure Update; virtual;
-    procedure Draw; virtual;    
+    procedure Draw; virtual;
     property X: Integer read FX write FX;
     property Y: Integer read FY write FY;
     property Enabled: Boolean read FEnabled write FEnabled;
@@ -118,8 +118,10 @@ type
     FBackTexture: string;
     FMainWindow: Boolean;
     FOnKeyDown: TOnKeyDownEvent;
+    FOnKeyDownEx: TOnKeyDownEventEx;
     FOnCloseEvent: TOnCloseEvent;
     FOnShowEvent: TOnShowEvent;
+    FUserData: Pointer;
   public
     Childs: array of TGUIControl;
     constructor Create(Name: string);
@@ -131,12 +133,14 @@ type
     procedure SetActive(Control: TGUIControl);
     function GetControl(Name: string): TGUIControl;
     property OnKeyDown: TOnKeyDownEvent read FOnKeyDown write FOnKeyDown;
+    property OnKeyDownEx: TOnKeyDownEventEx read FOnKeyDownEx write FOnKeyDownEx;
     property OnClose: TOnCloseEvent read FOnCloseEvent write FOnCloseEvent;
     property OnShow: TOnShowEvent read FOnShowEvent write FOnShowEvent;
     property Name: string read FName;
     property DefControl: string read FDefControl write FDefControl;
     property BackTexture: string read FBackTexture write FBackTexture;
     property MainWindow: Boolean read FMainWindow write FMainWindow;
+    property UserData: Pointer read FUserData write FUserData;
   end;
 
   TGUITextButton = class(TGUIControl)
@@ -713,6 +717,7 @@ begin
   FActiveControl := nil;
   FName := Name;
   FOnKeyDown := nil;
+  FOnKeyDownEx := nil;
   FOnCloseEvent := nil;
   FOnShowEvent := nil;
 end;
@@ -765,6 +770,7 @@ procedure TGUIWindow.OnMessage(var Msg: TMessage);
 begin
   if FActiveControl <> nil then FActiveControl.OnMessage(Msg);
   if @FOnKeyDown <> nil then FOnKeyDown(Msg.wParam);
+  if @FOnKeyDownEx <> nil then FOnKeyDownEx(self, Msg.wParam);
 
   if Msg.Msg = WM_KEYDOWN then
     if Msg.wParam = IK_ESCAPE then
@@ -883,7 +889,7 @@ begin
   case Msg.Msg of
     WM_KEYDOWN:
       case Msg.wParam of
-        IK_RETURN: Click();
+        IK_RETURN, IK_KPRETURN: Click();
       end;
   end;
 end;
@@ -912,7 +918,7 @@ end;
 procedure TFont.Draw(X, Y: Integer; Text: string; R, G, B: Byte);
 begin
   if FFontType = FONT_CHAR then e_CharFont_PrintEx(ID, X, Y, Text, _RGB(R, G, B), FScale)
-  else e_TextureFontPrintEx(X, Y, Text, ID, R, G, B, FScale); 
+  else e_TextureFontPrintEx(X, Y, Text, ID, R, G, B, FScale);
 end;
 
 procedure TFont.GetTextSize(Text: string; var w, h: Word);
@@ -999,7 +1005,7 @@ begin
   FCounter := MAINMENU_MARKERDELAY;
 
   g_Texture_Get(MAINMENU_MARKER1, FMarkerID1);
-  g_Texture_Get(MAINMENU_MARKER2, FMarkerID2); 
+  g_Texture_Get(MAINMENU_MARKER2, FMarkerID2);
 
   FHeader := TGUILabel.Create(Header, FFontID);
   with FHeader do
@@ -1037,7 +1043,7 @@ begin
       if FButtons[a] <> nil then FButtons[a].Draw;
 
     if FIndex <> -1 then
-      e_Draw(FMarkerID1, FButtons[FIndex].FX-48, FButtons[FIndex].FY, 0, True, False); 
+      e_Draw(FMarkerID1, FButtons[FIndex].FX-48, FButtons[FIndex].FY, 0, True, False);
   end;
 end;
 
@@ -1097,7 +1103,7 @@ begin
   case Msg.Msg of
     WM_KEYDOWN:
       case Msg.wParam of
-        IK_UP:
+        IK_UP, IK_KPUP:
         begin
           repeat
             Dec(FIndex);
@@ -1106,7 +1112,7 @@ begin
 
           g_Sound_PlayEx(MENU_CHANGESOUND);
         end;
-        IK_DOWN:
+        IK_DOWN, IK_KPDOWN:
         begin
           repeat
             Inc(FIndex);
@@ -1115,7 +1121,7 @@ begin
 
           g_Sound_PlayEx(MENU_CHANGESOUND);
         end;
-        IK_RETURN: if (FIndex <> -1) and FButtons[FIndex].FEnabled then FButtons[FIndex].Click;
+        IK_RETURN, IK_KPRETURN: if (FIndex <> -1) and FButtons[FIndex].FEnabled then FButtons[FIndex].Click;
       end;
   end;
 end;
@@ -1142,7 +1148,7 @@ constructor TGUILabel.Create(Text: string; FontID: DWORD);
 begin
   inherited Create();
 
-  FFont := TFont.Create(FontID, FONT_CHAR); 
+  FFont := TFont.Create(FontID, FONT_CHAR);
 
   FText := Text;
   FFixedLen := 0;
@@ -1169,8 +1175,8 @@ begin
   if FFixedLen = 0 then
     FFont.GetTextSize(FText, w, h)
   else
-    w := e_CharFont_GetMaxWidth(FFont.ID)*FFixedLen; 
-  Result := w; 
+    w := e_CharFont_GetMaxWidth(FFont.ID)*FFixedLen;
+  Result := w;
 end;
 
 procedure TGUILabel.OnMessage(var Msg: TMessage);
@@ -1182,7 +1188,7 @@ begin
   case Msg.Msg of
     WM_KEYDOWN:
       case Msg.wParam of
-        IK_RETURN: if @FOnClickEvent <> nil then FOnClickEvent();
+        IK_RETURN, IK_KPRETURN: if @FOnClickEvent <> nil then FOnClickEvent();
       end;
   end;
 end;
@@ -1343,9 +1349,9 @@ begin
       y := FItems[FIndex].Control.FY;
     end;
 
-    x := x-e_CharFont_GetMaxWidth(FFontID); 
+    x := x-e_CharFont_GetMaxWidth(FFontID);
 
-    e_CharFont_PrintEx(FFontID, x, y, #16, _RGB(255, 0, 0)); 
+    e_CharFont_PrintEx(FFontID, x, y, #16, _RGB(255, 0, 0));
   end;
 end;
 
@@ -1416,7 +1422,7 @@ begin
     WM_KEYDOWN:
     begin
       case Msg.wParam of
-        IK_UP:
+        IK_UP, IK_KPUP:
         begin
           c := 0;
           repeat
@@ -1437,7 +1443,7 @@ begin
           g_Sound_PlayEx(MENU_CHANGESOUND);
         end;
 
-        IK_DOWN:
+        IK_DOWN, IK_KPDOWN:
         begin
           c := 0;
           repeat
@@ -1458,13 +1464,13 @@ begin
           g_Sound_PlayEx(MENU_CHANGESOUND);
         end;
 
-        IK_LEFT, IK_RIGHT:
+        IK_LEFT, IK_RIGHT, IK_KPLEFT, IK_KPRIGHT:
         begin
           if FIndex <> -1 then
             if FItems[FIndex].Control <> nil then
               FItems[FIndex].Control.OnMessage(Msg);
         end;
-        IK_RETURN:
+        IK_RETURN, IK_KPRETURN:
         begin
           if FIndex <> -1 then
             if FItems[FIndex].Control <> nil then
@@ -1903,14 +1909,14 @@ begin
     WM_KEYDOWN:
     begin
       case Msg.wParam of
-        IK_LEFT:
+        IK_LEFT, IK_KPLEFT:
           if FValue > 0 then
           begin
             Dec(FValue);
             g_Sound_PlayEx(SCROLL_SUBSOUND);
             if @FOnChangeEvent <> nil then FOnChangeEvent(Self);
           end;
-        IK_RIGHT:
+        IK_RIGHT, IK_KPRIGHT:
           if FValue < FMax then
           begin
             Inc(FValue);
@@ -1987,7 +1993,7 @@ begin
   case Msg.Msg of
     WM_KEYDOWN:
       case Msg.wParam of
-        IK_RETURN, IK_RIGHT:
+        IK_RETURN, IK_RIGHT, IK_KPRETURN, IK_KPRIGHT:
         begin
           if FIndex < High(FItems) then
             Inc(FIndex)
@@ -1998,7 +2004,7 @@ begin
             FOnChangeEvent(Self);
         end;
 
-    IK_LEFT:
+    IK_LEFT, IK_KPLEFT:
       begin
         if FIndex > 0 then
           Dec(FIndex)
@@ -2097,11 +2103,11 @@ begin
             if FCaretPos > 0 then Dec(FCaretPos);
           end;
           IK_DELETE: Delete(FText, FCaretPos + 1, 1);
-          IK_END: FCaretPos := Length(FText);
-          IK_HOME: FCaretPos := 0;
-          IK_LEFT: if FCaretPos > 0 then Dec(FCaretPos);
-          IK_RIGHT: if FCaretPos < Length(FText) then Inc(FCaretPos);
-          IK_RETURN:
+          IK_END, IK_KPEND: FCaretPos := Length(FText);
+          IK_HOME, IK_KPHOME: FCaretPos := 0;
+          IK_LEFT, IK_KPLEFT: if FCaretPos > 0 then Dec(FCaretPos);
+          IK_RIGHT, IK_KPRIGHT: if FCaretPos < Length(FText) then Inc(FCaretPos);
+          IK_RETURN, IK_KPRETURN:
             with FWindow do
             begin
               if FActiveControl <> Self then
@@ -2155,7 +2161,7 @@ var
   w, h: Word;
 begin
   Result := 0;
+
   for a := 0 to 255 do
   begin
     FFont.GetTextSize(e_KeyNames[a], w, h);
@@ -2191,7 +2197,7 @@ begin
 
               FIsQuery := False;
             end;
-          IK_RETURN:
+          IK_RETURN, IK_KPRETURN:
             begin
               if not FIsQuery then
                 begin
@@ -2205,18 +2211,18 @@ begin
                 begin
                   FKey := IK_ENTER; // <Enter>
                   FIsQuery := False;
-                  
+
                   with FWindow do
                     if FDefControl <> '' then
                       SetActive(GetControl(FDefControl))
                     else
                       SetActive(nil);
-                end;   
+                end;
             end;
         end;
 
       MESSAGE_DIKEY:
-        if FIsQuery and (wParam <> IK_ENTER) then // Not <Enter
+        if FIsQuery and (wParam <> IK_ENTER) and (wParam <> IK_KPRETURN) then // Not <Enter
         begin
           if e_KeyNames[wParam] <> '' then
             FKey := wParam;
@@ -2253,7 +2259,7 @@ begin
 
   DrawBox(FX, FY, 4, 4);
 
-  if FModel <> nil then FModel.Draw(FX+4, FY+4); 
+  if FModel <> nil then FModel.Draw(FX+4, FY+4);
 end;
 
 procedure TGUIModelView.NextAnim();
@@ -2286,7 +2292,7 @@ end;
 
 procedure TGUIModelView.SetColor(Red, Green, Blue: Byte);
 begin
-  if FModel <> nil then FModel.SetColor(Red, Green, Blue); 
+  if FModel <> nil then FModel.SetColor(Red, Green, Blue);
 end;
 
 procedure TGUIModelView.SetModel(ModelName: string);
@@ -2302,7 +2308,7 @@ begin
 
   a := not a;
   if a then Exit;
+
   if FModel <> nil then FModel.Update;
 end;
 
@@ -2335,7 +2341,7 @@ begin
   e_DrawFillQuad(FX+4, FY+4,
     FX+4 + Trunc(FMapSize.X / FScale) - 1,
     FY+4 + Trunc(FMapSize.Y / FScale) - 1,
-    32, 32, 32, 0);     
+    32, 32, 32, 0);
 
   if FMapData <> nil then
     for a := 0 to High(FMapData) do
@@ -2346,7 +2352,7 @@ begin
 
         if X2 < 0 then Continue;
         if Y2 < 0 then Continue;
-     
+
         if X2 > MAPPREVIEW_WIDTH*16 then X2 := MAPPREVIEW_WIDTH*16;
         if Y2 > MAPPREVIEW_HEIGHT*16 then Y2 := MAPPREVIEW_HEIGHT*16;
 
@@ -2593,12 +2599,12 @@ end;
 
 function TGUIListBox.GetHeight: Word;
 begin
-  Result := 8+FHeight*16; 
+  Result := 8+FHeight*16;
 end;
 
 function TGUIListBox.GetWidth: Word;
 begin
-  Result := 8+(FWidth+1)*16; 
+  Result := 8+(FWidth+1)*16;
 end;
 
 procedure TGUIListBox.OnMessage(var Msg: TMessage);
@@ -2615,31 +2621,31 @@ begin
     case Msg of
       WM_KEYDOWN:
         case wParam of
-          IK_HOME:
+          IK_HOME, IK_KPHOME:
           begin
             FIndex := 0;
             FStartLine := 0;
           end;
-          IK_END:
+          IK_END, IK_KPEND:
           begin
             FIndex := High(FItems);
             FStartLine := Max(High(FItems)-FHeight+1, 0);
           end;
-          IK_UP, IK_LEFT:
+          IK_UP, IK_LEFT, IK_KPUP, IK_KPLEFT:
             if FIndex > 0 then
             begin
               Dec(FIndex);
               if FIndex < FStartLine then Dec(FStartLine);
               if @FOnChangeEvent <> nil then FOnChangeEvent(Self);
             end;
-          IK_DOWN, IK_RIGHT:
+          IK_DOWN, IK_RIGHT, IK_KPDOWN, IK_KPRIGHT:
             if FIndex < High(FItems) then
             begin
               Inc(FIndex);
               if FIndex > FStartLine+FHeight-1 then Inc(FStartLine);
               if @FOnChangeEvent <> nil then FOnChangeEvent(Self);
             end;
-          IK_RETURN:
+          IK_RETURN, IK_KPRETURN:
             with FWindow do
             begin
               if FActiveControl <> Self then SetActive(Self)
@@ -2675,7 +2681,7 @@ procedure TGUIListBox.FSetItems(Items: SArray);
 begin
   if FItems <> nil then
     FItems := nil;
-   
+
   FItems := Items;
 
   FStartLine := 0;
@@ -2739,7 +2745,7 @@ begin
     case Msg of
       WM_KEYDOWN:
         case wParam of
-          IK_HOME:
+          IK_HOME, IK_KPHOME:
             begin
               FIndex := 0;
               FStartLine := 0;
@@ -2747,7 +2753,7 @@ begin
                 FOnChangeEvent(Self);
             end;
 
-          IK_END:
+          IK_END, IK_KPEND:
             begin
               FIndex := High(FItems);
               FStartLine := Max(High(FItems)-FHeight+1, 0);
@@ -2755,7 +2761,7 @@ begin
                 FOnChangeEvent(Self);
             end;
 
-          IK_PAGEUP:
+          IK_PAGEUP, IK_KPPAGEUP:
             begin
               if FIndex > FHeight then
                 FIndex := FIndex-FHeight
@@ -2768,7 +2774,7 @@ begin
                 FStartLine := 0;
             end;
 
-          IK_PAGEDN:
+          IK_PAGEDN, IK_KPPAGEDN:
             begin
               if FIndex < High(FItems)-FHeight then
                 FIndex := FIndex+FHeight
@@ -2781,7 +2787,7 @@ begin
                 FStartLine := High(FItems)-FHeight+1;
             end;
 
-          IK_UP, IK_LEFT:
+          IK_UP, IK_LEFT, IK_KPUP, IK_KPLEFT:
             if FIndex > 0 then
             begin
               Dec(FIndex);
@@ -2791,7 +2797,7 @@ begin
                 FOnChangeEvent(Self);
             end;
 
-          IK_DOWN, IK_RIGHT:
+          IK_DOWN, IK_RIGHT, IK_KPDOWN, IK_KPRIGHT:
             if FIndex < High(FItems) then
             begin
               Inc(FIndex);
@@ -2801,7 +2807,7 @@ begin
                 FOnChangeEvent(Self);
             end;
 
-          IK_RETURN:
+          IK_RETURN, IK_KPRETURN:
             with FWindow do
             begin
               if FActiveControl <> Self then
@@ -2844,13 +2850,14 @@ procedure TGUIFileListBox.OpenDir(path: String);
 var
   SR: TSearchRec;
   i: Integer;
+  sm, sc: string;
 begin
   Clear();
 
   path := IncludeTrailingPathDelimiter(path);
   path := ExpandFileName(path);
 
-// Êàòàëîãè:
+  // Êàòàëîãè:
   if FDirs then
   begin
     if FindFirst(path+'*', faDirectory, SR) = 0 then
@@ -2867,13 +2874,17 @@ begin
     FindClose(SR);
   end;
 
-// Ôàéëû:
-  if FindFirst(path+FFileMask, faAnyFile, SR) = 0 then
-    repeat
-      AddItem(SR.Name);
-    until FindNext(SR) <> 0;
-
-  FindClose(SR);
+  // Ôàéëû:
+  sm := FFileMask;
+  while sm <> '' do
+  begin
+    i := Pos('|', sm);
+    if i = 0 then i := length(sm)+1;
+    sc := Copy(sm, 1, i-1);
+    Delete(sm, 1, i);
+    if FindFirst(path+sc, faAnyFile, SR) = 0 then repeat AddItem(SR.Name); until FindNext(SR) <> 0;
+    FindClose(SR);
+  end;
 
   for i := 0 to High(FItems) do
     if FItems[i][1] = #1 then
@@ -2907,7 +2918,7 @@ var
 begin
   if (FIndex = -1) or (FItems = nil) or
      (FIndex > High(FItems)) or
-     (FItems[FIndex][1] = '/') or 
+     (FItems[FIndex][1] = '/') or
      (FItems[FIndex][1] = '\') then
     fn := ''
   else
@@ -2977,13 +2988,13 @@ begin
     case Msg of
       WM_KEYDOWN:
         case wParam of
-          IK_UP, IK_LEFT:
+          IK_UP, IK_LEFT, IK_KPUP, IK_KPLEFT:
             if FStartLine > 0 then
               Dec(FStartLine);
-          IK_DOWN, IK_RIGHT:
+          IK_DOWN, IK_RIGHT, IK_KPDOWN, IK_KPRIGHT:
             if FStartLine < Length(FLines)-FHeight then
               Inc(FStartLine);
-          IK_RETURN:
+          IK_RETURN, IK_KPRETURN:
             with FWindow do
             begin
               if FActiveControl <> Self then
@@ -3034,7 +3045,7 @@ begin
   inherited;
 
   if FImageRes = '' then
-  begin   
+  begin
     if g_Texture_Get(FDefaultRes, ID) then e_Draw(ID, FX, FY, 0, True, False);
   end
   else