226 lines
7.0 KiB
JavaScript
226 lines
7.0 KiB
JavaScript
const { HandlebarsApplicationMixin } = foundry.applications.api;
|
|
|
|
export default class DonjonEtCieActorSheet extends HandlebarsApplicationMixin(foundry.applications.sheets.ActorSheetV2) {
|
|
static DEFAULT_OPTIONS = {
|
|
classes: ["fvtt-donjon-et-cie", "sheet", "actor"],
|
|
position: { width: 920, height: 820 },
|
|
form: {
|
|
submitOnChange: true,
|
|
closeOnSubmit: false
|
|
},
|
|
window: {
|
|
resizable: true
|
|
},
|
|
dragDrop: [{ dragSelector: ".item-list .item", dropSelector: ".item-dropzone" }],
|
|
actions: {
|
|
editImage: DonjonEtCieActorSheet.#onEditImage,
|
|
setTab: DonjonEtCieActorSheet.#onSetTab,
|
|
createItem: DonjonEtCieActorSheet.#onCreateItem,
|
|
editItem: DonjonEtCieActorSheet.#onEditItem,
|
|
deleteItem: DonjonEtCieActorSheet.#onDeleteItem,
|
|
rollHitDice: DonjonEtCieActorSheet.#onRollHitDice,
|
|
rollInitiative: DonjonEtCieActorSheet.#onRollInitiative,
|
|
rollCharacteristic: DonjonEtCieActorSheet.#onRollCharacteristic,
|
|
rollWeapon: DonjonEtCieActorSheet.#onRollWeapon,
|
|
rollDamage: DonjonEtCieActorSheet.#onRollDamage,
|
|
rollSpell: DonjonEtCieActorSheet.#onRollSpell,
|
|
rollUsage: DonjonEtCieActorSheet.#onRollUsage,
|
|
useFavorService: DonjonEtCieActorSheet.#onUseFavorService,
|
|
postItem: DonjonEtCieActorSheet.#onPostItem,
|
|
adjustCounter: DonjonEtCieActorSheet.#onAdjustCounter
|
|
}
|
|
};
|
|
|
|
async _prepareContext() {
|
|
const actor = this.document;
|
|
return {
|
|
actor,
|
|
system: actor.system,
|
|
source: actor.toObject(),
|
|
config: game.system.donjonEtCie.config,
|
|
characteristics: actor.getCharacteristicEntries(),
|
|
sections: actor.getSectionData(),
|
|
fields: actor.schema.fields,
|
|
systemFields: actor.system.schema.fields,
|
|
activeTab: this._activeTab ?? "combat"
|
|
};
|
|
}
|
|
|
|
_onRender(context, options) {
|
|
super._onRender(context, options);
|
|
this.#fixWindowShell();
|
|
this._applyActiveTab();
|
|
}
|
|
|
|
#fixWindowShell() {
|
|
const app = this.element?.matches?.(".application") ? this.element : this.element?.closest(".application");
|
|
const content = app?.querySelector(":scope > .window-content") ?? app?.querySelector(".window-content");
|
|
const header = app?.querySelector(".window-header");
|
|
|
|
if (app) {
|
|
app.style.display = "flex";
|
|
app.style.flexDirection = "column";
|
|
app.style.paddingTop = "0";
|
|
app.style.overflow = "hidden";
|
|
}
|
|
|
|
if (header) {
|
|
header.style.width = "100%";
|
|
header.style.flex = "0 0 auto";
|
|
header.style.position = "relative";
|
|
header.style.zIndex = "3";
|
|
}
|
|
|
|
if (content) {
|
|
content.style.width = "100%";
|
|
content.style.flex = "1 1 auto";
|
|
content.style.minHeight = "0";
|
|
content.style.overflowY = "auto";
|
|
content.style.overflowX = "hidden";
|
|
}
|
|
}
|
|
|
|
_canDragStart() {
|
|
return this.isEditable;
|
|
}
|
|
|
|
_canDragDrop() {
|
|
return this.isEditable;
|
|
}
|
|
|
|
_onDragStart(event) {
|
|
const itemElement = event.currentTarget.closest(".item");
|
|
if (!itemElement) return;
|
|
|
|
const itemId = itemElement.dataset.itemId;
|
|
const item = this.document.items.get(itemId);
|
|
if (!item) return;
|
|
|
|
event.dataTransfer.setData("text/plain", JSON.stringify({ type: "Item", uuid: item.uuid }));
|
|
}
|
|
|
|
_onDragOver(event) {
|
|
const dropTarget = event.target.closest(".item-section");
|
|
this.#setDropTarget(dropTarget);
|
|
}
|
|
|
|
async _onDrop(event) {
|
|
this.#setDropTarget(null);
|
|
return super._onDrop(event);
|
|
}
|
|
|
|
#setDropTarget(target) {
|
|
this.element.querySelectorAll(".item-section.is-dragover").forEach((section) => section.classList.remove("is-dragover"));
|
|
if (target instanceof HTMLElement) {
|
|
target.classList.add("is-dragover");
|
|
}
|
|
}
|
|
|
|
_applyActiveTab() {
|
|
const activeTab = this._activeTab ?? "combat";
|
|
this.element.querySelectorAll("[data-tab-button]").forEach((button) => {
|
|
const isActive = button.dataset.tab === activeTab;
|
|
button.classList.toggle("active", isActive);
|
|
button.setAttribute("aria-pressed", isActive ? "true" : "false");
|
|
});
|
|
|
|
this.element.querySelectorAll("[data-tab-panel]").forEach((panel) => {
|
|
const isActive = panel.dataset.tabPanel === activeTab;
|
|
panel.classList.toggle("active", isActive);
|
|
panel.toggleAttribute("hidden", !isActive);
|
|
});
|
|
}
|
|
|
|
static async #onEditImage(event) {
|
|
event.preventDefault();
|
|
const picker = new FilePicker({
|
|
type: "image",
|
|
current: this.document.img,
|
|
callback: (path) => this.document.update({ img: path })
|
|
});
|
|
return picker.browse();
|
|
}
|
|
|
|
static async #onCreateItem(event, target) {
|
|
event.preventDefault();
|
|
const type = target.dataset.type;
|
|
if (!type) return;
|
|
return this.document.createEmbeddedDocuments("Item", [{ name: `Nouveau ${type}`, type }], { renderSheet: true });
|
|
}
|
|
|
|
static async #onSetTab(event, target) {
|
|
event.preventDefault();
|
|
const tab = target.dataset.tab;
|
|
if (!tab) return;
|
|
this._activeTab = tab;
|
|
this._applyActiveTab();
|
|
}
|
|
|
|
static async #onEditItem(event, target) {
|
|
event.preventDefault();
|
|
const item = this.document.items.get(target.closest("[data-item-id]")?.dataset.itemId);
|
|
return item?.sheet.render(true);
|
|
}
|
|
|
|
static async #onDeleteItem(event, target) {
|
|
event.preventDefault();
|
|
const itemId = target.closest("[data-item-id]")?.dataset.itemId;
|
|
if (!itemId) return;
|
|
return this.document.deleteEmbeddedDocuments("Item", [itemId]);
|
|
}
|
|
|
|
static async #onRollCharacteristic(event, target) {
|
|
event.preventDefault();
|
|
return this.document.rollCharacteristic(target.dataset.characteristic);
|
|
}
|
|
|
|
static async #onRollInitiative(event) {
|
|
event.preventDefault();
|
|
return this.document.rollInitiative();
|
|
}
|
|
|
|
static async #onRollHitDice(event) {
|
|
event.preventDefault();
|
|
return this.document.rollHitDice();
|
|
}
|
|
|
|
static async #onRollWeapon(event, target) {
|
|
event.preventDefault();
|
|
return this.document.rollWeapon(target.closest("[data-item-id]")?.dataset.itemId);
|
|
}
|
|
|
|
static async #onRollDamage(event, target) {
|
|
event.preventDefault();
|
|
return this.document.rollDamage(target.closest("[data-item-id]")?.dataset.itemId);
|
|
}
|
|
|
|
static async #onRollSpell(event, target) {
|
|
event.preventDefault();
|
|
return this.document.rollSpell(target.closest("[data-item-id]")?.dataset.itemId);
|
|
}
|
|
|
|
static async #onRollUsage(event, target) {
|
|
event.preventDefault();
|
|
return this.document.rollUsage(target.closest("[data-item-id]")?.dataset.itemId);
|
|
}
|
|
|
|
static async #onUseFavorService(event, target) {
|
|
event.preventDefault();
|
|
return this.document.useFavorService(target.dataset.department);
|
|
}
|
|
|
|
static async #onPostItem(event, target) {
|
|
event.preventDefault();
|
|
const item = this.document.items.get(target.closest("[data-item-id]")?.dataset.itemId);
|
|
return item?.postToChat();
|
|
}
|
|
|
|
static async #onAdjustCounter(event, target) {
|
|
event.preventDefault();
|
|
const path = target.dataset.path;
|
|
const delta = Number(target.dataset.delta ?? 0);
|
|
if (!path || Number.isNaN(delta)) return;
|
|
return this.document.adjustNumericField(path, delta);
|
|
}
|
|
}
|