Skip to content

Commit

Permalink
Merge pull request #1 from novrain/feature/using_lumino_widget
Browse files Browse the repository at this point in the history
Feature/using lumino widget
  • Loading branch information
novrain authored Dec 13, 2023
2 parents eef37c3 + 96fbcfd commit 95e2da3
Show file tree
Hide file tree
Showing 14 changed files with 597 additions and 132 deletions.
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@ Target: Build a protocol testing tool that supports various connection methods.

### UI

Communication between two serial ports.
Using lumino, drag and drop function to change the layout, making it more convenient for multiple connections.

![COM1](docs/imgs/COM-1.png)
[vue3-lumino-widget](https://github.com/novrain/vue3-lumino-widget)

![COM2](docs/imgs/COM-2.png)
Send and receive data between two serial ports.

![Lumino](docs/imgs/Lumino.png)

## Development

Expand Down
8 changes: 5 additions & 3 deletions README_zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@

### UI

两个串口间收发数据。
引入了Lumino, 方便的拖拽功能,改变布局,多连接时更便捷。

[vue3-lumino-widget](https://github.com/novrain/vue3-lumino-widget)

![COM1](docs/imgs/COM-1.png)
两个串口间收发数据。

![COM2](docs/imgs/COM-2.png)
![Lumino](docs/imgs/Lumino.png)

## 开发

Expand Down
Binary file added docs/imgs/Lumino.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
21 changes: 12 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@
"forge:publish": "electron-forge publish"
},
"dependencies": {
"@fortawesome/fontawesome-free": "^6.5.1",
"@intlify/unplugin-vue-i18n": "^1.5.0",
"@lumino/default-theme": "^2.1.4",
"@lumino/widgets": "^2.3.1",
"@mdi/font": "7.3.67",
"@serialport/binding-abstract": "^10.1.0",
"buffer": "^6.0.3",
Expand All @@ -40,13 +43,13 @@
"js-yaml": "^4.1.0",
"macos-release": "^3.2.0",
"pinia": "^2.1.7",
"reflect-metadata": "^0.1.13",
"reflect-metadata": "^0.1.14",
"roboto-fontface": "*",
"rxjs": "^7.8.1",
"serialport": "^12.0.0",
"splitpanes": "^3.1.5",
"stylus": "^0.62.0",
"vue": "^3.3.10",
"vue": "^3.3.11",
"vue-i18n": "^9.8.0",
"vue-router": "^4.2.5",
"vuetify": "^3.4.6",
Expand All @@ -58,7 +61,7 @@
"windows-native-registry": "^3.2.2"
},
"devDependencies": {
"@babel/types": "^7.23.5",
"@babel/types": "^7.23.6",
"@electron-forge/cli": "^7.2.0",
"@electron-forge/maker-deb": "^7.2.0",
"@electron-forge/maker-rpm": "^7.2.0",
Expand All @@ -67,10 +70,10 @@
"@electron-forge/plugin-auto-unpack-natives": "^7.2.0",
"@types/jest": "^29.5.11",
"@types/js-yaml": "^4.0.9",
"@types/node": "^20.10.3",
"@typescript-eslint/eslint-plugin": "^6.13.2",
"@typescript-eslint/parser": "^6.13.2",
"@vitejs/plugin-vue": "^4.5.1",
"@types/node": "^20.10.4",
"@typescript-eslint/eslint-plugin": "^6.14.0",
"@typescript-eslint/parser": "^6.14.0",
"@vitejs/plugin-vue": "^4.5.2",
"@vue/eslint-config-typescript": "^12.0.0",
"@vue/test-utils": "^2.4.3",
"@vue/vue3-jest": "^29.2.6",
Expand All @@ -84,8 +87,8 @@
"ts-jest": "^29.1.1",
"typescript": "^5.3.3",
"unplugin-fonts": "^1.1.1",
"vite": "^5.0.6",
"vite-plugin-vuetify": "^1.0.2",
"vite": "^5.0.8",
"vite-plugin-vuetify": "^2.0.1",
"vue-tsc": "^1.8.25",
"wait-on": "^7.2.0"
},
Expand Down
5 changes: 4 additions & 1 deletion src/renderer/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
<script setup lang="ts">
import AppMenu from '@/components/Menu.vue'
import SessionManager from '@/views/SessionManager.vue'
import 'splitpanes/dist/splitpanes.css'
// @ts-ignore
import { Pane, Splitpanes } from 'splitpanes'
import { onMounted } from 'vue'
Expand Down Expand Up @@ -92,7 +93,9 @@ onMounted(async () => {
items: undefined,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
handler: (_e: any) => {
window.hostWindow.openExternal('https://github.com/novrain/wavy')
if (window.hostWindow) {
window.hostWindow.openExternal('https://github.com/novrain/wavy')
}
},
}
]
Expand Down
10 changes: 7 additions & 3 deletions src/renderer/src/components/SerialSession.vue
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,8 @@ import { storeToRefs } from 'pinia'
import SessionTextarea from './SessionTextarea.vue'
import { useSerialStore } from '@/store/serial'
import { Buffer } from 'buffer'
import { session } from 'electron'
const emits = defineEmits(['nameChanged'])
const textDecoder = new TextDecoder()
const textEncoder = new TextEncoder()
Expand Down Expand Up @@ -269,7 +270,8 @@ const connect = async () => {
connected.value = r.result
info.value = r.err || ''
if (r.result) {
props.session.name = options.path
// props.session.name = options.path
emits('nameChanged', {session:props.session,name: options.path})
window.serialPort.on(props.session.id, 'data', onData)
window.serialPort.on(props.session.id, 'close', onClose)
window.serialPort.on(props.session.id, 'error', onError)
Expand All @@ -284,7 +286,9 @@ const disconnect = async () => {
return
}
window.serialPort.disconnect(props.session.id)
.then((r: boolean) => connected.value = !r)
.then((r: boolean) => {
connected.value = !r
})
.catch((e) => { console.log(e) })
}
Expand Down
72 changes: 72 additions & 0 deletions src/renderer/src/components/lumino/ItemWidget.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { Message } from '@lumino/messaging'
import { Widget } from '@lumino/widgets'

export interface Item {
id: string,
name: string,
}

export interface OnClose {
(msg: Message): void
}

export interface OnActive {
(msg: Message): void
}

export interface Options {
closable?: boolean
onClose?: OnClose
onActive?: OnActive
}

export interface WidgetEvent {
msg: Message
item: Item
widget: ItemWidget
}

export class ItemWidget extends Widget {
closable: boolean
item: Item
onClose?: OnClose
onActive?: OnActive

constructor(item: Item, { closable = true, onClose }: Options) {
super({ node: ItemWidget.createNode(item) })
this.closable = closable
// classes and flags
this.setFlag(Widget.Flag.DisallowLayout)
this.addClass('lumino-content')
// tab title
this.title.label = item.name
this.title.closable = closable
this.item = item
this.onClose = onClose
}

static createNode(item: Item) {
const div = document.createElement('div')
div.setAttribute('id', item.id)
return div
}

protected onActivateRequest(msg: Message): void {
super.onActivateRequest(msg)
if (this.onActive) {
this.onActive(msg)
}
}

protected onCloseRequest(msg: Message): void {
if (this.onClose) {
this.onClose(msg)
} else {
super.onCloseRequest(msg)
}
}

doClose(msg: Message): void {
super.onCloseRequest(msg)
}
}
65 changes: 65 additions & 0 deletions src/renderer/src/components/lumino/LuminoBoxPanel.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<template>
<div class="lumino-container"
ref="container">
<slot></slot>
</div>
</template>

<script setup lang="ts">
import "@fortawesome/fontawesome-free/css/all.css"
import '@lumino/default-theme/style/index.css'
import { BoxPanel, DockPanel, Widget } from '@lumino/widgets'
import { provide, onMounted, onUpdated, ref, onUnmounted } from 'vue'
const boxPanel = new BoxPanel({ direction: 'left-to-right', spacing: 0 })
const dockPanel = new DockPanel()
boxPanel.id = 'box-panel'
dockPanel.id = 'dock-panel'
provide('boxPanel', boxPanel)
provide('dockPanel', dockPanel)
const container = ref<HTMLElement | null>(null)
const onWindowResize = () => {
boxPanel.update()
}
onMounted(() => {
boxPanel.addWidget(dockPanel)
BoxPanel.setStretch(dockPanel, 1)
if (container.value) {
Widget.attach(boxPanel, container.value)
}
window.addEventListener('resize', onWindowResize)
})
onUnmounted(() => {
window.removeEventListener('resize', onWindowResize)
})
onUpdated(() => {
boxPanel.update()
})
</script>

<style lang="scss" scoped>
.lumino-container {
display: flex;
flex: 1;
:deep(#box-panel) {
display: flex;
flex: 1;
.lumino-content {
border: 1px solid #c0c0c0;
border-top: none;
background: white;
position: relative;
overflow: auto;
display: flex;
}
}
}
</style>
56 changes: 56 additions & 0 deletions src/renderer/src/components/lumino/LuminoWidget.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<template>
<div v-show="false">
<div class="lumino-widget"
ref="realEl">
<slot></slot>
</div>
</div>
</template>

<script setup lang="ts">
import { Message } from '@lumino/messaging'
import { BoxPanel, DockPanel, Widget } from '@lumino/widgets'
import { inject, nextTick, onMounted, ref, watch } from 'vue'
import { ItemWidget, Item } from './ItemWidget'
const props = defineProps(['item', 'closable'])
const emits = defineEmits(['close', 'active'])
const boxPanel: BoxPanel | undefined = inject('boxPanel')
const dockPanel: DockPanel | undefined = inject('dockPanel')
const realEl = ref()
const onLuminoWidgetClose = (msg: Message) => {
emits('close', { msg, item: props.item, widget: luminoWidget })
}
const onLuminoWidgetActive = (msg: Message) => {
emits('close', { msg, item: props.item, widget: luminoWidget })
}
const luminoWidget = new ItemWidget(props.item, {
closable: props.closable,
onClose: onLuminoWidgetClose,
onActive: onLuminoWidgetActive
})
watch(() => props.item, (newItem: Item, oldItem: Item) => {
luminoWidget.title.label = newItem.name
}, { deep: true })
onMounted(() => {
const widgets = dockPanel!.widgets()
if (!Array.from(widgets).find((w: Widget) => {
return w.id === props.item.id
})) {
dockPanel!.addWidget(luminoWidget)
nextTick(() => {
document.getElementById(props.item.id)?.appendChild(realEl.value)
})
}
})
</script>

<style scoped lang="scss">
.lumino-widget {
display: flex;
flex: 1;
}
</style>
1 change: 0 additions & 1 deletion src/renderer/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import { createApp } from 'vue'

// Plugins
import { registerPlugins } from '@/plugins'
import 'splitpanes/dist/splitpanes.css'

const app = createApp(App)

Expand Down
8 changes: 8 additions & 0 deletions src/renderer/src/store/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,14 @@ export const useSessionStore = defineStore('session', {
this.sessions = this.sessions.filter(s => {
return !(s.id === session.id)
})
},
setSessionName(session: Session, name: string) {
const s = this.sessions.find(s => {
return (s.id === session.id)
})
if (s) {
s.name = name
}
}
}
})
Loading

0 comments on commit 95e2da3

Please sign in to comment.