Skip to content
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

Canvas layout bug fixes and edition mode UI improvements #1393

Merged
merged 5 commits into from
May 20, 2022
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
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
:y="y"
:w="w"
:h="h"
:parent="true"
:z="active ? 10 : 0"
:parent="false"
:draggable="!!context.editmode"
:resizable="!!context.editmode && !autosize"
:class-name="!!context.editmode ? 'oh-canvas-item-editmode' : 'oh-canvas-item-runmode'"
Expand All @@ -17,8 +18,12 @@
@dragging="onDrag"
@resizing="onResize"
:on-drag-start="onDragStartCallback"
:on-resize-start="onResizeStartCallback">
<f7-menu v-if="context.editmode" class="configure-canvas-menu">
:on-resize-start="onResizeStartCallback"
@dragstop="onDragStop"
@resizestop="onResizeStop"
:active.sync="active"
:prevent-deactivation="preventDeactivation">
<f7-menu v-if="context.editmode" class="configure-canvas-menu disable-user-select">
<f7-menu-item icon-f7="menu" dropdown icon-only>
<f7-menu-dropdown right>
<f7-menu-dropdown-item @click="context.editmode.configureWidget(context.component, context.parent)" href="#" text="Configure container" />
Expand Down Expand Up @@ -52,14 +57,26 @@
'oh-canvas-item-styled' : styled,
'oh-canvas-item-shadow' : styled && shadow
}" />
<f7-icon v-if="context.editmode" class="drag-handle disable-user-select" f7="move" size="15" color="gray" />
<div v-if="context.editmode" class="oh-canvas-item-id disable-user-select">
{{ config.id }}
</div>
<div v-if="context.editmode && active" class="oh-canvas-item-msg disable-user-select">
{{ editMessage }}
</div>
</div>
<f7-icon v-if="context.editmode" class="drag-handle" f7="move" size="15" color="gray" />
</vue-draggable-resizable>
</template>

<style lang="stylus">
.oh-canvas-item-editmode
outline 1px dashed #F00
cursor move
color red
font-size 10px

*
cursor move !important

.oh-canvas-item
position absolute
Expand Down Expand Up @@ -91,6 +108,16 @@
.label-card-content
text-shadow var(--oh-canvas-item-text-shadow)

.oh-canvas-item-id
position absolute
bottom 0
right 0

.oh-canvas-item-msg
position absolute
bottom -22px
right 0

.placeholder-widget a
height 100%
padding 0
Expand Down Expand Up @@ -133,7 +160,8 @@ export default {
props: {
gridPitch: Number,
gridEnable: Boolean,
id: String
id: String,
preventDeactivation: Boolean
},
data () {
return {
Expand All @@ -143,7 +171,10 @@ export default {
h: 0,
reloadKey: 0,
shadow: true,
styled: true
styled: true,
dragging: false,
resizing: false,
active: false
}
},
created () {
Expand All @@ -157,6 +188,21 @@ export default {
computed: {
autosize () {
return this.w === 'auto'
},
editMessage () {
if (this.dragging) {
return `(${this.x}, ${this.y})`
} else if (this.resizing) {
return `${this.w}x${this.h}`
} else {
return ''
}
}
},
watch: {
active (val) {
if (val) this.$emit('ociSelected', this)
else this.$emit('ociDeselected', this)
}
},
methods: {
Expand All @@ -182,6 +228,10 @@ export default {
this.h = this.context.component.config.h = height
},
onDrag (x, y) {
this.$emit('ociDragged', this, x - this.x, y - this.y)
this.moveTo(x, y)
},
moveTo (x, y) {
this.x = this.context.component.config.x = x
this.y = this.context.component.config.y = y
},
Expand All @@ -197,34 +247,50 @@ export default {

if (this.w === snapW && this.h === snapH) {
// Widget already on grid, can continue to resize
return true && posOK
this.resizing = posOK
} else {
// Widget was not on grid, snap to grid upon first action
this.w = this.context.component.config.w = snapW
this.h = this.context.component.config.h = snapH
return false
this.onResize(this.x, this.y, snapW, snapH)
this.resizing = false
}
} else {
return true
this.resizing = true
}

if (this.resizing) this.dragging = false
return this.resizing
},
onDragStartCallback (ev) {
if (!this.context.editmode) return false

if (this.gridEnable) {
const snapX = Math.round(this.x / this.gridPitch) * this.gridPitch
const snapY = Math.round(this.y / this.gridPitch) * this.gridPitch

if (this.x === snapX && this.y === snapY) {
// Origin on grid, continue dragging action
return true
this.dragging = true
} else {
// First snap to grid component and stop action
this.x = this.context.component.config.x = snapX
this.y = this.context.component.config.y = snapY
return false
this.onDrag(snapX, snapY)
this.dragging = true
}
} else {
return true
this.dragging = true
}

if (this.dragging) this.resizing = false
return this.dragging
},
onResizeStop () {
this.resizing = false
},
onDragStop () {
this.$emit('ociDragStop', this)
this.stopDrag()
},
stopDrag () {
this.dragging = false
},
eventControl (ev) {
// Events are captured before bubbling to prevent undesired widget interaction when a widget has been
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
:id="obj.id"
:grid-enable="gridEnable"
:grid-pitch="gridPitch"
:context="childContext(obj.item)" />
:prevent-deactivation="preventDeactivation"
:context="childContext(obj.item)"
v-on="$listeners" />
</div>
</template>

Expand All @@ -32,7 +34,8 @@ export default {
props: {
gridPitch: Number,
gridEnable: Boolean,
id: String
id: String,
preventDeactivation: Boolean
},
data () {
return {
Expand Down Expand Up @@ -61,6 +64,7 @@ export default {
if (item.component === 'oh-canvas-item') {
layer.push({
item: item,
selected: false,
id: Math.random().toString(36).substring(2)
})
} else {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<div ref="ohCanvasLayout" class="oh-canvas-layout disable-user-select" :class="context.editMode ? 'margin-top' : ''">
<div ref="ohCanvasLayout" class="oh-canvas-layout disable-user-select" :class="context.editmode ? 'margin-top' : ''" @keydown="onKeyDown" @keyup="onKeyUp">
<f7-block v-if="context.editmode">
<f7-menu class="configure-layout-menu">
<f7-menu-item
Expand Down Expand Up @@ -77,6 +77,7 @@
transform: `scale(${style.scale})`,
'text-align': 'center',
position: 'relative',
overflow: context.editmode ? 'visible' : 'hidden',
'--oh-canvas-item-box-shadow': config.boxShadow
? config.boxShadow
: '0px 0px 4px 2px #444',
Expand Down Expand Up @@ -141,7 +142,12 @@
:id="obj.id"
:grid-enable="grid.enable"
:grid-pitch="grid.pitch"
:context="childContext(obj.item)" />
:prevent-deactivation="preventDeactivation"
:context="childContext(obj.item)"
@ociDragged="ociDragged"
@ociDragStop="ociDragStop"
@ociSelected="ociSelected"
@ociDeselected="ociDeselected" />
</div>
</div>
</template>
Expand Down Expand Up @@ -194,7 +200,9 @@ export default {
pitch: Number,
enable: false
},
actLyrIdx: 0
actLyrIdx: 0,
preventDeactivation: false,
selectedItems: []
}
},
computed: {
Expand Down Expand Up @@ -325,6 +333,72 @@ export default {
})
}
this.layout = layout
},
onKeyDown (ev) {
let moveX = 0, moveY = 0
switch (ev.key) {
case 'Shift':
this.preventDeactivation = true
break
case 'ArrowDown':
moveY = 1
break
case 'ArrowUp':
moveY = -1
break
case 'ArrowRight':
moveX = 1
break
case 'ArrowLeft':
moveX = -1
break
}
if (moveX || moveY) {
const moveBy = this.grid.enable ? this.grid.pitch : 1
const didMove = this.moveSelectedItems(null, moveX * moveBy, moveY * moveBy)
if (didMove) {
ev.stopPropagation()
ev.preventDefault()
}
}
},
onKeyUp (ev) {
switch (ev.key) {
case 'Shift':
this.preventDeactivation = false
break
}
},
moveSelectedItems (exceptId, deltaX, deltaY) {
let movedSomething = false
this.selectedItems.forEach(i => {
if (i.id !== exceptId) {
i.moveTo(i.x + deltaX, i.y + deltaY)
movedSomething = true
}
})
return movedSomething
},
ociSelected (item) {
this.selectedItems.push(item)
},
ociDeselected (item) {
this.selectedItems.splice(this.selectedItems.indexOf(item), 1)
},
ociDragged (item, deltaX, deltaY) {
// Move all selected (active) items, except the source one (already moved)
// if there are several objects selected
if (this.selectedItems.length > 1) {
this.moveSelectedItems(item.id, deltaX, deltaY)
}
},
ociDragStop (itemId) {
// Notify items of drag end in case of multiple items selection
if (this.selectedItems.length > 1) {
this.selectedItems.forEach(item => {
item.stopDrag()
})
}
}
}
}
Expand Down