Skip to content

Feature/resize panel #105

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Apr 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 31 additions & 11 deletions ui/arduino/main.css
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
@import url('https://fonts.googleapis.com/css2?family=Roboto+Mono:wght@400;700&display=swap');
@font-face {
font-family: "RobotoMono", monospace;
src:
url("media/roboto-mono-latin-ext-400-normal.woff"),
url("media/roboto-mono-latin-ext-400-normal.woff2");
font-weight: normal;
font-style: normal;
}

* {
/* box-sizing: border-box; */
-moz-user-select: none;
-webkit-user-select: none;
user-select: none;
font-family: "RobotoMono", monospace;
}

body, html {
Expand All @@ -31,6 +39,7 @@ button {
border-radius: 45px;
background: rgba(255, 255, 255, 0.8);
cursor: pointer;
transition: all 0.1s;
}
button.small {
width: 28px;
Expand Down Expand Up @@ -99,7 +108,7 @@ button.small .icon {
height: 100%;
justify-content: center;
align-items: center;
font-family: Roboto Mono;
font-family: "RobotoMono", monospace;
overflow: hidden;
}

Expand Down Expand Up @@ -141,6 +150,7 @@ button.small .icon {
cursor: pointer;
background: #DAE3E3;
overflow: hidden;
transition: all 0.1s;
}

.tab:hover {
Expand Down Expand Up @@ -259,12 +269,18 @@ button.small .icon {
transition: height 0.15s;
}

#panel.closed {
height: 45px;
#panel {
min-height: 45px;
}

#panel #drag-handle {
width: 100%;
height: 100%;
cursor: grab;
}

#panel.open {
height: 320px;
#panel #drag-handle:active {
cursor: grabbing;
}

.panel-bar {
Expand All @@ -290,6 +306,7 @@ button.small .icon {
.panel-bar .term-operations.hidden {
opacity: 0;
transition-delay: 0.15s;
pointer-events: none;
}
.panel-bar .term-operations.visible {
opacity: 1;
Expand Down Expand Up @@ -445,7 +462,7 @@ button.small .icon {
position: relative;
cursor: pointer;
color: #000;
font-family: Roboto Mono;
font-family: "RobotoMono", monospace;
font-size: 14px;
font-style: normal;
font-weight: 400;
Expand All @@ -472,7 +489,7 @@ button.small .icon {
width: 30px;
height: 100%;
background: linear-gradient(0.25turn, white 25%, rgba(0, 0, 0, 0));
z-index: 99;
z-index: 98;
}

.file-list {
Expand Down Expand Up @@ -504,6 +521,7 @@ button.small .icon {
align-items: center;
gap: 10px;
align-self: stretch;
transition: all 0.1s;
}

.file-list .item.selected,
Expand All @@ -512,14 +530,16 @@ button.small .icon {
}

.file-list .item .options {
display: none;
display: flex;
opacity: 0;
align-items: center;
align-self: stretch;
cursor: pointer;
transition: all 0.1s;
}

.file-list .item:hover .options {
display: flex;
opacity: 1;
}

.file-list .item .icon {
Expand All @@ -528,7 +548,7 @@ button.small .icon {
}
.file-list .item .text {
color: #000;
font-family: Roboto Mono;
font-family: "RobotoMono", monospace;
font-size: 14px;
font-style: normal;
font-weight: 400;
Expand Down
4 changes: 3 additions & 1 deletion ui/arduino/main.js
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe these 3 constants could indicate we're referring to HEIGHT.
Verbosity never hurts :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It kind of does hurt, though. Of course the variable name can be PANEL_HEIGHT_CLOSED but I opted to keep the word height on the other side of the expression and leave the constant names shorter:

state.panelHeight = PANEL_CLOSED
state.savedPanelHeight = PANEL_DEFAULT

if (state.panelHeight < PANEL_TOO_SMALL) {
  ...
}

It also reads cleaner without the "height" on both sides, in my humble opinion.

Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
const PANEL_HEIGHT = 320
const PANEL_CLOSED = 45
const PANEL_TOO_SMALL = 65
const PANEL_DEFAULT = 320

function App(state, emit) {
if (state.diskNavigationRoot == null) {
Expand Down
Binary file not shown.
Binary file not shown.
57 changes: 47 additions & 10 deletions ui/arduino/store.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,6 @@ async function store(state, emitter) {
state.isConnected = false
state.connectedPort = null


state.isPanelOpen = false
state.isSaving = false
state.savingProgress = 0
state.isTransferring = false
Expand All @@ -53,6 +51,18 @@ async function store(state, emitter) {
state.openFiles.push(newFile)
state.editingFile = newFile.id

state.savedPanelHeight = PANEL_DEFAULT
state.panelHeight = PANEL_CLOSED
state.resizePanel = function(e) {
state.panelHeight = (PANEL_CLOSED/2) + document.body.clientHeight - e.clientY
if (state.panelHeight <= PANEL_CLOSED) {
state.savedPanelHeight = PANEL_DEFAULT
} else {
state.savedPanelHeight = state.panelHeight
}
emitter.emit('render')
}

// START AND BASIC ROUTING
emitter.on('select-disk-navigation-root', async () => {
const folder = await selectDiskFolder()
Expand Down Expand Up @@ -110,8 +120,8 @@ async function store(state, emitter) {
// Connected and ready
state.isConnecting = false
state.isConnected = true
if (state.view === 'editor') {
state.isPanelOpen = true
if (state.view === 'editor' && state.panelHeight <= PANEL_CLOSED) {
state.panelHeight = state.savedPanelHeight
}
state.connectedPort = path

Expand All @@ -138,7 +148,7 @@ async function store(state, emitter) {
emitter.on('disconnect', async () => {
await serial.disconnect()
state.isConnected = false
state.isPanelOpen = false
state.panelHeight = PANEL_CLOSED
state.boardFiles = []
state.boardNavigationPath = '/'
emitter.emit('refresh-files')
Expand All @@ -155,9 +165,9 @@ async function store(state, emitter) {
// CODE EXECUTION
emitter.on('run', async () => {
log('run')
state.isPanelOpen = true
const openFile = state.openFiles.find(f => f.id == state.editingFile)
const code = openFile.editor.editor.state.doc.toString()
emitter.emit('open-panel')
emitter.emit('render')
try {
await serial.get_prompt()
Expand All @@ -168,13 +178,19 @@ async function store(state, emitter) {
})
emitter.on('stop', async () => {
log('stop')
state.isPanelOpen = true
if (state.panelHeight <= PANEL_CLOSED) {
state.panelHeight = state.savedPanelHeight
}
emitter.emit('open-panel')
emitter.emit('render')
await serial.get_prompt()
})
emitter.on('reset', async () => {
log('reset')
state.isPanelOpen = true
if (state.panelHeight <= PANEL_CLOSED) {
state.panelHeight = state.savedPanelHeight
}
emitter.emit('open-panel')
emitter.emit('render')
await serial.reset()
emitter.emit('update-files')
Expand All @@ -183,16 +199,37 @@ async function store(state, emitter) {

// PANEL
emitter.on('open-panel', () => {
state.isPanelOpen = true
emitter.emit('stop-resizing-panel')
state.panelHeight = state.savedPanelHeight
emitter.emit('render')
setTimeout(() => {
state.cache(XTerm, 'terminal').resizeTerm()
}, 200)
})
emitter.on('close-panel', () => {
state.isPanelOpen = false
emitter.emit('stop-resizing-panel')
state.savedPanelHeight = state.panelHeight
state.panelHeight = 0
emitter.emit('render')
})
emitter.on('clear-terminal', () => {
state.cache(XTerm, 'terminal').term.clear()
})
emitter.on('start-resizing-panel', () => {
log('start-resizing-panel')
window.addEventListener('mousemove', state.resizePanel)
// Stop resizing when mouse leaves window or enters the tabs area
document.body.addEventListener('mouseleave', () => {
emitter.emit('stop-resizing-panel')
}, { once: true })
document.querySelector('#tabs').addEventListener('mouseenter', () => {
emitter.emit('stop-resizing-panel')
}, { once: true })
})
emitter.on('stop-resizing-panel', () => {
log('stop-resizing-panel')
window.removeEventListener('mousemove', state.resizePanel)
})

// SAVING
emitter.on('save', async () => {
Expand Down
5 changes: 3 additions & 2 deletions ui/arduino/views/components/elements/terminal.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,13 @@ class XTerm extends Component {
}

resizeTerm() {
// XXX: This should not be querying the DOM like that :o
if (document.querySelector('#panel')) {
let handleSize = 45
const parentStyle = window.getComputedStyle(document.querySelector('#panel'))
const parentWidth = parseInt(parentStyle.getPropertyValue('width'))
const parentHeight = parseInt(parentStyle.getPropertyValue('height'))
const cols = Math.floor(parentWidth / this.term._core._renderService.dimensions.actualCellWidth) - 6
const rows = Math.floor((PANEL_HEIGHT-handleSize) / this.term._core._renderService.dimensions.actualCellHeight) - 2
const rows = Math.floor((parentHeight-PANEL_CLOSED) / this.term._core._renderService.dimensions.actualCellHeight) - 2
this.term.resize(cols, rows)
}
}
Expand Down
14 changes: 8 additions & 6 deletions ui/arduino/views/components/repl-panel.js
Original file line number Diff line number Diff line change
@@ -1,25 +1,27 @@
function ReplPanel(state, emit) {
let height = state.isPanelOpen ? PANEL_HEIGHT : 45

const onToggle = () => {
if (state.isPanelOpen) {
if (state.panelHeight > PANEL_CLOSED) {
emit('close-panel')
} else {
emit('open-panel')
}
}
const panelOpenClass = state.isPanelOpen ? 'open' : 'closed'
const termOperationsVisibility = state.isPanelOpen ? 'visible' : 'hidden'
const termOperationsVisibility = state.panelHeight > PANEL_TOO_SMALL ? 'visible' : 'hidden'
const terminalDisabledClass = state.isConnected ? 'terminal-enabled' : 'terminal-disabled'

return html`
<div id="panel" class="${panelOpenClass}">
<div id="panel" style="height: ${state.panelHeight}px">
<div class="panel-bar">
<div id="drag-handle"
onmousedown=${() => emit('start-resizing-panel')}
onmouseup=${() => emit('stop-resizing-panel')}
></div>
<div class="term-operations ${termOperationsVisibility}">
${ReplOperations(state, emit)}
</div>
${Button({
icon: `arrow-${state.isPanelOpen ? 'down' : 'up'}.svg`,
icon: `arrow-${state.panelHeight > PANEL_CLOSED ? 'down' : 'up'}.svg`,
size: 'small',
onClick: onToggle
})}
Expand Down