]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Favorites tab for the construction menu (#26347)
authorArtjom <artjombebenin@gmail.com>
Sat, 29 Jun 2024 04:10:00 +0000 (08:10 +0400)
committerGitHub <noreply@github.com>
Sat, 29 Jun 2024 04:10:00 +0000 (14:10 +1000)
* Added fovarite button

* Some fixes in xaml

* added some events for favorite recipes

* set methods for presenter

* fixes for  presenter

* added translates

* reset seach when you select any category

* added some margins

* some fixes from compared

* fixed PR notes about arrays

* deleted controls & margins

* did simpleer with arrays

* review

---------

Co-authored-by: metalgearsloth <comedian_vs_clown@hotmail.com>
Content.Client/Construction/UI/ConstructionMenu.xaml
Content.Client/Construction/UI/ConstructionMenu.xaml.cs
Content.Client/Construction/UI/ConstructionMenuPresenter.cs
Resources/Locale/en-US/construction/construction-categories.ftl

index dd210d972933d29fe55772ddae9cd6772f280e93..6e4438cf6fdc6c8df8513b9934b6cce80d7fe113 100644 (file)
@@ -1,29 +1,33 @@
 <DefaultWindow xmlns="https://spacestation14.io">
     <BoxContainer Orientation="Horizontal" HorizontalExpand="True">
-        <BoxContainer Orientation="Vertical" HorizontalExpand="True" SizeFlagsStretchRatio="0.4">
-            <BoxContainer Orientation="Horizontal" HorizontalExpand="True">
+        <BoxContainer Orientation="Vertical" HorizontalExpand="True" SizeFlagsStretchRatio="0.4" Margin="0 0 5 0">
+            <BoxContainer Orientation="Horizontal" HorizontalExpand="True" Margin="0 0 0 5">
                 <LineEdit Name="SearchBar" PlaceHolder="Search" HorizontalExpand="True"/>
-                <OptionButton Name="Category" Access="Public" MinSize="130 0"/>
+                <OptionButton Name="OptionCategories" Access="Public" MinSize="130 0"/>
             </BoxContainer>
             <ItemList Name="Recipes" Access="Public" SelectMode="Single" VerticalExpand="True"/>
         </BoxContainer>
-        <Control MinSize="10 0"/>
         <BoxContainer Orientation="Vertical" HorizontalExpand="True" SizeFlagsStretchRatio="0.6">
+            <Button Name="FavoriteButton" Visible="false" HorizontalExpand="False"
+                HorizontalAlignment="Right" Margin="0 0 0 15"/>
             <Control>
-                <BoxContainer Orientation="Horizontal" Align="Center">
-                    <TextureRect Name="TargetTexture" HorizontalAlignment="Right" Stretch="Keep"/>
-                    <Control MinSize="10 0"/>
-                    <BoxContainer Orientation="Vertical">
-                        <RichTextLabel Name="TargetName"/>
-                        <RichTextLabel Name="TargetDesc"/>
+                <BoxContainer Orientation="Vertical" HorizontalExpand="True" Margin="0 0 0 5">
+                    <BoxContainer Orientation="Horizontal" Align="Center">
+                        <TextureRect Name="TargetTexture" HorizontalAlignment="Right" Stretch="Keep" Margin="0 0 10 0"/>
+                        <BoxContainer Orientation="Vertical">
+                            <RichTextLabel Name="TargetName"/>
+                            <RichTextLabel Name="TargetDesc"/>
+                        </BoxContainer>
                     </BoxContainer>
                 </BoxContainer>
             </Control>
-            <ItemList Name="RecipeStepList" Access="Public" VerticalExpand="True"/>
+            <ItemList Name="RecipeStepList" Access="Public" VerticalExpand="True" Margin="0 0 0 5"/>
             <BoxContainer Orientation="Vertical">
-                <Button Name="BuildButton" Disabled="True" ToggleMode="True" VerticalExpand="True" SizeFlagsStretchRatio="0.5"/>
+                <Button Name="BuildButton" Disabled="True" ToggleMode="True"
+                        VerticalExpand="True" SizeFlagsStretchRatio="0.5"/>
                 <BoxContainer Orientation="Horizontal" VerticalExpand="True" SizeFlagsStretchRatio="0.5">
-                    <Button Name="EraseButton" ToggleMode="True" HorizontalExpand="True" SizeFlagsStretchRatio="0.7"/>
+                    <Button Name="EraseButton" ToggleMode="True"
+                        HorizontalExpand="True" SizeFlagsStretchRatio="0.7"/>
                     <Button Name="ClearButton" HorizontalExpand="True" SizeFlagsStretchRatio="0.3"/>
                 </BoxContainer>
             </BoxContainer>
index 8fce1dbbda0f95c7c63e37affcdfd25e1eea768e..f0cb8148762591ac1c39d9a0f772cfbdabe9caf2 100644 (file)
@@ -22,7 +22,7 @@ namespace Content.Client.Construction.UI
         // It isn't optimal to expose UI controls like this, but the UI control design is
         // questionable so it can't be helped.
         string[] Categories { get; set; }
-        OptionButton Category { get; }
+        OptionButton OptionCategories { get; }
 
         bool EraseButtonPressed { get; set; }
         bool BuildButtonPressed { get; set; }
@@ -32,12 +32,13 @@ namespace Content.Client.Construction.UI
 
         event EventHandler<(string search, string catagory)> PopulateRecipes;
         event EventHandler<ItemList.Item?> RecipeSelected;
+        event EventHandler RecipeFavorited;
         event EventHandler<bool> BuildButtonToggled;
         event EventHandler<bool> EraseButtonToggled;
         event EventHandler ClearAllGhosts;
 
         void ClearRecipeInfo();
-        void SetRecipeInfo(string name, string description, Texture iconTexture, bool isItem);
+        void SetRecipeInfo(string name, string description, Texture iconTexture, bool isItem, bool isFavorite);
         void ResetPlacement();
 
         #region Window Control
@@ -84,10 +85,12 @@ namespace Content.Client.Construction.UI
             Recipes.OnItemSelected += obj => RecipeSelected?.Invoke(this, obj.ItemList[obj.ItemIndex]);
             Recipes.OnItemDeselected += _ => RecipeSelected?.Invoke(this, null);
 
-            SearchBar.OnTextChanged += _ => PopulateRecipes?.Invoke(this, (SearchBar.Text, Categories[Category.SelectedId]));
-            Category.OnItemSelected += obj =>
+            SearchBar.OnTextChanged += _ =>
+                PopulateRecipes?.Invoke(this, (SearchBar.Text, Categories[OptionCategories.SelectedId]));
+            OptionCategories.OnItemSelected += obj =>
             {
-                Category.SelectId(obj.Id);
+                OptionCategories.SelectId(obj.Id);
+                SearchBar.SetText(string.Empty);
                 PopulateRecipes?.Invoke(this, (SearchBar.Text, Categories[obj.Id]));
             };
 
@@ -97,12 +100,14 @@ namespace Content.Client.Construction.UI
             ClearButton.OnPressed += _ => ClearAllGhosts?.Invoke(this, EventArgs.Empty);
             EraseButton.Text = Loc.GetString("construction-menu-eraser-mode");
             EraseButton.OnToggled += args => EraseButtonToggled?.Invoke(this, args.Pressed);
+
+            FavoriteButton.OnPressed += args => RecipeFavorited?.Invoke(this, EventArgs.Empty);
         }
 
         public event EventHandler? ClearAllGhosts;
-
         public event EventHandler<(string search, string catagory)>? PopulateRecipes;
         public event EventHandler<ItemList.Item?>? RecipeSelected;
+        public event EventHandler? RecipeFavorited;
         public event EventHandler<bool>? BuildButtonToggled;
         public event EventHandler<bool>? EraseButtonToggled;
 
@@ -112,13 +117,17 @@ namespace Content.Client.Construction.UI
             EraseButton.Pressed = false;
         }
 
-        public void SetRecipeInfo(string name, string description, Texture iconTexture, bool isItem)
+        public void SetRecipeInfo(
+            string name, string description, Texture iconTexture, bool isItem, bool isFavorite)
         {
             BuildButton.Disabled = false;
             BuildButton.Text = Loc.GetString(isItem ? "construction-menu-place-ghost" : "construction-menu-craft");
             TargetName.SetMessage(name);
             TargetDesc.SetMessage(description);
             TargetTexture.Texture = iconTexture;
+            FavoriteButton.Visible = true;
+            FavoriteButton.Text = Loc.GetString(
+                            isFavorite ? "construction-add-favorite-button" : "construction-remove-from-favorite-button");
         }
 
         public void ClearRecipeInfo()
@@ -127,6 +136,7 @@ namespace Content.Client.Construction.UI
             TargetName.SetMessage(string.Empty);
             TargetDesc.SetMessage(string.Empty);
             TargetTexture.Texture = null;
+            FavoriteButton.Visible = false;
             RecipeStepList.Clear();
         }
     }
index 0c7912e0bcd5507837fe95a18645217e02147bf5..c315cdedb2ca92d8ae6fd35b4e38b20da3dc055c 100644 (file)
@@ -36,7 +36,10 @@ namespace Content.Client.Construction.UI
 
         private ConstructionSystem? _constructionSystem;
         private ConstructionPrototype? _selected;
-
+        private List<ConstructionPrototype> _favoritedRecipes = [];
+        private string _selectedCategory = string.Empty;
+        private string _favoriteCatName = "construction-category-favorites";
+        private string _forAllCategoryName = "construction-category-all";
         private bool CraftingAvailable
         {
             get => _uiManager.GetActiveUIWidget<GameTopMenuBar>().CraftingButton.Visible;
@@ -65,7 +68,7 @@ namespace Content.Client.Construction.UI
                     else
                         _constructionView.OpenCentered();
 
-                    if(_selected != null)
+                    if (_selected != null)
                         PopulateInfo(_selected);
                 }
                 else
@@ -105,9 +108,10 @@ namespace Content.Client.Construction.UI
                 _constructionView.EraseButtonPressed = b;
             };
 
+            _constructionView.RecipeFavorited += (_, _) => OnViewFavoriteRecipe();
+
             PopulateCategories();
             OnViewPopulateRecipes(_constructionView, (string.Empty, string.Empty));
-
         }
 
         public void OnHudCraftingButtonToggled(ButtonToggledEventArgs args)
@@ -154,6 +158,13 @@ namespace Content.Client.Construction.UI
             recipesList.Clear();
             var recipes = new List<ConstructionPrototype>();
 
+            var isEmptyCategory = string.IsNullOrEmpty(category) || category == _forAllCategoryName;
+
+            if (isEmptyCategory)
+                _selectedCategory = string.Empty;
+            else
+                _selectedCategory = category;
+
             foreach (var recipe in _prototypeManager.EnumeratePrototypes<ConstructionPrototype>())
             {
                 if (recipe.Hide)
@@ -170,10 +181,19 @@ namespace Content.Client.Construction.UI
                         continue;
                 }
 
-                if (!string.IsNullOrEmpty(category) && category != "construction-category-all")
+                if (!isEmptyCategory)
                 {
-                    if (recipe.Category != category)
+                    if (category == _favoriteCatName)
+                    {
+                        if (!_favoritedRecipes.Contains(recipe))
+                        {
+                            continue;
+                        }
+                    }
+                    else if (recipe.Category != category)
+                    {
                         continue;
+                    }
                 }
 
                 recipes.Add(recipe);
@@ -189,13 +209,10 @@ namespace Content.Client.Construction.UI
             // There is apparently no way to set which
         }
 
-        private void PopulateCategories()
+        private void PopulateCategories(string? selectCategory = null)
         {
             var uniqueCategories = new HashSet<string>();
 
-            // hard-coded to show all recipes
-            uniqueCategories.Add("construction-category-all");
-
             foreach (var prototype in _prototypeManager.EnumeratePrototypes<ConstructionPrototype>())
             {
                 var category = prototype.Category;
@@ -204,25 +221,49 @@ namespace Content.Client.Construction.UI
                     uniqueCategories.Add(category);
             }
 
-            _constructionView.Category.Clear();
+            var isFavorites = _favoritedRecipes.Count > 0;
+            var categoriesArray = new string[isFavorites ? uniqueCategories.Count + 2 : uniqueCategories.Count + 1];
 
-            var array = uniqueCategories.OrderBy(Loc.GetString).ToArray();
-            Array.Sort(array);
+            // hard-coded to show all recipes
+            var idx = 0;
+            categoriesArray[idx++] = _forAllCategoryName;
+
+            // hard-coded to show favorites if it need
+            if (isFavorites)
+            {
+                categoriesArray[idx++] = _favoriteCatName;
+            }
 
-            for (var i = 0; i < array.Length; i++)
+            var sortedProtoCategories = uniqueCategories.OrderBy(Loc.GetString);
+
+            foreach (var cat in sortedProtoCategories)
             {
-                var category = array[i];
-                _constructionView.Category.AddItem(Loc.GetString(category), i);
+                categoriesArray[idx++] = cat;
             }
 
-            _constructionView.Categories = array;
+            _constructionView.OptionCategories.Clear();
+
+            for (var i = 0; i < categoriesArray.Length; i++)
+            {
+                _constructionView.OptionCategories.AddItem(Loc.GetString(categoriesArray[i]), i);
+
+                if (!string.IsNullOrEmpty(selectCategory) && selectCategory == categoriesArray[i])
+                    _constructionView.OptionCategories.SelectId(i);
+
+            }
+
+            _constructionView.Categories = categoriesArray;
         }
 
         private void PopulateInfo(ConstructionPrototype prototype)
         {
             var spriteSys = _systemManager.GetEntitySystem<SpriteSystem>();
             _constructionView.ClearRecipeInfo();
-            _constructionView.SetRecipeInfo(prototype.Name, prototype.Description, spriteSys.Frame0(prototype.Icon), prototype.Type != ConstructionType.Item);
+
+            _constructionView.SetRecipeInfo(
+                prototype.Name, prototype.Description, spriteSys.Frame0(prototype.Icon),
+                prototype.Type != ConstructionType.Item,
+                !_favoritedRecipes.Contains(prototype));
 
             var stepList = _constructionView.RecipeStepList;
             GenerateStepList(prototype, stepList);
@@ -240,7 +281,7 @@ namespace Content.Client.Construction.UI
                 var text = entry.Arguments != null
                     ? Loc.GetString(entry.Localization, entry.Arguments) : Loc.GetString(entry.Localization);
 
-                if (entry.EntryNumber is {} number)
+                if (entry.EntryNumber is { } number)
                 {
                     text = Loc.GetString("construction-presenter-step-wrapper",
                         ("step-number", number), ("text", text));
@@ -332,6 +373,26 @@ namespace Content.Client.Construction.UI
             if (args.System is ConstructionSystem) SystemBindingChanged(null);
         }
 
+        private void OnViewFavoriteRecipe()
+        {
+            if (_selected is not ConstructionPrototype recipe)
+                return;
+
+            if (!_favoritedRecipes.Remove(_selected))
+                _favoritedRecipes.Add(_selected);
+
+            if (_selectedCategory == _favoriteCatName)
+            {
+                if (_favoritedRecipes.Count > 0)
+                    OnViewPopulateRecipes(_constructionView, (string.Empty, _favoriteCatName));
+                else
+                    OnViewPopulateRecipes(_constructionView, (string.Empty, string.Empty));
+            }
+
+            PopulateInfo(_selected);
+            PopulateCategories(_selectedCategory);
+        }
+
         private void SystemBindingChanged(ConstructionSystem? newSystem)
         {
             if (newSystem is null)
index cb31edad85de5cecb3c634fe544ad30fa75f62f8..5c44da51d19c22cf9246841135da1bd0eaf6c85a 100644 (file)
@@ -10,3 +10,6 @@ construction-category-tiles = Tiles
 construction-category-utilities = Utilities
 construction-category-misc = Misc
 construction-category-clothing = Clothing
+construction-category-favorites = Favorites
+construction-add-favorite-button = Add to favorites
+construction-remove-from-favorite-button = Remove from favorites