Made Dialog reusable.

This commit is contained in:
Daan Vanden Bosch 2020-01-07 17:40:01 +01:00
parent 10d6eb68d9
commit b93b22a223
4 changed files with 62 additions and 39 deletions

View File

@ -1,4 +1,5 @@
.core_ResultPopup {
.core_Dialog {
z-index: 20;
display: flex;
flex-direction: column;
outline: none;
@ -9,34 +10,43 @@
box-shadow: black 0 0 10px -2px;
}
.core_ResultPopup:focus-within {
.core_Dialog:focus-within {
border: var(--border-focus);
}
.core_ResultPopup h1 {
.core_Dialog h1 {
font-size: 20px;
margin: 0 0 10px 0;
padding-bottom: 4px;
border-bottom: var(--border);
}
.core_ResultPopup_description {
.core_Dialog_description {
user-select: text;
cursor: text;
}
.core_ResultPopup_body {
.core_Dialog_body {
user-select: text;
overflow: auto;
margin: 4px 0;
}
.core_ResultPopup_body ul {
cursor: text;
}
.core_ResultPopup_footer {
.core_Dialog_footer {
display: flex;
flex-direction: row;
justify-content: flex-end;
}
.core_Dialog_modal_overlay {
outline: none;
z-index: 10;
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
background-color: black;
opacity: 50%;
backdrop-filter: blur(5px);
}

View File

@ -1,55 +1,62 @@
import { ResizableWidget } from "./ResizableWidget";
import { Widget } from "./Widget";
import { div, h1, li, section, ul } from "./dom";
import { Problem, Result } from "../Result";
import { Result } from "../Result";
import { Button } from "./Button";
import "./ResultPopup.css";
import "./Dialog.css";
const POPUP_WIDTH = 500;
const POPUP_HEIGHT = 500;
const DIALOG_WIDTH = 500;
const DIALOG_MAX_HEIGHT = 500;
export class ResultPopup extends ResizableWidget {
export class Dialog extends ResizableWidget {
private x = 0;
private y = 0;
private prev_mouse_x = 0;
private prev_mouse_y = 0;
private readonly overlay_element: HTMLElement;
readonly element: HTMLElement;
readonly children: readonly Widget[] = [];
readonly dismiss_button = this.disposable(new Button({ text: "Dismiss" }));
constructor(title: string, description: string, problems: readonly Problem[] = []) {
constructor(title: string, description: string, content: Node | string) {
super();
let header_element: HTMLElement;
this.element = section(
{ className: "core_ResultPopup", tabIndex: 0 },
{ className: "core_Dialog", tabIndex: 0 },
(header_element = h1(title)),
div({ className: "core_ResultPopup_description" }, description),
div(
{ className: "core_ResultPopup_body" },
ul(...problems.map(problem => li(problem.ui_message))),
),
div({ className: "core_ResultPopup_footer" }, this.dismiss_button.element),
div({ className: "core_Dialog_description" }, description),
div({ className: "core_Dialog_body" }, content),
div({ className: "core_Dialog_footer" }, this.dismiss_button.element),
);
this.element.style.width = `${POPUP_WIDTH}px`;
this.element.style.maxHeight = `${POPUP_HEIGHT}px`;
this.element.style.width = `${DIALOG_WIDTH}px`;
this.element.style.maxHeight = `${DIALOG_MAX_HEIGHT}px`;
this.set_position(
(window.innerWidth - POPUP_WIDTH) / 2,
(window.innerHeight - POPUP_HEIGHT) / 2,
(window.innerWidth - DIALOG_WIDTH) / 2,
(window.innerHeight - DIALOG_MAX_HEIGHT) / 2,
);
this.element.addEventListener("keydown", this.keydown);
header_element.addEventListener("mousedown", this.mousedown);
this.overlay_element = div({ className: "core_Dialog_modal_overlay", tabIndex: -1 });
this.overlay_element.addEventListener("focus", () => this.element.focus());
document.body.append(this.overlay_element);
this.disposables(this.dismiss_button.onclick.observe(() => this.dispose()));
this.finalize_construction();
}
dispose(): void {
super.dispose();
this.overlay_element.remove();
}
set_position(x: number, y: number): void {
this.x = x;
this.y = y;
@ -87,27 +94,33 @@ export class ResultPopup extends ResizableWidget {
}
/**
* Shows a popup if `result` failed or succeeded with problems.
* Shows a dialog window if `result` failed or succeeded with problems.
*
* @param result
* @param problems_message - Message to show if problems occurred when result is successful.
* @param error_message - Message to show if result failed.
*/
export function show_result_popup(
export function show_result_dialog(
result: Result<unknown>,
problems_message: string,
error_message: string,
): void {
let popup: ResultPopup | undefined;
let dialog: Dialog | undefined;
if (!result.success) {
popup = new ResultPopup("Error", error_message, result.problems);
dialog = new Dialog("Error", error_message, create_result_body(result));
} else if (result.problems.length) {
popup = new ResultPopup("Problems", problems_message, result.problems);
dialog = new Dialog("Problems", problems_message, create_result_body(result));
}
if (popup) {
document.body.append(popup.element);
popup.focus();
if (dialog) {
document.body.append(dialog.element);
dialog.focus();
}
}
function create_result_body(result: Result<unknown>): HTMLElement {
const body = ul(...result.problems.map(problem => li(problem.ui_message)));
body.style.cursor = "text";
return body;
}

View File

@ -11,8 +11,8 @@ import { list_property } from "../../core/observable";
import { ListProperty } from "../../core/observable/property/list/ListProperty";
import { prs_decompress } from "../../core/data_formats/compression/prs/decompress";
import { failure, Result, result_builder } from "../../core/Result";
import { show_result_popup } from "../../core/gui/ResultPopup";
import { Severity } from "../../core/Severity";
import { show_result_dialog } from "../../core/gui/Dialog";
const logger = LogManager.get("viewer/controllers/TextureController");
@ -75,7 +75,7 @@ export class TextureController extends Controller {
result = failure();
}
show_result_popup(
show_result_dialog(
result,
`Encountered some problems while opening "${file.name}".`,
`Couldn't open "${file.name}".`,

View File

@ -11,8 +11,8 @@ import { parse_afs } from "../../../core/data_formats/parsing/afs";
import { LogManager } from "../../../core/Logger";
import { prs_decompress } from "../../../core/data_formats/compression/prs/decompress";
import { failure, Result, result_builder, success } from "../../../core/Result";
import { show_result_popup } from "../../../core/gui/ResultPopup";
import { Severity } from "../../../core/Severity";
import { show_result_dialog } from "../../../core/gui/Dialog";
const logger = LogManager.get("viewer/controllers/model/ModelToolBarController");
@ -136,7 +136,7 @@ export class ModelToolBarController extends Controller {
result = failure();
}
show_result_popup(
show_result_dialog(
result,
`Encountered some problems while opening "${file.name}".`,
`Couldn't open "${file.name}".`,