交互插件结构、名称调整
属性页面基础布局 绘制store创建
This commit is contained in:
parent
8b86abf994
commit
addb813a2b
15
src/components/draw-app/DrawProperties.vue
Normal file
15
src/components/draw-app/DrawProperties.vue
Normal file
@ -0,0 +1,15 @@
|
||||
<template>
|
||||
<div v-if="drawStore.drawMode" class="q-pa-md">图形模板</div>
|
||||
<div v-else class="q-pa-md"></div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useDrawStore } from 'src/stores/draw-store';
|
||||
import { onMounted, ref } from 'vue';
|
||||
|
||||
const drawStore = useDrawStore();
|
||||
|
||||
onMounted(() => {
|
||||
console.log('绘制属性组件mounted');
|
||||
});
|
||||
</script>
|
65
src/components/draw-app/properties/LinkProperty.vue
Normal file
65
src/components/draw-app/properties/LinkProperty.vue
Normal file
@ -0,0 +1,65 @@
|
||||
<template>
|
||||
<q-form @submit="onSubmit" @reset="onReset" class="q-gutter-md">
|
||||
<q-input
|
||||
filled
|
||||
v-model="name"
|
||||
label="Your name *"
|
||||
hint="Name and surname"
|
||||
lazy-rules
|
||||
:rules="[(val) => (val && val.length > 0) || 'Please type something']"
|
||||
/>
|
||||
|
||||
<q-input
|
||||
filled
|
||||
type="number"
|
||||
v-model="age"
|
||||
label="Your age *"
|
||||
lazy-rules
|
||||
:rules="[
|
||||
(val) => (val !== null && val !== '') || 'Please type your age',
|
||||
(val) => (val > 0 && val < 100) || 'Please type a real age',
|
||||
]"
|
||||
/>
|
||||
|
||||
<q-toggle v-model="accept" label="I accept the license and terms" />
|
||||
|
||||
<div>
|
||||
<q-btn label="Submit" type="submit" color="primary" />
|
||||
<q-btn label="Reset" type="reset" color="primary" flat class="q-ml-sm" />
|
||||
</div>
|
||||
</q-form>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useQuasar } from 'quasar';
|
||||
import { ref } from 'vue';
|
||||
const $q = useQuasar();
|
||||
|
||||
const name = ref(null);
|
||||
const age = ref(null);
|
||||
const accept = ref(false);
|
||||
|
||||
function onSubmit() {
|
||||
if (accept.value !== true) {
|
||||
$q.notify({
|
||||
color: 'red-5',
|
||||
textColor: 'white',
|
||||
icon: 'warning',
|
||||
message: 'You need to accept the license and terms first',
|
||||
});
|
||||
} else {
|
||||
$q.notify({
|
||||
color: 'green-4',
|
||||
textColor: 'white',
|
||||
icon: 'cloud_done',
|
||||
message: 'Submitted',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function onReset() {
|
||||
name.value = null;
|
||||
age.value = null;
|
||||
accept.value = false;
|
||||
}
|
||||
</script>
|
65
src/components/draw-app/templates/LinkTemplate.vue
Normal file
65
src/components/draw-app/templates/LinkTemplate.vue
Normal file
@ -0,0 +1,65 @@
|
||||
<template>
|
||||
<q-form @submit="onSubmit" @reset="onReset" class="q-gutter-md">
|
||||
<q-input
|
||||
filled
|
||||
v-model="name"
|
||||
label="Your name *"
|
||||
hint="Name and surname"
|
||||
lazy-rules
|
||||
:rules="[(val) => (val && val.length > 0) || 'Please type something']"
|
||||
/>
|
||||
|
||||
<q-input
|
||||
filled
|
||||
type="number"
|
||||
v-model="age"
|
||||
label="Your age *"
|
||||
lazy-rules
|
||||
:rules="[
|
||||
(val) => (val !== null && val !== '') || 'Please type your age',
|
||||
(val) => (val > 0 && val < 100) || 'Please type a real age',
|
||||
]"
|
||||
/>
|
||||
|
||||
<q-toggle v-model="accept" label="I accept the license and terms" />
|
||||
|
||||
<div>
|
||||
<q-btn label="Submit" type="submit" color="primary" />
|
||||
<q-btn label="Reset" type="reset" color="primary" flat class="q-ml-sm" />
|
||||
</div>
|
||||
</q-form>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useQuasar } from 'quasar';
|
||||
import { ref } from 'vue';
|
||||
const $q = useQuasar();
|
||||
|
||||
const name = ref(null);
|
||||
const age = ref(null);
|
||||
const accept = ref(false);
|
||||
|
||||
function onSubmit() {
|
||||
if (accept.value !== true) {
|
||||
$q.notify({
|
||||
color: 'red-5',
|
||||
textColor: 'white',
|
||||
icon: 'warning',
|
||||
message: 'You need to accept the license and terms first',
|
||||
});
|
||||
} else {
|
||||
$q.notify({
|
||||
color: 'green-4',
|
||||
textColor: 'white',
|
||||
icon: 'cloud_done',
|
||||
message: 'Submitted',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function onReset() {
|
||||
name.value = null;
|
||||
age.value = null;
|
||||
accept.value = false;
|
||||
}
|
||||
</script>
|
@ -21,7 +21,7 @@ export interface IProtoGraphicData extends pb_1.Message {
|
||||
code: string;
|
||||
}
|
||||
|
||||
export abstract class BaseGraphicData implements GraphicData {
|
||||
export abstract class GraphicDataBase implements GraphicData {
|
||||
_data: IProtoGraphicData;
|
||||
constructor(data: IProtoGraphicData) {
|
||||
this._data = data;
|
||||
@ -92,10 +92,10 @@ export abstract class BaseGraphicData implements GraphicData {
|
||||
clone(): GraphicData {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
copyFrom(gd: BaseGraphicData): void {
|
||||
copyFrom(gd: GraphicDataBase): void {
|
||||
pb_1.Message.copyInto(gd._data, this._data);
|
||||
}
|
||||
eq(other: BaseGraphicData): boolean {
|
||||
eq(other: GraphicDataBase): boolean {
|
||||
return pb_1.Message.equals(this._data, other._data);
|
||||
}
|
||||
}
|
@ -1,16 +1,16 @@
|
||||
import * as pb_1 from 'google-protobuf';
|
||||
import { IIscsFanData } from 'src/graphics/iscs-fan/IscsFan';
|
||||
import { graphicData } from '../protos/draw_data_storage';
|
||||
import { BaseGraphicData } from './BaseGraphicData';
|
||||
import { GraphicDataBase } from './GraphicDataBase';
|
||||
|
||||
export class IscsFanData extends BaseGraphicData implements IIscsFanData {
|
||||
export class IscsFanData extends GraphicDataBase implements IIscsFanData {
|
||||
constructor(data?: graphicData.IscsFan) {
|
||||
let fan;
|
||||
if (data) {
|
||||
fan = data;
|
||||
} else {
|
||||
fan = new graphicData.IscsFan({
|
||||
common: BaseGraphicData.defaultCommonInfo(),
|
||||
common: GraphicDataBase.defaultCommonInfo(),
|
||||
});
|
||||
}
|
||||
super(fan);
|
||||
|
@ -2,14 +2,14 @@ import * as pb_1 from 'google-protobuf';
|
||||
import { IPointData } from 'pixi.js';
|
||||
import { ILinkData } from 'src/graphics/link/Link';
|
||||
import { graphicData } from '../protos/draw_data_storage';
|
||||
import { BaseGraphicData } from './BaseGraphicData';
|
||||
import { GraphicDataBase } from './GraphicDataBase';
|
||||
|
||||
export class LinkData extends BaseGraphicData implements ILinkData {
|
||||
export class LinkData extends GraphicDataBase implements ILinkData {
|
||||
constructor(data?: graphicData.Link) {
|
||||
let link;
|
||||
if (!data) {
|
||||
link = new graphicData.Link({
|
||||
common: BaseGraphicData.defaultCommonInfo(),
|
||||
common: GraphicDataBase.defaultCommonInfo(),
|
||||
});
|
||||
} else {
|
||||
link = data;
|
||||
|
@ -70,7 +70,22 @@ export const DefaultCanvasMenu = new ContextMenu({
|
||||
],
|
||||
});
|
||||
|
||||
export function initDrawApp(app: JlDrawApp) {
|
||||
let drawApp: JlDrawApp | null = null;
|
||||
|
||||
export function getDrawApp(): JlDrawApp | null {
|
||||
return drawApp;
|
||||
}
|
||||
|
||||
export function destroyDrawApp(): void {
|
||||
if (drawApp) {
|
||||
drawApp.destroy();
|
||||
drawApp = null;
|
||||
}
|
||||
}
|
||||
|
||||
export function initDrawApp(dom: HTMLElement): JlDrawApp {
|
||||
drawApp = new JlDrawApp(dom);
|
||||
const app = drawApp;
|
||||
app.setOptions({
|
||||
drawAssistants: [
|
||||
new LinkDraw(app, () => {
|
||||
@ -137,6 +152,7 @@ export function initDrawApp(app: JlDrawApp) {
|
||||
},
|
||||
})
|
||||
);
|
||||
return drawApp;
|
||||
}
|
||||
|
||||
const StorageKey = 'graphic-storage';
|
||||
|
@ -11,22 +11,19 @@ import {
|
||||
} from 'pixi.js';
|
||||
import { GraphicIdGenerator } from '../core/IdGenerator';
|
||||
import { GraphicData, GraphicTemplate, JlGraphic } from '../core/JlGraphic';
|
||||
import {
|
||||
AppDragEvent,
|
||||
BoundsGraphic,
|
||||
GraphicTransformEvent,
|
||||
ShiftData,
|
||||
TransformPoints,
|
||||
} from '../plugins';
|
||||
import { JlOperation } from '../operation/JlOperation';
|
||||
import {
|
||||
AppDragEvent,
|
||||
AppInteractionPlugin,
|
||||
CombinationKey,
|
||||
GraphicTransformEvent,
|
||||
InteractionPlugin,
|
||||
KeyListener,
|
||||
ShiftData,
|
||||
ViewportMovePlugin,
|
||||
} from '../plugins';
|
||||
import { CommonMouseTool } from '../plugins/CommonMousePlugin';
|
||||
import { MenuItemOptions } from '../ui/Menu';
|
||||
import { DOWN, LEFT, RIGHT, UP, recursiveChildren } from '../utils';
|
||||
import {
|
||||
CanvasData,
|
||||
@ -35,8 +32,6 @@ import {
|
||||
ICanvasProperties,
|
||||
JlCanvas,
|
||||
} from './JlGraphicApp';
|
||||
import { ContextMenu } from '../ui/ContextMenu';
|
||||
import { MenuItemOptions, MenuOptions } from '../ui/Menu';
|
||||
|
||||
/**
|
||||
* 图形绘制助手
|
||||
|
@ -276,8 +276,8 @@ export interface GraphicAppEvents extends GlobalMixins.GraphicAppEvents {
|
||||
graphicstored: [graphic: JlGraphic];
|
||||
graphicdeleted: [graphic: JlGraphic];
|
||||
loadfinish: [];
|
||||
'interaction-plugin-resume': [activeTool: InteractionPlugin]; // 交互插件启用
|
||||
'interaction-plugin-pause': [activeTool: InteractionPlugin]; // 交互插件停止
|
||||
'interaction-plugin-resume': [plugin: InteractionPlugin]; // 交互插件启用
|
||||
'interaction-plugin-pause': [plugin: InteractionPlugin]; // 交互插件停止
|
||||
'options-update': [options: GraphicAppOptions]; // 配置更新
|
||||
graphicselectedchange: [graphic: JlGraphic, selected: boolean];
|
||||
graphicchildselectedchange: [child: DisplayObject, selected: boolean];
|
||||
|
@ -8,7 +8,7 @@ import {
|
||||
} from 'pixi.js';
|
||||
import {
|
||||
AppDragEvent,
|
||||
BaseInteractionPlugin,
|
||||
InteractionPluginBase,
|
||||
InteractionPluginType,
|
||||
KeyListener,
|
||||
} from '.';
|
||||
@ -154,7 +154,7 @@ export class GraphicTransformEvent {
|
||||
}
|
||||
}
|
||||
|
||||
export class GraphicTransformPlugin extends BaseInteractionPlugin {
|
||||
export class GraphicTransformPlugin extends InteractionPluginBase {
|
||||
static Name = '__graphic_transform_plugin';
|
||||
|
||||
/**
|
||||
|
@ -33,9 +33,12 @@ export interface InteractionPlugin {
|
||||
* 是否生效
|
||||
*/
|
||||
isActive(): boolean;
|
||||
isAppPlugin(): boolean;
|
||||
isOtherPlugin(): boolean;
|
||||
isGraphicPlugin(): boolean;
|
||||
}
|
||||
|
||||
export abstract class BaseInteractionPlugin implements InteractionPlugin {
|
||||
export abstract class InteractionPluginBase implements InteractionPlugin {
|
||||
readonly _type: string;
|
||||
name: string; // 唯一标识
|
||||
app: GraphicApp;
|
||||
@ -55,6 +58,7 @@ export abstract class BaseInteractionPlugin implements InteractionPlugin {
|
||||
resume(): void {
|
||||
this.bind();
|
||||
this._pause = false;
|
||||
this.app.emit('interaction-plugin-resume', this);
|
||||
}
|
||||
/**
|
||||
* 停止
|
||||
@ -62,6 +66,7 @@ export abstract class BaseInteractionPlugin implements InteractionPlugin {
|
||||
pause(): void {
|
||||
this.unbind();
|
||||
this._pause = true;
|
||||
this.app.emit('interaction-plugin-pause', this);
|
||||
}
|
||||
|
||||
abstract bind(): void;
|
||||
@ -72,6 +77,21 @@ export abstract class BaseInteractionPlugin implements InteractionPlugin {
|
||||
isActive(): boolean {
|
||||
return !this._pause;
|
||||
}
|
||||
isGraphicPlugin(): boolean {
|
||||
return this._type === InteractionPluginType.Graphic;
|
||||
}
|
||||
isAppPlugin(): boolean {
|
||||
return this._type === InteractionPluginType.App;
|
||||
}
|
||||
isOtherPlugin(): boolean {
|
||||
return this._type === InteractionPluginType.Other;
|
||||
}
|
||||
}
|
||||
|
||||
export abstract class OtherInteractionPlugin extends InteractionPluginBase {
|
||||
constructor(app: GraphicApp, name: string) {
|
||||
super(app, name, InteractionPluginType.Other);
|
||||
}
|
||||
}
|
||||
|
||||
export class AppDragEvent {
|
||||
@ -152,7 +172,7 @@ export class AppDragEvent {
|
||||
/**
|
||||
* 拖拽操作插件
|
||||
*/
|
||||
export class DragPlugin extends BaseInteractionPlugin {
|
||||
export class DragPlugin extends OtherInteractionPlugin {
|
||||
static Name = '__drag_operation_plugin';
|
||||
private threshold = 3;
|
||||
target: DisplayObject | null = null;
|
||||
@ -160,7 +180,7 @@ export class DragPlugin extends BaseInteractionPlugin {
|
||||
startClientPoint: Point | null = null;
|
||||
drag = false;
|
||||
constructor(app: GraphicApp) {
|
||||
super(app, DragPlugin.Name, InteractionPluginType.Other);
|
||||
super(app, DragPlugin.Name);
|
||||
app.on('options-update', (options: IGraphicAppConfig) => {
|
||||
if (options.threshold !== undefined) {
|
||||
this.threshold = options.threshold;
|
||||
@ -258,7 +278,7 @@ export class DragPlugin extends BaseInteractionPlugin {
|
||||
/**
|
||||
* 视口移动插件
|
||||
*/
|
||||
export class ViewportMovePlugin extends BaseInteractionPlugin {
|
||||
export class ViewportMovePlugin extends OtherInteractionPlugin {
|
||||
static Name = '__viewport_move_plugin';
|
||||
|
||||
static MoveInterval = 20; // 移动间隔,单位ms
|
||||
@ -270,7 +290,7 @@ export class ViewportMovePlugin extends BaseInteractionPlugin {
|
||||
moveSpeedy = 0;
|
||||
|
||||
constructor(app: GraphicApp) {
|
||||
super(app, ViewportMovePlugin.Name, InteractionPluginType.Other);
|
||||
super(app, ViewportMovePlugin.Name);
|
||||
}
|
||||
|
||||
static new(app: GraphicApp): ViewportMovePlugin {
|
||||
@ -360,9 +380,7 @@ export class ViewportMovePlugin extends BaseInteractionPlugin {
|
||||
/**
|
||||
* 应用交互插件,同时只能生效一个
|
||||
*/
|
||||
export abstract class AppInteractionPlugin extends BaseInteractionPlugin {
|
||||
readonly _type = InteractionPluginType.App;
|
||||
|
||||
export abstract class AppInteractionPlugin extends InteractionPluginBase {
|
||||
constructor(name: string, app: GraphicApp) {
|
||||
super(app, name, InteractionPluginType.App);
|
||||
}
|
||||
@ -372,8 +390,7 @@ export abstract class AppInteractionPlugin extends BaseInteractionPlugin {
|
||||
*/
|
||||
resume(): void {
|
||||
this.app.pauseAppInteractionPlugins();
|
||||
this.bind();
|
||||
this._pause = false;
|
||||
super.resume();
|
||||
}
|
||||
}
|
||||
|
||||
@ -409,16 +426,27 @@ export abstract class GraphicInteractionPlugin<G extends JlGraphic>
|
||||
isActive(): boolean {
|
||||
return !this._pause;
|
||||
}
|
||||
isAppPlugin(): boolean {
|
||||
return false;
|
||||
}
|
||||
isOtherPlugin(): boolean {
|
||||
return false;
|
||||
}
|
||||
isGraphicPlugin(): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
resume(): void {
|
||||
const list = this.filter(...this.app.queryStore.getAllGraphics());
|
||||
this.binds(list);
|
||||
this._pause = false;
|
||||
this.app.emit('interaction-plugin-resume', this);
|
||||
}
|
||||
pause(): void {
|
||||
const list = this.filter(...this.app.queryStore.getAllGraphics());
|
||||
this.unbinds(list);
|
||||
this._pause = true;
|
||||
this.app.emit('interaction-plugin-pause', this);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -97,35 +97,7 @@
|
||||
<q-drawer show-if-above bordered v-model="rightDrawerOpen" side="right">
|
||||
<q-resize-observer @resize="onRightResize" />
|
||||
<!-- drawer content -->
|
||||
<q-list bordered padding class="rounded-borders text-primary">
|
||||
<q-item
|
||||
clickable
|
||||
v-ripple
|
||||
:active="link === 'inbox'"
|
||||
@click="link = 'inbox'"
|
||||
active-class="my-menu-link"
|
||||
>
|
||||
<q-item-section avatar>
|
||||
<q-icon name="inbox" />
|
||||
</q-item-section>
|
||||
|
||||
<q-item-section>Inbox</q-item-section>
|
||||
</q-item>
|
||||
|
||||
<q-item
|
||||
clickable
|
||||
v-ripple
|
||||
:active="link === 'outbox'"
|
||||
@click="link = 'outbox'"
|
||||
active-class="my-menu-link"
|
||||
>
|
||||
<q-item-section avatar>
|
||||
<q-icon name="send" />
|
||||
</q-item-section>
|
||||
|
||||
<q-item-section>Outbox</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
<draw-properties></draw-properties>
|
||||
</q-drawer>
|
||||
|
||||
<q-page-container>
|
||||
@ -135,10 +107,13 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { initDrawApp, loadDrawDatas } from 'src/examples/app';
|
||||
import { JlDrawApp } from 'src/jlgraphic';
|
||||
import DrawProperties from 'src/components/draw-app/DrawProperties.vue';
|
||||
import { getDrawApp, initDrawApp, loadDrawDatas } from 'src/examples/app';
|
||||
import { useDrawStore } from 'src/stores/draw-store';
|
||||
import { onMounted, onUnmounted, ref } from 'vue';
|
||||
|
||||
const drawStore = useDrawStore();
|
||||
|
||||
const leftDrawerOpen = ref(false);
|
||||
const rightDrawerOpen = ref(false);
|
||||
function toggleLeftDrawer() {
|
||||
@ -152,12 +127,11 @@ function toggleRightDrawer() {
|
||||
|
||||
const link = ref('outbox');
|
||||
|
||||
let drawApp: JlDrawApp | null = null;
|
||||
onMounted(() => {
|
||||
console.log('绘制应用layout mounted');
|
||||
const dom = document.getElementById('draw-app-container');
|
||||
if (dom) {
|
||||
drawApp = new JlDrawApp(dom);
|
||||
initDrawApp(drawApp);
|
||||
const drawApp = drawStore.initDrawApp(dom);
|
||||
loadDrawDatas(drawApp);
|
||||
}
|
||||
});
|
||||
@ -194,14 +168,13 @@ function onResize() {
|
||||
dom.style.width = canvasWidth.value + 'px';
|
||||
dom.style.height = canvasHeight.value + 'px';
|
||||
}
|
||||
const drawApp = getDrawApp();
|
||||
if (drawApp) {
|
||||
drawApp.onDomResize(canvasWidth.value, canvasHeight.value);
|
||||
}
|
||||
}
|
||||
|
||||
onUnmounted(() => {
|
||||
if (drawApp) {
|
||||
drawApp.destroy();
|
||||
}
|
||||
drawStore.destroy();
|
||||
});
|
||||
</script>
|
||||
|
29
src/stores/draw-store.ts
Normal file
29
src/stores/draw-store.ts
Normal file
@ -0,0 +1,29 @@
|
||||
import { defineStore } from 'pinia';
|
||||
import { destroyDrawApp, initDrawApp } from 'src/examples/app';
|
||||
import { GraphicDrawAssistant } from 'src/jlgraphic';
|
||||
|
||||
export const useDrawStore = defineStore('draw', {
|
||||
state: () => ({
|
||||
drawMode: false,
|
||||
}),
|
||||
getters: {},
|
||||
actions: {
|
||||
initDrawApp(dom: HTMLElement) {
|
||||
const app = initDrawApp(dom);
|
||||
app.on('interaction-plugin-resume', (plugin) => {
|
||||
if (plugin.isAppPlugin()) {
|
||||
if (plugin instanceof GraphicDrawAssistant) {
|
||||
this.drawMode = true;
|
||||
} else {
|
||||
this.drawMode = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
return app;
|
||||
},
|
||||
destroy() {
|
||||
this.drawMode = false;
|
||||
destroyDrawApp();
|
||||
},
|
||||
},
|
||||
});
|
Loading…
Reference in New Issue
Block a user