Skip to content

Commit

Permalink
first update
Browse files Browse the repository at this point in the history
  • Loading branch information
octo-kumo committed Dec 11, 2023
1 parent 6b2f5a4 commit 4a004d2
Show file tree
Hide file tree
Showing 34 changed files with 6,246 additions and 2,766 deletions.
13 changes: 13 additions & 0 deletions components/JsonEditorVue.client.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<script setup>
import JsonEditorVue from 'json-editor-vue'
const value = ref()
const attrs = useAttrs()
</script>

<template>
<JsonEditorVue
v-model="value"
v-bind="attrs"
/>
</template>
49 changes: 49 additions & 0 deletions components/KumoDrawer.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<script setup lang="ts">
import {useDrawer} from "@/composables/states";
const drawer = useDrawer();
const router = useRouter();
const nav = router.getRoutes();
function getName(name?: string | symbol) {
switch (name) {
case "projects-er-editor":
return "ER Editor"
case "projects-json-schema":
return "JSON Editor"
case "projects-price-comparator":
return "Price Comparator"
case "projects-thumbnails":
return "Thumbnails"
default:
return String(name);
}
}
</script>

<template>
<v-navigation-drawer color="grey-darken-2" v-model="drawer">
<v-list>
<v-list-item title="白云" subtitle="Personal Site"></v-list-item>
<v-divider></v-divider>
<v-list-item title="Home" to="/" prepend-icon="mdi-home"></v-list-item>
<v-list-group>
<template v-slot:activator="{ props }">
<v-list-item
v-bind="props"
prepend-icon="mdi-folder-heart"
title="Tools"
></v-list-item>
</template>
<v-list-item v-for="n in nav.filter(r=>r.path.startsWith('/projects'))"
:title="getName(n.name)" :key="n.name"
:to="n"></v-list-item>
</v-list-group>
<v-list-item title="About" to="/about" prepend-icon="mdi-information"></v-list-item>
</v-list>
</v-navigation-drawer>
</template>

<style scoped lang="css">
</style>
11 changes: 11 additions & 0 deletions components/KumoHeader.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<template>
<v-app-bar scroll-behavior="inverted" color="black" order="1">
<v-app-bar-nav-icon @click="drawer=!drawer"/>
<v-app-bar-title>云</v-app-bar-title>
</v-app-bar>
</template>
<script setup>
import {useDrawer} from "@/composables/states";
const drawer = useDrawer();
</script>
11 changes: 11 additions & 0 deletions components/NavFab.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<script setup lang="ts">
</script>

<template>
<button></button>
</template>

<style scoped lang="css">
</style>
1 change: 1 addition & 0 deletions composables/states.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const useDrawer = () => useState<boolean>('counter', () => false);
13 changes: 13 additions & 0 deletions layouts/default.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<template>
<v-app>
<NuxtLoadingIndicator/>
<kumo-header/>
<kumo-drawer/>
<v-main>
<slot/>
</v-main>
<NavFab/>
</v-app>
</template>
<script setup lang="ts">
</script>
34 changes: 34 additions & 0 deletions model/er_model/data-types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
export type ObjectType = 'entity' | 'relationship' | 'attribute' | 'specialization';

export type attributeEntity = {
'did': string;
'id': string;
'isDerived': boolean;
'isKey': boolean;
'pid': string | null;
}

export type objectEntity = {
'did': string;
'id': string;
'name': string;
'outlined': boolean;
'type': ObjectType;
'x': number;
'y': number;
}

// export type relatesEntity = {
// 'cardinality': string;
// 'did': string;
// 'oid': string;
// 'rid': string;
// 'role': string;
// 'total': boolean;
// }

export type specializationEntity = {
'did': string;
'disjoint': boolean;
'id': string;
}
162 changes: 162 additions & 0 deletions model/er_model/line.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
import Vector, {alwaysUp} from "@/model/vector";
import {Shape} from "@/model/er_model/shape";
import type {Relation} from "@/model/er_model/model";
import {ERObject} from "@/model/er_model/model";

export interface LineParam {
a?: Vector
b?: Vector
}

export interface RelationLineParam {
a: ERObject;
b: ERObject;
r: Relation;
}

export type LineStyle = "curve" | "straight" | "axis"


export function lineUnderString(ctx: CanvasRenderingContext2D, text: string) {
const textMetrics = ctx.measureText(text)
return new Line({
a: new Vector({x: -textMetrics.width / 2, y: textMetrics.actualBoundingBoxAscent}),
b: new Vector({x: textMetrics.width / 2, y: textMetrics.actualBoundingBoxAscent})
})
}

export function fancyLine(ctx: CanvasRenderingContext2D, a: Vector, b: Vector, style: LineStyle) {
const d = b.minus(a)
const s = a.add(b)
const horizontal = Math.abs(d.y) < Math.abs(d.x)
const mid = horizontal ? s.x / 2 : s.y / 2
ctx.beginPath()
switch (style) {
case 'straight':
ctx.moveTo(a.x, a.y)
ctx.lineTo(b.x, b.y)
break
case 'axis':
moveTo(a.x, a.y)
if (horizontal) {
ctx.lineTo(mid, a.y)
ctx.lineTo(mid, b.y)
} else {
ctx.lineTo(a.x, mid)
ctx.lineTo(b.x, mid)
}
ctx.lineTo(b.x, b.y)
break
case 'curve':
moveTo(a.x, a.y)
if (horizontal) ctx.bezierCurveTo(mid, a.y, mid, b.y, b.x, b.y)
else ctx.bezierCurveTo(a.x, mid, b.x, mid, b.x, b.y)
break
}
ctx.closePath()
}


export class Line extends Shape {
a!: Vector
b!: Vector

constructor({a, b}: LineParam) {
super()
this.a = a ?? new Vector({})
this.b = b ?? new Vector({})
}

draw(ctx: CanvasRenderingContext2D) {
ctx.beginPath()
ctx.moveTo(this.a.x, this.a.y)
ctx.lineTo(this.b.x, this.b.y)
ctx.closePath()
ctx.stroke()
}

translated(x: number, y: number): Shape {
return new Line({a: this.a.add(x, y), b: this.b.add(x, y)})
}

contains(_point: Vector): boolean {
return false
}
}

export class RelationLine extends Line {
private r: Relation
private normal = new Vector({})

constructor({a, b, r}: RelationLineParam) {
super({a, b})
this.r = r
}

predraw(ctx: CanvasRenderingContext2D) {
this.setNormal()
const a = this.getStart()
const b = this.getEnd()
if (this.r.total) {
ctx.lineWidth = 4
fancyLine(ctx, a, b, 'straight')
ctx.stroke()

ctx.lineWidth = 3
ctx.strokeStyle = "#fff"
fancyLine(ctx, a, b, 'straight')
ctx.stroke()
ctx.strokeStyle = "#000"
ctx.lineWidth = 1
} else {
fancyLine(ctx, a, b, 'straight')
ctx.stroke()
}
}

draw(ctx: CanvasRenderingContext2D) {
this.setNormal()
const a = this.getStart()
const b = this.getEnd()
const d = b.minus(a)
const c = a.add(b).div(2)
if (this.r.role) {
const mid = b.add(a).div(2)
const angle = alwaysUp(d.angle() - Math.PI / 2) + Math.PI / 2
ctx.save()
ctx.translate(mid.x, mid.y)
ctx.rotate(angle)
ctx.fillStyle = "#fff"
const metrics = ctx.measureText(this.r.role)
const w = metrics.width
const h = metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent
ctx.fillRect(-w / 2, -h / 2, w, h)
ctx.fillStyle = "#000"
ctx.fillText(this.r.role, 0, 0)
ctx.restore()
}
if (this.r.cardinality) {
const dist = 10
const angle = alwaysUp(d.angle() + Math.PI / 2) +
((this.r.uniqueIndex || 0) % 2 === (d.x >= 0 ? 1 : 0) ? 0 : Math.PI)
c.incre(Math.cos(angle) * dist, Math.sin(angle) * dist)
ctx.fillText(this.r.cardinality, c.x, c.y)
}
}

getStart() {
return this.a.add(this.normal.multi(this.bouncingIndex(this.r.uniqueIndex ?? 0) + ((this.r.dupeCount ?? 0) % 2 === 0 ? -0.5 : 0)))
}

getEnd() {
return this.b.add(this.normal.multi(this.bouncingIndex(this.r.uniqueIndex ?? 0) + ((this.r.dupeCount ?? 0) % 2 === 0 ? -0.5 : 0)))
}

setNormal() {
this.normal.set(this.b.minus(this.a).rot90().norm().scale(15))
}

bouncingIndex(i: number) {
return i % 2 === 0 ? -Math.floor(i / 2) : Math.floor(i / 2) + 1
}
}
Loading

0 comments on commit 4a004d2

Please sign in to comment.