mirror of
				https://github.com/Zelda64Recomp/Zelda64Recomp.git
				synced 2025-10-30 08:03:03 +00:00 
			
		
		
		
	WIP mod menu, fix some warnings
This commit is contained in:
		
							parent
							
								
									a05ac15dcd
								
							
						
					
					
						commit
						2c68c8bd29
					
				
					 22 changed files with 405 additions and 104 deletions
				
			
		| 
						 | 
				
			
			@ -182,6 +182,7 @@ set (SOURCES
 | 
			
		|||
    ${CMAKE_SOURCE_DIR}/src/ui/elements/ElementOptionTypeRange.cpp
 | 
			
		||||
    ${CMAKE_SOURCE_DIR}/src/ui/elements/ElementOptionTypeTextField.cpp
 | 
			
		||||
    ${CMAKE_SOURCE_DIR}/src/ui/elements/ElementModMenu.cpp
 | 
			
		||||
    ${CMAKE_SOURCE_DIR}/src/ui/elements/ElementModDetailsPanel.cpp
 | 
			
		||||
    ${CMAKE_SOURCE_DIR}/src/ui/elements/presets.cpp
 | 
			
		||||
 | 
			
		||||
    ${CMAKE_SOURCE_DIR}/rsp/aspMain.cpp
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										22
									
								
								assets/scss/package-lock.json
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										22
									
								
								assets/scss/package-lock.json
									
										
									
										generated
									
									
									
								
							| 
						 | 
				
			
			@ -307,11 +307,11 @@
 | 
			
		|||
      "dev": true
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/braces": {
 | 
			
		||||
      "version": "3.0.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
 | 
			
		||||
      "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
 | 
			
		||||
      "version": "3.0.3",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
 | 
			
		||||
      "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "fill-range": "^7.0.1"
 | 
			
		||||
        "fill-range": "^7.1.1"
 | 
			
		||||
      },
 | 
			
		||||
      "engines": {
 | 
			
		||||
        "node": ">=8"
 | 
			
		||||
| 
						 | 
				
			
			@ -638,9 +638,9 @@
 | 
			
		|||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/fill-range": {
 | 
			
		||||
      "version": "7.0.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
 | 
			
		||||
      "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
 | 
			
		||||
      "version": "7.1.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
 | 
			
		||||
      "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "to-regex-range": "^5.0.1"
 | 
			
		||||
      },
 | 
			
		||||
| 
						 | 
				
			
			@ -1192,12 +1192,12 @@
 | 
			
		|||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/micromatch": {
 | 
			
		||||
      "version": "4.0.5",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
 | 
			
		||||
      "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
 | 
			
		||||
      "version": "4.0.8",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
 | 
			
		||||
      "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "braces": "^3.0.2",
 | 
			
		||||
        "braces": "^3.0.3",
 | 
			
		||||
        "picomatch": "^2.3.1"
 | 
			
		||||
      },
 | 
			
		||||
      "engines": {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										74
									
								
								assets/scss/styles/components/ModDetails.scss
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								assets/scss/styles/components/ModDetails.scss
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,74 @@
 | 
			
		|||
.mod-details {
 | 
			
		||||
    display: block;
 | 
			
		||||
    position: relative;
 | 
			
		||||
    flex: 1 1 200%;
 | 
			
		||||
    height: 100%;
 | 
			
		||||
    flex-direction: column;
 | 
			
		||||
    border-bottom-right-radius: $border-radius-modal;
 | 
			
		||||
    background-color: $color-bg-overlay;
 | 
			
		||||
 | 
			
		||||
    &__header {
 | 
			
		||||
        display: flex;
 | 
			
		||||
        position: relative;
 | 
			
		||||
        flex-direction: row;
 | 
			
		||||
        width: 100%;
 | 
			
		||||
        height: auto;
 | 
			
		||||
        padding: space(16);
 | 
			
		||||
        // border-width: $border-width-thickness;
 | 
			
		||||
        // border-radius: $border-radius-modal;
 | 
			
		||||
        // border-color: $color-border;
 | 
			
		||||
        background: $color-bg-shadow;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &__thumbnail-container {
 | 
			
		||||
        height: auto;
 | 
			
		||||
        width: auto;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &__thumbnail {
 | 
			
		||||
        height: 100dp;
 | 
			
		||||
        width: 100dp;
 | 
			
		||||
        // max-width: 100dp;
 | 
			
		||||
        // max-height: 100dp;
 | 
			
		||||
        // padding: space(16);
 | 
			
		||||
        // border-bottom-width: $border-width-thickness;
 | 
			
		||||
        // border-top-left-radius: $border-radius-modal;
 | 
			
		||||
        // border-top-right-radius: $border-radius-modal;
 | 
			
		||||
        // border-bottom-color: $color-border;
 | 
			
		||||
        background-color: $color-bg-overlay;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &__header-details {
 | 
			
		||||
        display: flex;
 | 
			
		||||
        position: relative;
 | 
			
		||||
        flex-direction: column;
 | 
			
		||||
        justify-content:space-evenly;
 | 
			
		||||
        width: auto;
 | 
			
		||||
        height: auto;
 | 
			
		||||
        margin-left: space(16);
 | 
			
		||||
        overflow: hidden;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &__title {
 | 
			
		||||
        @extend %header-3;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &__version {
 | 
			
		||||
        @extend %label-md;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &__body {
 | 
			
		||||
        display: flex;
 | 
			
		||||
        position: relative;
 | 
			
		||||
        flex-direction: column;
 | 
			
		||||
        width: 100%;
 | 
			
		||||
        height: auto;
 | 
			
		||||
        padding-left: space(16);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &__authors, &__description {
 | 
			
		||||
        @extend %label-md;
 | 
			
		||||
        margin-top: space(16);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -76,12 +76,50 @@
 | 
			
		|||
        overflow-y: auto;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &__details {
 | 
			
		||||
        display: block;
 | 
			
		||||
    &__list-entry {
 | 
			
		||||
        @extend %nav-all;
 | 
			
		||||
        display: flex;
 | 
			
		||||
        position: relative;
 | 
			
		||||
        flex: 1 1 100%;
 | 
			
		||||
        height: 100%;
 | 
			
		||||
        border-bottom-right-radius: $border-radius-modal;
 | 
			
		||||
        flex-direction: row;
 | 
			
		||||
        width: 100%;
 | 
			
		||||
        height: auto;
 | 
			
		||||
        padding: space(4) space(8) space(4) space(8);
 | 
			
		||||
        border-width: $border-width-thickness;
 | 
			
		||||
        @include create-icon-button-variation($color-text);
 | 
			
		||||
        border-color: rgba($color-text, 0.05);
 | 
			
		||||
 | 
			
		||||
        &:hover, &:focus {
 | 
			
		||||
            cursor: pointer;
 | 
			
		||||
        }
 | 
			
		||||
        &[is_selected] {
 | 
			
		||||
            border-color: rgb(255,255,255);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &__list-entry-thumbnail {
 | 
			
		||||
        height: 100dp;
 | 
			
		||||
        width: 100dp;
 | 
			
		||||
        min-width: 100dp;
 | 
			
		||||
        min-height: 100dp;
 | 
			
		||||
        background-color: $color-bg-overlay;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &__list-entry-body {
 | 
			
		||||
        display: flex;
 | 
			
		||||
        position: relative;
 | 
			
		||||
        flex-direction: column;
 | 
			
		||||
        width: auto;
 | 
			
		||||
        height: 100dp;
 | 
			
		||||
        margin-left: space(16);
 | 
			
		||||
        overflow: hidden;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &__list-entry-name {
 | 
			
		||||
        @extend %label-md;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &__list-entry-description {
 | 
			
		||||
        padding-top: space(8);
 | 
			
		||||
        @extend %body;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,3 +15,4 @@
 | 
			
		|||
@import "./BottomLeft";
 | 
			
		||||
@import "./Prompt";
 | 
			
		||||
@import "./ModMenu";
 | 
			
		||||
@import "./ModDetails";
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -123,7 +123,7 @@ void ElementConfigGroup::OnAttributeChange(const Rml::ElementAttributes& changed
 | 
			
		|||
 | 
			
		||||
        const nlohmann::json& options = get_options(config_key);
 | 
			
		||||
 | 
			
		||||
        for (int i = 0; i < options.size(); i++) {
 | 
			
		||||
        for (size_t i = 0; i < options.size(); i++) {
 | 
			
		||||
            const auto &el = options[i];
 | 
			
		||||
            AddConfigOptionElement(el);
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -132,7 +132,6 @@ void ElementConfigOption::OnAttributeChange(const Rml::ElementAttributes& change
 | 
			
		|||
        try {
 | 
			
		||||
            auto value = recomp::config::get_config_store_value<std::string>("translations/" + config_key);
 | 
			
		||||
            SetTextLabel(value);
 | 
			
		||||
            printf("found type and translation\n");
 | 
			
		||||
            AddOptionTypeElement();
 | 
			
		||||
        } catch (const std::runtime_error& e) {
 | 
			
		||||
            SetTextLabel(e.what());
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										72
									
								
								src/ui/elements/ElementModDetailsPanel.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								src/ui/elements/ElementModDetailsPanel.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,72 @@
 | 
			
		|||
#include "ElementModDetailsPanel.h"
 | 
			
		||||
#include "presets.h"
 | 
			
		||||
#include "librecomp/mods.hpp"
 | 
			
		||||
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
#define MOD_DETAILS_BEM "mod-details"
 | 
			
		||||
 | 
			
		||||
namespace recompui {
 | 
			
		||||
 | 
			
		||||
static const std::string cls_base = BLOCK(MOD_DETAILS_BEM);
 | 
			
		||||
static const std::string cls_header = EL(MOD_DETAILS_BEM, "header");
 | 
			
		||||
static const std::string cls_thumbnail_container = EL(MOD_DETAILS_BEM, "thumbnail-container");
 | 
			
		||||
static const std::string cls_thumbnail = EL(MOD_DETAILS_BEM, "thumbnail");
 | 
			
		||||
static const std::string cls_header_details = EL(MOD_DETAILS_BEM, "header-details");
 | 
			
		||||
static const std::string cls_title = EL(MOD_DETAILS_BEM, "title");
 | 
			
		||||
static const std::string cls_version = EL(MOD_DETAILS_BEM, "version");
 | 
			
		||||
static const std::string cls_body = EL(MOD_DETAILS_BEM, "body");
 | 
			
		||||
static const std::string cls_authors = EL(MOD_DETAILS_BEM, "authors");
 | 
			
		||||
static const std::string cls_description = EL(MOD_DETAILS_BEM, "description");
 | 
			
		||||
 | 
			
		||||
ElementModDetailsPanel::ElementModDetailsPanel(const Rml::String& tag) : Rml::Element(tag)
 | 
			
		||||
{
 | 
			
		||||
    SetAttribute("recomp-store-element", true);
 | 
			
		||||
    Rml::ElementDocument *doc = GetOwnerDocument();
 | 
			
		||||
    SetClass(cls_base, true);
 | 
			
		||||
 | 
			
		||||
    {
 | 
			
		||||
        Rml::Element *header_el = add_div_with_class(doc, this, cls_header);
 | 
			
		||||
        {
 | 
			
		||||
            Rml::Element *thumbnail_container_el = add_div_with_class(doc, header_el, cls_thumbnail_container);
 | 
			
		||||
            {
 | 
			
		||||
                Rml::Element *thumbnail_el = add_div_with_class(doc, thumbnail_container_el, cls_thumbnail);
 | 
			
		||||
            } // thumbnail_container_el
 | 
			
		||||
 | 
			
		||||
            Rml::Element *header_details_el = add_div_with_class(doc, header_el, cls_header_details);
 | 
			
		||||
            {
 | 
			
		||||
                title_el = add_div_with_class(doc, header_details_el, cls_title);
 | 
			
		||||
                version_el = add_div_with_class(doc, header_details_el, cls_version);
 | 
			
		||||
            } // header_details_el
 | 
			
		||||
        }
 | 
			
		||||
        Rml::Element* body_el = add_div_with_class(doc, this, cls_body);
 | 
			
		||||
        {
 | 
			
		||||
            description_el = add_div_with_class(doc, body_el, cls_description);
 | 
			
		||||
            authors_el = add_div_with_class(doc, body_el, cls_authors);
 | 
			
		||||
        } // body_el
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ElementModDetailsPanel::~ElementModDetailsPanel()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ElementModDetailsPanel::SetModDetails(const recomp::mods::ModDetails& details) {
 | 
			
		||||
    cur_details = details;
 | 
			
		||||
 | 
			
		||||
    title_el->SetInnerRML(cur_details.mod_id);
 | 
			
		||||
    version_el->SetInnerRML(cur_details.version.to_string());
 | 
			
		||||
 | 
			
		||||
    std::string authors_str = "<i>Authors</i>:";
 | 
			
		||||
    bool first = true;
 | 
			
		||||
    for (const std::string& author : details.authors) {
 | 
			
		||||
        authors_str += (first ? " " : ", ") + author;
 | 
			
		||||
        first = false;
 | 
			
		||||
    }
 | 
			
		||||
    authors_el->SetInnerRML(authors_str);
 | 
			
		||||
    description_el->SetInnerRML("Placeholder description. Some long text to make sure that wrapping is working correctly. Yet more text and so on.");
 | 
			
		||||
 | 
			
		||||
    DirtyLayout();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace Rml
 | 
			
		||||
							
								
								
									
										24
									
								
								src/ui/elements/ElementModDetailsPanel.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/ui/elements/ElementModDetailsPanel.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,24 @@
 | 
			
		|||
#ifndef RECOMPUI_ELEMENT_MOD_DETAILS_PANEL_H
 | 
			
		||||
#define RECOMPUI_ELEMENT_MOD_DETAILS_PANEL_H
 | 
			
		||||
 | 
			
		||||
#include "common.h"
 | 
			
		||||
#include "librecomp/mods.hpp"
 | 
			
		||||
 | 
			
		||||
namespace recompui {
 | 
			
		||||
 | 
			
		||||
class ElementModDetailsPanel : public Rml::Element {
 | 
			
		||||
public:
 | 
			
		||||
	ElementModDetailsPanel(const Rml::String& tag);
 | 
			
		||||
	virtual ~ElementModDetailsPanel();
 | 
			
		||||
    void SetModDetails(const recomp::mods::ModDetails& details);
 | 
			
		||||
private:
 | 
			
		||||
    recomp::mods::ModDetails cur_details;
 | 
			
		||||
    Rml::Element* thumbnail_el;
 | 
			
		||||
    Rml::Element* title_el;
 | 
			
		||||
    Rml::Element* authors_el;
 | 
			
		||||
    Rml::Element* version_el;
 | 
			
		||||
    Rml::Element* description_el;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // namespace recompui
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -1,65 +1,160 @@
 | 
			
		|||
#include "ElementModMenu.h"
 | 
			
		||||
#include "ElementModDetailsPanel.h"
 | 
			
		||||
#include "presets.h"
 | 
			
		||||
#include "librecomp/mods.hpp"
 | 
			
		||||
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
#define MOD_MENU_BEM "mod-menu"
 | 
			
		||||
 | 
			
		||||
namespace recompui {
 | 
			
		||||
 | 
			
		||||
static const BEM mod_menu_bem("mod-menu");
 | 
			
		||||
static const std::string cls_base = BLOCK(MOD_MENU_BEM);
 | 
			
		||||
static const std::string cls_modal_wrapper = EL(MOD_MENU_BEM, "modal-wrapper");
 | 
			
		||||
static const std::string cls_modal_header = EL(MOD_MENU_BEM, "modal-header");
 | 
			
		||||
static const std::string cls_modal_body = EL(MOD_MENU_BEM, "modal-body");
 | 
			
		||||
static const std::string cls_list = EL(MOD_MENU_BEM, "list");
 | 
			
		||||
static const std::string cls_list_scroll = EL(MOD_MENU_BEM, "list-scroll");
 | 
			
		||||
static const std::string cls_list_entry = EL(MOD_MENU_BEM, "list-entry");
 | 
			
		||||
static const std::string cls_list_entry_thumbnail = EL(MOD_MENU_BEM, "list-entry-thumbnail");
 | 
			
		||||
static const std::string cls_list_entry_body = EL(MOD_MENU_BEM, "list-entry-body");
 | 
			
		||||
static const std::string cls_list_entry_name = EL(MOD_MENU_BEM, "list-entry-name");
 | 
			
		||||
static const std::string cls_list_entry_description = EL(MOD_MENU_BEM, "list-entry-description");
 | 
			
		||||
 | 
			
		||||
static const std::string cls_base = mod_menu_bem.get_block(); 
 | 
			
		||||
static const std::string cls_modal_wrapper = mod_menu_bem.el("modal-wrapper"); 
 | 
			
		||||
static const std::string cls_modal_header = mod_menu_bem.el("modal-header"); 
 | 
			
		||||
static const std::string cls_modal_body = mod_menu_bem.el("modal-body"); 
 | 
			
		||||
static const std::string cls_list = mod_menu_bem.el("list"); 
 | 
			
		||||
static const std::string cls_list_scroll = mod_menu_bem.el("list-scroll"); 
 | 
			
		||||
static const std::string cls_details = mod_menu_bem.el("details"); 
 | 
			
		||||
void ElementModMenu::ProcessEvent(Rml::Event& event) {
 | 
			
		||||
    Rml::Element* event_element = event.GetCurrentElement();
 | 
			
		||||
    Rml::EventId event_id = event.GetId();
 | 
			
		||||
    switch (event_id) {
 | 
			
		||||
        // Click event handlers.
 | 
			
		||||
        case Rml::EventId::Click:
 | 
			
		||||
            // Refresh
 | 
			
		||||
            if (event_element == refresh_button) {
 | 
			
		||||
                RefreshMods();
 | 
			
		||||
            }
 | 
			
		||||
            // Close
 | 
			
		||||
            else if (event_element == close_button) {
 | 
			
		||||
 | 
			
		||||
static Rml::Element *add_div_with_class(Rml::ElementDocument *doc, Rml::Element *parent_el, const std::string& cls) {
 | 
			
		||||
    Rml::Element *el = parent_el->AppendChild(doc->CreateElement("div"));
 | 
			
		||||
    el->SetClass(cls.c_str(), true);
 | 
			
		||||
    return el;
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
        case Rml::EventId::Focus:
 | 
			
		||||
            {
 | 
			
		||||
                size_t mod_index;
 | 
			
		||||
                Rml::Variant *val = event_element->GetAttribute("mod_index");
 | 
			
		||||
                if (val->GetInto(mod_index) && mod_index < mod_details.size()) {
 | 
			
		||||
                    details_el->SetModDetails(mod_details[mod_index]);
 | 
			
		||||
                }
 | 
			
		||||
                if (active_list_entry_el != nullptr) {
 | 
			
		||||
                    active_list_entry_el->RemoveAttribute("is_selected");
 | 
			
		||||
                }
 | 
			
		||||
                event_element->SetAttribute("is_selected", true);
 | 
			
		||||
                active_list_entry_el = event_element;
 | 
			
		||||
            }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ElementModMenu::ElementModMenu(const Rml::String& tag) : Rml::Element(tag)
 | 
			
		||||
{
 | 
			
		||||
Rml::ElementPtr ElementModMenu::CreateModListEntry(const recomp::mods::ModDetails& details, size_t index) {
 | 
			
		||||
    Rml::ElementDocument *doc = GetOwnerDocument();
 | 
			
		||||
 | 
			
		||||
    Rml::ElementPtr mod_el = doc->CreateElement("div");
 | 
			
		||||
    mod_el->SetClass(cls_list_entry, true);
 | 
			
		||||
    mod_el->SetAttribute("mod_index", index);
 | 
			
		||||
    {
 | 
			
		||||
        Rml::Element* thumbnail_el = add_div_with_class(doc, mod_el.get(), cls_list_entry_thumbnail);
 | 
			
		||||
        Rml::Element *body_el = add_div_with_class(doc, mod_el.get(), cls_list_entry_body);
 | 
			
		||||
        {
 | 
			
		||||
            Rml::Element *name_el = add_div_with_class(doc, body_el, cls_list_entry_name);
 | 
			
		||||
            name_el->SetInnerRML(details.mod_id);
 | 
			
		||||
 | 
			
		||||
            Rml::Element *description_el = add_div_with_class(doc, body_el, cls_list_entry_description);
 | 
			
		||||
            description_el->SetInnerRML("Short description of mod here.");
 | 
			
		||||
        } // body_el
 | 
			
		||||
    } // mod_el
 | 
			
		||||
 | 
			
		||||
    return mod_el;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ElementModMenu::CreateModList() {
 | 
			
		||||
    Rml::ElementDocument *doc = GetOwnerDocument();
 | 
			
		||||
 | 
			
		||||
    // Clear the contents of the list scroll.
 | 
			
		||||
    list_el_scroll->SetInnerRML("");
 | 
			
		||||
    Rml::Element* prev_el = refresh_button;
 | 
			
		||||
    active_list_entry_el = nullptr;
 | 
			
		||||
 | 
			
		||||
    bool first = true;
 | 
			
		||||
 | 
			
		||||
    // Create the child elements for the list scroll.
 | 
			
		||||
    for (size_t mod_index = 0; mod_index < mod_details.size(); mod_index++) {
 | 
			
		||||
        const recomp::mods::ModDetails& details = mod_details[mod_index];
 | 
			
		||||
        Rml::Element *mod_el = list_el_scroll->AppendChild(CreateModListEntry(details, mod_index));
 | 
			
		||||
        mod_el->SetAttribute("mod_index", mod_index);
 | 
			
		||||
        mod_el->AddEventListener(Rml::EventId::Focus, this, false);
 | 
			
		||||
        mod_el->SetId("mod-list-entry-" + std::to_string(mod_index));
 | 
			
		||||
 | 
			
		||||
        mod_el->SetProperty("nav-up", "#" + prev_el->GetId());
 | 
			
		||||
        prev_el->SetProperty("nav-down", "#" + mod_el->GetId());
 | 
			
		||||
 | 
			
		||||
        if (first) {
 | 
			
		||||
            active_list_entry_el = mod_el;
 | 
			
		||||
        }
 | 
			
		||||
        first = false;
 | 
			
		||||
 | 
			
		||||
        prev_el = mod_el;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    active_list_entry_el->SetAttribute("is_selected", true);
 | 
			
		||||
 | 
			
		||||
    DirtyLayout();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ElementModMenu::RefreshMods() {
 | 
			
		||||
    recomp::mods::scan_mods();
 | 
			
		||||
    mod_details = recomp::mods::get_mod_details(game_mod_id);
 | 
			
		||||
 | 
			
		||||
    details_el->SetModDetails(mod_details[0]);
 | 
			
		||||
 | 
			
		||||
    CreateModList();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ElementModMenu::ElementModMenu(const Rml::String& tag) : Rml::Element(tag) {
 | 
			
		||||
    game_mod_id = "mm";
 | 
			
		||||
    SetAttribute("recomp-store-element", true);
 | 
			
		||||
    Rml::ElementDocument *doc = GetOwnerDocument();
 | 
			
		||||
    SetClass(mod_menu_bem.block, true);
 | 
			
		||||
    SetClass(cls_base, true);
 | 
			
		||||
 | 
			
		||||
    {
 | 
			
		||||
        Rml::Element *modal_wrapper_el = add_div_with_class(doc, this, cls_modal_wrapper);
 | 
			
		||||
        {
 | 
			
		||||
            Rml::Element *header_el = add_div_with_class(doc, modal_wrapper_el, cls_modal_header);
 | 
			
		||||
            {
 | 
			
		||||
                add_button(doc, header_el, "Refresh", ButtonVariant::Primary);
 | 
			
		||||
                add_icon_button(doc, header_el, "icons/X.svg", ButtonVariant::Tertiary);
 | 
			
		||||
            }
 | 
			
		||||
                refresh_button = add_button(doc, header_el, "Refresh", ButtonVariant::Primary);
 | 
			
		||||
                refresh_button->AddEventListener(Rml::EventId::Click, this, false);
 | 
			
		||||
                refresh_button->SetId("refresh-button");
 | 
			
		||||
                close_button = add_icon_button(doc, header_el, "icons/X.svg", ButtonVariant::Tertiary);
 | 
			
		||||
                close_button->AddEventListener(Rml::EventId::Click, this, false);
 | 
			
		||||
                close_button->SetId("close-button");
 | 
			
		||||
 | 
			
		||||
                refresh_button->SetProperty("nav-right", "#" + close_button->GetId());
 | 
			
		||||
                close_button->SetProperty("nav-left", "#" + refresh_button->GetId());
 | 
			
		||||
            } // header_el
 | 
			
		||||
 | 
			
		||||
            Rml::Element *body_el = add_div_with_class(doc, modal_wrapper_el, cls_modal_body);
 | 
			
		||||
            {
 | 
			
		||||
                Rml::Element *list_el = add_div_with_class(doc, body_el, cls_list);
 | 
			
		||||
                list_el = add_div_with_class(doc, body_el, cls_list);
 | 
			
		||||
                {
 | 
			
		||||
                    Rml::Element *list_el_scroll = add_div_with_class(doc, list_el, cls_list_scroll);
 | 
			
		||||
                    {
 | 
			
		||||
                        std::vector<recomp::mods::ModDetails> mods = recomp::mods::get_mod_details("mm");
 | 
			
		||||
                        for (auto& mod : mods) {
 | 
			
		||||
                            Rml::Element *mod_el = list_el_scroll->AppendChild(doc->CreateElement("div"));
 | 
			
		||||
                            mod_el->SetInnerRML(mod.mod_id);
 | 
			
		||||
                        }
 | 
			
		||||
                    } // list_el_scroll
 | 
			
		||||
                    list_el_scroll = add_div_with_class(doc, list_el, cls_list_scroll);
 | 
			
		||||
                } // list_el
 | 
			
		||||
 | 
			
		||||
                Rml::Element *details_el = add_div_with_class(doc, body_el, cls_details);
 | 
			
		||||
                details_el->SetInnerRML("two");
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
                details_el =
 | 
			
		||||
                    static_cast<ElementModDetailsPanel*>(body_el->AppendChild(doc->CreateElement("recomp-mod-details-panel")));
 | 
			
		||||
            } // body_el
 | 
			
		||||
        } // modal_wrapper_el
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    RefreshMods();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ElementModMenu::~ElementModMenu()
 | 
			
		||||
{
 | 
			
		||||
ElementModMenu::~ElementModMenu() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,13 +2,28 @@
 | 
			
		|||
#define RECOMPUI_ELEMENT_MOD_MENU_H
 | 
			
		||||
 | 
			
		||||
#include "common.h"
 | 
			
		||||
#include "librecomp/mods.hpp"
 | 
			
		||||
#include "ElementModDetailsPanel.h"
 | 
			
		||||
 | 
			
		||||
namespace recompui {
 | 
			
		||||
 | 
			
		||||
class ElementModMenu : public Rml::Element {
 | 
			
		||||
class ElementModMenu : public Rml::Element, public Rml::EventListener {
 | 
			
		||||
public:
 | 
			
		||||
	ElementModMenu(const Rml::String& tag);
 | 
			
		||||
	virtual ~ElementModMenu();
 | 
			
		||||
	void ProcessEvent(Rml::Event& event) final;
 | 
			
		||||
private:
 | 
			
		||||
	void RefreshMods();
 | 
			
		||||
	void CreateModList();
 | 
			
		||||
	Rml::ElementPtr CreateModListEntry(const recomp::mods::ModDetails& details, size_t index);
 | 
			
		||||
	Rml::Element *refresh_button;
 | 
			
		||||
	Rml::Element *close_button;
 | 
			
		||||
	Rml::Element *list_el; // The root mod list element.
 | 
			
		||||
	Rml::Element *list_el_scroll; // The scroll within the root mod list element.
 | 
			
		||||
	ElementModDetailsPanel *details_el; // The details panel.
 | 
			
		||||
	Rml::Element *active_list_entry_el = nullptr;
 | 
			
		||||
	std::vector<recomp::mods::ModDetails> mod_details{};
 | 
			
		||||
	std::string game_mod_id;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // namespace recompui
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -46,7 +46,7 @@ ElementOptionTypeColor::ElementOptionTypeColor(const Rml::String& tag) : Rml::El
 | 
			
		|||
 | 
			
		||||
            Rml::Element *hsv_wrapper = preview_wrapper->AppendChild(doc->CreateElement("div"));
 | 
			
		||||
            hsv_wrapper->SetClass(cls_color_hsv_wrapper, true);
 | 
			
		||||
            for (int i = 0; i < 3; i++) {
 | 
			
		||||
            for (size_t i = 0; i < 3; i++) {
 | 
			
		||||
                const auto &label = hsv_label[i];
 | 
			
		||||
 | 
			
		||||
                Rml::Element *range_wrapper = hsv_wrapper->AppendChild(doc->CreateElement("div"));
 | 
			
		||||
| 
						 | 
				
			
			@ -88,7 +88,7 @@ ElementOptionTypeColor::~ElementOptionTypeColor()
 | 
			
		|||
{
 | 
			
		||||
    Rml::ElementList elements;
 | 
			
		||||
    GetElementsByTagName(elements, "input");
 | 
			
		||||
    for (int i = 0; i < elements.size(); i++) {
 | 
			
		||||
    for (size_t i = 0; i < elements.size(); i++) {
 | 
			
		||||
        Rml::Element *el = elements[i];
 | 
			
		||||
        el->RemoveEventListener(Rml::EventId::Click, this, false);
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -144,7 +144,7 @@ void ElementOptionTypeColor::init_option(std::string& _config_key) {
 | 
			
		|||
 | 
			
		||||
    set_preview_block_rgb(col);
 | 
			
		||||
 | 
			
		||||
    for (int i = 0; i < 3; i++) {
 | 
			
		||||
    for (size_t i = 0; i < 3; i++) {
 | 
			
		||||
        const auto &label = hsv_label[i];
 | 
			
		||||
 | 
			
		||||
        Rml::ElementFormControlInput *range = (Rml::ElementFormControlInput *)GetElementById(range_input_id + label);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -48,7 +48,7 @@ void ElementOptionTypeDropdown::init_option(std::string& _config_key) {
 | 
			
		|||
 | 
			
		||||
    auto select_el = get_select();
 | 
			
		||||
 | 
			
		||||
    for (int i = 0; i < opt_array.size(); i++) {
 | 
			
		||||
    for (size_t i = 0; i < opt_array.size(); i++) {
 | 
			
		||||
        const auto &j_opt = opt_array[i];
 | 
			
		||||
        const std::string opt_val = j_opt.get<std::string>();
 | 
			
		||||
        const std::string opt_id = select_option_id + config_key + "--" + opt_val;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,7 +19,7 @@ ElementOptionTypeRadioTabs::~ElementOptionTypeRadioTabs()
 | 
			
		|||
{
 | 
			
		||||
    Rml::ElementList elements;
 | 
			
		||||
    GetElementsByTagName(elements, "input");
 | 
			
		||||
    for (int i = 0; i < elements.size(); i++) {
 | 
			
		||||
    for (size_t i = 0; i < elements.size(); i++) {
 | 
			
		||||
        Rml::Element *el = elements[i];
 | 
			
		||||
        el->RemoveEventListener(Rml::EventId::Click, this, false);
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -28,9 +28,9 @@ ElementOptionTypeRadioTabs::~ElementOptionTypeRadioTabs()
 | 
			
		|||
void ElementOptionTypeRadioTabs::set_cur_option(int opt) {
 | 
			
		||||
    Rml::ElementList elements;
 | 
			
		||||
    GetElementsByTagName(elements, "input");
 | 
			
		||||
    for (int i = 0; i < elements.size(); i++) {
 | 
			
		||||
    for (size_t i = 0; i < elements.size(); i++) {
 | 
			
		||||
        Rml::Element *el = elements[i];
 | 
			
		||||
        if (i == opt) {
 | 
			
		||||
        if (static_cast<int>(i) == opt) {
 | 
			
		||||
            SetAttribute("checked", true);
 | 
			
		||||
            el->SetAttribute("checked", true);
 | 
			
		||||
        } else {
 | 
			
		||||
| 
						 | 
				
			
			@ -48,7 +48,7 @@ void ElementOptionTypeRadioTabs::init_option(std::string& _config_key) {
 | 
			
		|||
    int opt = recomp::config::get_config_store_value<int>(config_key);
 | 
			
		||||
    const json& opt_array = option_json["values"];
 | 
			
		||||
 | 
			
		||||
    for (int i = 0; i < opt_array.size(); i++) {
 | 
			
		||||
    for (size_t i = 0; i < opt_array.size(); i++) {
 | 
			
		||||
        const auto &j_opt = opt_array[i];
 | 
			
		||||
        const std::string opt_val = j_opt.get<std::string>();
 | 
			
		||||
        const std::string opt_id = radio_input_id + config_key + "--" + opt_val;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,16 +1,18 @@
 | 
			
		|||
#include "presets.h"
 | 
			
		||||
 | 
			
		||||
#define BUTTON_BEM "button"
 | 
			
		||||
#define ICON_BUTTON_BEM "icon-button"
 | 
			
		||||
 | 
			
		||||
namespace recompui {
 | 
			
		||||
 | 
			
		||||
static const BEM button_bem("button");
 | 
			
		||||
Rml::Element *add_button(Rml::ElementDocument *doc, Rml::Element *parent_el, const Rml::String contents, ButtonVariant variant, bool isLarge) {
 | 
			
		||||
    Rml::Element *button = parent_el->AppendChild(doc->CreateElement("button"));
 | 
			
		||||
 | 
			
		||||
    button->SetClass(button_bem.get_block(), true);
 | 
			
		||||
    button->SetClass(BLOCK(BUTTON_BEM), true);
 | 
			
		||||
 | 
			
		||||
    button->SetClass(button_bem.mod(button_variants.at(variant)), true);
 | 
			
		||||
    button->SetClass(MOD_DYN(BUTTON_BEM, button_variants.at(variant)), true);
 | 
			
		||||
    if (isLarge) {
 | 
			
		||||
        button->SetClass(button_bem.mod("large"), true);
 | 
			
		||||
        button->SetClass(MOD(BUTTON_BEM, "large"), true);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (contents != "") {
 | 
			
		||||
| 
						 | 
				
			
			@ -20,16 +22,15 @@ Rml::Element *add_button(Rml::ElementDocument *doc, Rml::Element *parent_el, con
 | 
			
		|||
    return button;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const BEM icon_button_bem("icon-button");
 | 
			
		||||
Rml::Element *add_icon_button(Rml::ElementDocument *doc, Rml::Element *parent_el, const std::string &svg_src, ButtonVariant variant) {
 | 
			
		||||
    Rml::Element *button = parent_el->AppendChild(doc->CreateElement("button"));
 | 
			
		||||
 | 
			
		||||
    button->SetClass(icon_button_bem.get_block(), true);
 | 
			
		||||
    button->SetClass(icon_button_bem.mod(button_variants.at(variant)), true);
 | 
			
		||||
    button->SetClass(BLOCK(ICON_BUTTON_BEM), true);
 | 
			
		||||
    button->SetClass(MOD_DYN(ICON_BUTTON_BEM, button_variants.at(variant)), true);
 | 
			
		||||
 | 
			
		||||
    {
 | 
			
		||||
        Rml::Element *icon = button->AppendChild(doc->CreateElement("svg"));
 | 
			
		||||
        icon->SetClass(icon_button_bem.el("icon"), true);
 | 
			
		||||
        icon->SetClass(EL(ICON_BUTTON_BEM, "icon"), true);
 | 
			
		||||
        icon->SetAttribute("src", svg_src);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,6 +6,12 @@
 | 
			
		|||
namespace recompui {
 | 
			
		||||
    Rml::Element *add_button(Rml::ElementDocument *doc, Rml::Element *parent_el, const Rml::String contents = "", ButtonVariant variant = ButtonVariant::Primary, bool isLarge = false);
 | 
			
		||||
    Rml::Element *add_icon_button(Rml::ElementDocument *doc, Rml::Element *parent_el, const std::string &svg_src, ButtonVariant variant = ButtonVariant::Tertiary);
 | 
			
		||||
 | 
			
		||||
    inline Rml::Element *add_div_with_class(Rml::ElementDocument *doc, Rml::Element *parent_el, const std::string& cls) {
 | 
			
		||||
        Rml::Element *el = parent_el->AppendChild(doc->CreateElement("div"));
 | 
			
		||||
        el->SetClass(cls, true);
 | 
			
		||||
        return el;
 | 
			
		||||
    }
 | 
			
		||||
} // namespace recompui
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -77,7 +77,7 @@ namespace recompui {
 | 
			
		|||
			}
 | 
			
		||||
 | 
			
		||||
			// Parse each of the colour elements.
 | 
			
		||||
			for (int i = 0; i < 4; i++)
 | 
			
		||||
			for (size_t i = 0; i < 4; i++)
 | 
			
		||||
			{
 | 
			
		||||
				int tens = Rml::Math::HexToDecimal(hex_values[i][0]);
 | 
			
		||||
				int ones = Rml::Math::HexToDecimal(hex_values[i][1]);
 | 
			
		||||
| 
						 | 
				
			
			@ -115,7 +115,7 @@ namespace recompui {
 | 
			
		|||
			}
 | 
			
		||||
 | 
			
		||||
			// Parse the three RGB values.
 | 
			
		||||
			for (int i = 0; i < 3; ++i)
 | 
			
		||||
			for (size_t i = 0; i < 3; ++i)
 | 
			
		||||
			{
 | 
			
		||||
				int component;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -20,6 +20,7 @@ static RecompElementConfig custom_elements[] = {
 | 
			
		|||
    CUSTOM_ELEMENT("recomp-option-type-radio-tabs", recompui::ElementOptionTypeRadioTabs),
 | 
			
		||||
    CUSTOM_ELEMENT("recomp-option-type-range", recompui::ElementOptionTypeRange),
 | 
			
		||||
    CUSTOM_ELEMENT("recomp-mod-menu", recompui::ElementModMenu),
 | 
			
		||||
    CUSTOM_ELEMENT("recomp-mod-details-panel", recompui::ElementModDetailsPanel),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void recompui::register_custom_elements() {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,6 +15,7 @@
 | 
			
		|||
#include "elements/ElementOptionTypeTextField.h"
 | 
			
		||||
#include "elements/ElementDescription.h"
 | 
			
		||||
#include "elements/ElementModMenu.h"
 | 
			
		||||
#include "elements/ElementModDetailsPanel.h"
 | 
			
		||||
 | 
			
		||||
namespace recompui {
 | 
			
		||||
    void register_custom_elements();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -554,12 +554,10 @@ public:
 | 
			
		|||
            else {
 | 
			
		||||
                const Rml::byte *src_data = flip_y ? source + row_pitch * (source_dimensions.y - 1) : source;
 | 
			
		||||
                uint32_t src_stride = flip_y ? -row_pitch : row_pitch;
 | 
			
		||||
                size_t offset = 0;
 | 
			
		||||
 | 
			
		||||
                for (int row = 0; row < source_dimensions.y; row++) { //(offset + increment) <= image_size_bytes) {
 | 
			
		||||
                for (int row = 0; row < source_dimensions.y; row++) {
 | 
			
		||||
                    memcpy(dst_data, src_data, row_pitch);
 | 
			
		||||
                    src_data += src_stride;
 | 
			
		||||
                    offset += row_pitch;
 | 
			
		||||
                    dst_data += row_byte_width;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			@ -1161,13 +1159,9 @@ void init_hook(RT64::RenderInterface* interface, RT64::RenderDevice* device) {
 | 
			
		|||
    if (std::filesystem::exists(test_conf_path)) {
 | 
			
		||||
        const std::string s = read_file_to_string(test_conf_path); 
 | 
			
		||||
        recomp::config::register_config(read_file_to_string(test_conf_path), "cheats");
 | 
			
		||||
        printf("SUCC CONF\n");
 | 
			
		||||
 | 
			
		||||
        if (std::filesystem::exists(test_conf_trans_path)) {
 | 
			
		||||
            recomp::config::register_translation(read_file_to_string("config_example.cheats.en_us.json"), "cheats");
 | 
			
		||||
            printf("SUCC TRANSLATION\n");
 | 
			
		||||
        } else {
 | 
			
		||||
            printf("FAIL TRANSLATION");
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        printf("FAIL ALL\n");
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,31 +3,10 @@
 | 
			
		|||
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
namespace recompui {
 | 
			
		||||
    // BEM base class
 | 
			
		||||
    class BEM {
 | 
			
		||||
    public:
 | 
			
		||||
        std::string block;
 | 
			
		||||
 | 
			
		||||
        BEM(const std::string &block) : block(block) {}
 | 
			
		||||
        virtual ~BEM() = default;
 | 
			
		||||
 | 
			
		||||
        const std::string get_block() const {
 | 
			
		||||
            return block;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const std::string el(const std::string &element) const {
 | 
			
		||||
            return block + "__" + element;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const BEM bem_el(const std::string &element) const {
 | 
			
		||||
            return BEM(el(element));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const std::string mod(const std::string &modifier) const {
 | 
			
		||||
            return block + "--" + modifier;
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
} // namespace recompui
 | 
			
		||||
#define EL(bem, element) bem "__" element
 | 
			
		||||
#define EL_DYN(bem, element) bem "__" + element
 | 
			
		||||
#define MOD(bem, modifier) bem "--" modifier
 | 
			
		||||
#define MOD_DYN(bem, modifier) bem "--" + modifier
 | 
			
		||||
#define BLOCK(bem) bem
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue