/* eslint-disable max-classes-per-file */ import DG, { BASE_TEMPLATE_PATH } from "./config.js"; import DGActorSheet from "./sheets/base-actor-sheet.js"; import DGItemSheet from "./sheets/base-item-sheet.js"; const { ApplicationV2, HandlebarsApplicationMixin } = foundry.applications.api; /** * Base class for all setting forms. * * Note: This class is abstract and should not be instantiated directly. * * @extends {ApplicationV2} */ const SettingForm = class extends HandlebarsApplicationMixin(ApplicationV2) { /** @type {"automation"|"handler"|null} */ static _namespace = null; /** * The namespace for the settings defined by this class. This is necessary * to register the settings with the game. * * @returns {string} */ static get namespace() { return this._namespace; } /** * A getter that returns an object with all the settings defined by the subclass. * Used to register settings with the game. * * @abstract * @returns {object} An object with all the settings defined by the subclass * @throws Will throw an error if this method is not defined by a subclass. */ static get settings() { throw new Error("This static getter must be defined by a subclass"); } /** * Registers the settings for each defined SettingForm subclass. * @returns {void} */ static register() { const { settings } = this; for (const [settingID, setting] of Object.entries(settings)) { game.settings.register(DG.ID, settingID, { scope: "world", config: false, name: game.i18n.localize(`DG.Settings.${settingID}.name`), hint: game.i18n.localize(`DG.Settings.${settingID}.hint`), ...setting, }); } } /** @override */ static DEFAULT_OPTIONS = { tag: "form", id: "dg-settings", classes: [DG.ID, "settings-menu"], window: { contentClasses: ["standard-form"], resizable: true }, position: { width: 500, height: "auto" }, actions: {}, form: { handler: this.onSubmit, submitOnChange: false, closeOnSubmit: true, }, }; /** @override */ static PARTS = { footer: { template: `${BASE_TEMPLATE_PATH}/save.hbs` }, }; /** @override */ static async onSubmit(event, form, formData) { event.preventDefault(); // Get form data into a standard object. const data = foundry.utils.expandObject(formData.object); const settingsPromises = []; // Set each setting with the new value, if any. for (const [key, value] of Object.entries(data[DG.ID])) { settingsPromises.push(game.settings.set(DG.ID, key, value)); } // Once all promises resolve, show a notification. Promise.allSettled(settingsPromises).then((values) => { ui.notifications.info(game.i18n.localize("DG.Settings.Saved")); }); } /** @override */ _onFirstRender(options) { super._onFirstRender(options); this._attachFormGroupHTML(); } /** * Populate the window content section with form groups representing the settings. * @returns {void} */ _attachFormGroupHTML() { const windowContent = this.element.querySelector("section.window-content"); const formGroupString = this._prepareFormGroupElements() .map((formGroup) => formGroup.outerHTML) .join(""); // Create a div element whose inner html is the form groups (as a string of HTML), // and prepend it to the window content. const div = document.createElement("div"); div.classList.add("flexcol"); div.innerHTML = formGroupString; windowContent.prepend(div); } /** * Generates an array of form groups, each corresponding to a setting in a menu. * @returns {HTMLDivElement[]} An array of form group HTML elements. */ _prepareFormGroupElements() { // Get Foundry's built-in input creation functions. const { createCheckboxInput, createNumberInput, createSelectInput, createTextInput, createFormGroup, } = foundry.applications.fields; const formGroups = []; // Iterate over each setting and create the appropriate input element. const { settings } = this.constructor; for (const settingID of Object.keys(settings)) { // The setting config object, not the value of the setting itself. const settingConfig = game.settings.settings.get(`${DG.ID}.${settingID}`); // Default input settings. const inputConfig = { name: `${DG.ID}.${settingID}`, value: game.settings.get(DG.ID, settingID), // The value that the setting is currently set to. label: settingConfig.name, }; // Use Foundry's built-in /