phantasmal-world/src/ui/quest_editor/QuestEditorComponent.tsx

170 lines
5.6 KiB
TypeScript
Raw Normal View History

import { Button, Form, Icon, Input, Modal, Select, Upload } from "antd";
import { UploadChangeParam } from "antd/lib/upload";
import { UploadFile } from "antd/lib/upload/interface";
import { observer } from "mobx-react";
2019-07-03 02:56:33 +08:00
import React, { ChangeEvent, ReactNode, Component } from "react";
import { quest_editor_store } from "../../stores/QuestEditorStore";
import { EntityInfoComponent } from "./EntityInfoComponent";
import "./QuestEditorComponent.css";
import { QuestInfoComponent } from "./QuestInfoComponent";
2019-07-11 23:30:23 +08:00
import { RendererComponent } from "../RendererComponent";
import { get_quest_renderer } from "../../rendering/QuestRenderer";
@observer
2019-07-03 02:56:33 +08:00
export class QuestEditorComponent extends Component<
{},
{
filename?: string;
save_dialog_open: boolean;
save_dialog_filename: string;
}
> {
state = {
save_dialog_open: false,
save_dialog_filename: "Untitled",
};
2019-07-03 02:56:33 +08:00
render(): ReactNode {
const quest = quest_editor_store.current_quest;
return (
<div className="qe-QuestEditorComponent">
<Toolbar onSaveAsClicked={this.save_as_clicked} />
<div className="qe-QuestEditorComponent-main">
<QuestInfoComponent quest={quest} />
2019-07-11 23:30:23 +08:00
<RendererComponent renderer={get_quest_renderer()} />
<EntityInfoComponent entity={quest_editor_store.selected_entity} />
</div>
<SaveAsForm
is_open={this.state.save_dialog_open}
filename={this.state.save_dialog_filename}
on_filename_change={this.save_dialog_filename_changed}
on_ok={this.save_dialog_affirmed}
on_cancel={this.save_dialog_cancelled}
/>
</div>
);
}
private save_as_clicked = (filename?: string) => {
2019-06-01 23:57:27 +08:00
const name = filename
? filename.endsWith(".qst")
? filename.slice(0, -4)
: filename
: this.state.save_dialog_filename;
this.setState({
save_dialog_open: true,
save_dialog_filename: name,
});
};
private save_dialog_filename_changed = (filename: string) => {
this.setState({ save_dialog_filename: filename });
};
private save_dialog_affirmed = () => {
quest_editor_store.save_current_quest_to_file(this.state.save_dialog_filename);
this.setState({ save_dialog_open: false });
};
private save_dialog_cancelled = () => {
this.setState({ save_dialog_open: false });
};
}
@observer
2019-07-03 02:56:33 +08:00
class Toolbar extends Component<{ onSaveAsClicked: (filename?: string) => void }> {
state = {
filename: undefined,
};
2019-07-03 02:56:33 +08:00
render(): ReactNode {
const quest = quest_editor_store.current_quest;
2019-06-26 23:47:53 +08:00
const areas = quest && Array.from(quest.area_variants).map(a => a.area);
const area = quest_editor_store.current_area;
const area_id = area && area.id;
return (
<div className="qe-QuestEditorComponent-toolbar">
<Upload
accept=".qst"
showUploadList={false}
onChange={this.set_filename}
2019-06-22 02:06:55 +08:00
// Make sure it doesn't do a POST:
customRequest={() => false}
>
<Button icon="file">{this.state.filename || "Open file..."}</Button>
</Upload>
{areas && (
<Select
onChange={quest_editor_store.set_current_area_id}
value={area_id}
style={{ width: 200 }}
>
{areas.map(area => (
<Select.Option key={area.id} value={area.id}>
{area.name}
</Select.Option>
))}
</Select>
)}
{quest && (
<Button icon="save" onClick={this.save_as_clicked}>
Save as...
</Button>
)}
</div>
);
}
private set_filename = (info: UploadChangeParam<UploadFile>) => {
if (info.file.originFileObj) {
this.setState({ filename: info.file.name });
quest_editor_store.load_file(info.file.originFileObj as File);
}
};
private save_as_clicked = () => {
this.props.onSaveAsClicked(this.state.filename);
};
}
class SaveAsForm extends React.Component<{
is_open: boolean;
filename: string;
on_filename_change: (name: string) => void;
on_ok: () => void;
on_cancel: () => void;
}> {
2019-07-03 02:56:33 +08:00
render(): ReactNode {
return (
<Modal
title={
<>
<Icon type="save" /> Save as...
</>
}
visible={this.props.is_open}
onOk={this.props.on_ok}
onCancel={this.props.on_cancel}
>
<Form layout="vertical">
<Form.Item label="Name">
<Input
autoFocus={true}
maxLength={12}
value={this.props.filename}
onChange={this.name_changed}
/>
</Form.Item>
</Form>
</Modal>
);
}
private name_changed = (e: ChangeEvent<HTMLInputElement>) => {
this.props.on_filename_change(e.currentTarget.value);
};
}