Skip to content

Commit

Permalink
Allow embedding things in other things.
Browse files Browse the repository at this point in the history
  • Loading branch information
grantjbutler committed Nov 27, 2021
1 parent a749c46 commit 4c1dd84
Show file tree
Hide file tree
Showing 15 changed files with 71 additions and 31 deletions.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
37 changes: 21 additions & 16 deletions src/components/Sidebar/TreeControl.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<Disclosure v-slot="{ open }">
<Disclosure v-slot="{ open }" :defaultOpen="true">
<context-menu-providing>
<div class="flex justify-between" :class="{'bg-green-200': isSelected}" @click.prevent="selectComponent">
<div class="flex">
Expand All @@ -18,6 +18,10 @@
<menu-item v-for="action in containerActions" :key="action.title" @click="action.action()">{{ action.title }}</menu-item>
</Submenu>
<menu-separator v-if="isContainerComponent" />
<Submenu label="Embed In...">
<menu-item v-for="action in embedActions" :key="action.title" @click="action.action()">{{ action.title }}</menu-item>
</Submenu>
<menu-separator/>
<menu-item>Delete</menu-item>
</context-menu>
</template>
Expand All @@ -30,24 +34,16 @@

<script lang="ts">
import { computed, defineComponent, PropType, toRefs } from 'vue'
import { Component, FlexComponent, SourceComponent, components as LayoutComponents } from '@/layout';
import { Component, FlexComponent, SourceComponent, ContainerComponent, containerComponents as ContainerComponents, components as LayoutComponents } from '@/layout';
import {
Disclosure,
DisclosureButton,
DisclosurePanel,
} from '@headlessui/vue';
import { ChevronRightIcon } from '@heroicons/vue/solid';
import {
ContextMenuProviding,
ContextMenu,
MenuItem,
Submenu,
MenuSeparator
} from '../Menu'
import { useStore } from 'vuex';
import { key } from '@/store';
import { ADD_CHILD, SELECT_COMPONENT } from '@/store/mutation-types';
import ContainerComponent from '@/layout/ContainerComponent';
import { ADD_CHILD, SELECT_COMPONENT, EMBED_IN_COMPONENT } from '@/store/mutation-types';
interface ContainerAction {
title: string
Expand All @@ -61,11 +57,6 @@ export default defineComponent({
DisclosureButton,
DisclosurePanel,
ChevronRightIcon,
ContextMenuProviding,
ContextMenu,
MenuItem,
Submenu,
MenuSeparator,
},
props: {
component: {
Expand Down Expand Up @@ -119,11 +110,25 @@ export default defineComponent({
return actions;
})
const embedActions = computed((): ContainerAction[] => {
let actions: ContainerAction[] = []
for (const property in ContainerComponents) {
actions.push({
title: LayoutComponents[property].displayName,
action: () => {
store.commit(EMBED_IN_COMPONENT, { id: component.value.id, container: new LayoutComponents[property]() })
}
})
}
return actions
})
return {
selectComponent,
isSelected,
isContainerComponent,
containerActions,
embedActions,
addFlexComponent,
addSourceComponent
}
Expand Down
12 changes: 2 additions & 10 deletions src/layout/Component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,15 @@ import ContainerComponent from './ContainerComponent';

export default class Component {
id: string = uuidv4()
#parent: WeakRef<ContainerComponent> | undefined = undefined;
_parent: WeakRef<ContainerComponent> | undefined = undefined;
customName: string | undefined

get name(): string {
return this.customName ?? Object.getPrototypeOf(this).constructor.displayName
}

get parent(): ContainerComponent | undefined {
return this.#parent?.deref();
}

set _parent(parent: ContainerComponent | undefined) {
if (parent) {
this.#parent = new WeakRef(parent);
} else {
this.#parent = undefined;
}
return this._parent?.deref();
}

removeFromParent(): void {
Expand Down
2 changes: 1 addition & 1 deletion src/layout/ContainerComponent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export default abstract class ContainerComponent extends Component {

addChild(child: Component): void {
this._children.push(child)
child._parent = this
child._parent = new WeakRef(this);
}

_removeChild(child: Component): void {
Expand Down
7 changes: 7 additions & 0 deletions src/layout/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,22 @@ import LayoutExerciser from './LayoutExerciser'
import Frame from './Frame'
import Size from './Size'
import LayoutNode from './LayoutNode'
import ContainerComponent from './ContainerComponent';

export const components: { [index: string]: typeof Component } = {
FlexComponent,
InsetComponent,
SourceComponent
}

export const containerComponents: { [index: string]: typeof ContainerComponent } = {
FlexComponent,
InsetComponent
}

export {
Component,
ContainerComponent,
FlexComponent,
InsetComponent,
SourceComponent,
Expand Down
8 changes: 8 additions & 0 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,18 @@ import { createApp } from 'vue'
import App from './App.vue'
import { store, key } from './store'
import observeResize from './directives/observe-resize'
import {
ContextMenu, ContextMenuProviding, MenuItem, MenuSeparator, Submenu
} from './components/ContextMenu';

createApp(App)
.use(store, key)
.directive(
'observe-resize', observeResize
)
.component('context-menu', ContextMenu)
.component('context-menu-providing', ContextMenuProviding)
.component('menu-item', MenuItem)
.component('menu-separator', MenuSeparator)
.component('Submenu', Submenu)
.mount('#app')
23 changes: 20 additions & 3 deletions src/store/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Component, FlexComponent, SourceComponent, LayoutExerciser, LayoutNode, Size } from '@/layout'
import { Component, FlexComponent, SourceComponent, LayoutExerciser, LayoutNode, Size, containerComponents } from '@/layout'
import ContainerComponent from '@/layout/ContainerComponent'
import InsetComponent from '@/layout/InsetComponent'
import Insets from '@/layout/Insets'
Expand All @@ -8,13 +8,15 @@ import { createStore, Store } from 'vuex'
import {
SELECT_COMPONENT,
ADD_CHILD,
EMBED_IN_COMPONENT,
EXERCISE_LAYOUT,
FLEX_SET_DIRECTION,
FLEX_SET_DISTRIBUTION,
FLEX_SET_SPACING,
INSET_SET_INSETS,
SOURCE_SET_SOURCE,
SET_PREVIEW_SIZE,
layoutExercisingMutations
} from './mutation-types'

export interface State {
Expand Down Expand Up @@ -44,10 +46,25 @@ export const store = createStore<State>({
state.rootNode = new LayoutExerciser().execute(state.rootComponent, state.previewSize)
},
[ADD_CHILD](state: State, payload: { component: Component, parentId: string }) {
const parent = state.rootComponent?.childWithId(payload.parentId)
const parent = state.rootComponent.childWithId(payload.parentId)
if (!parent || !(parent instanceof ContainerComponent)) { return }
parent.addChild(payload.component)
},
[EMBED_IN_COMPONENT](state: State, payload: { id: string, container: ContainerComponent }) {
if (state.rootComponent.id == payload.id) {
payload.container.addChild(state.rootComponent)
state.rootComponent = payload.container
} else {
const child = state.rootComponent.childWithId(payload.id)
if (!child) { return; }
const parent = child.parent;
if (!parent) { return; }

child.removeFromParent()
parent.addChild(payload.container)
payload.container.addChild(child)
}
},
[FLEX_SET_DIRECTION](state: State, direction: 'horizontal' | 'vertical') {
if (!state.selectedComponent || !(state.selectedComponent instanceof FlexComponent)) {
return;
Expand Down Expand Up @@ -86,7 +103,7 @@ export const store = createStore<State>({
plugins: [
(store) => {
store.subscribe(mutation => {
if (![ADD_CHILD, SET_PREVIEW_SIZE, FLEX_SET_DIRECTION, FLEX_SET_SPACING, SOURCE_SET_SOURCE, FLEX_SET_DISTRIBUTION, INSET_SET_INSETS].includes(mutation.type)) {
if (!layoutExercisingMutations.includes(mutation.type)) {
return;
}
store.commit(EXERCISE_LAYOUT)
Expand Down
13 changes: 12 additions & 1 deletion src/store/mutation-types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export const SELECT_COMPONENT = 'SELECT_COMPONENT'
export const ADD_CHILD = 'ADD_CHILD'
export const EMBED_IN_COMPONENT = 'EMBED_IN_COMPONENT'

export const EXERCISE_LAYOUT = 'EXERCISE_LAYOUT'
export const SET_PREVIEW_SIZE = 'SET_PREVIEW_SIZE'
Expand All @@ -10,4 +11,14 @@ export const FLEX_SET_SPACING = 'FLEX_SET_SPACING'

export const INSET_SET_INSETS = 'INSET_SET_INSETS'

export const SOURCE_SET_SOURCE = 'SOURCE_SET_SOURCE'
export const SOURCE_SET_SOURCE = 'SOURCE_SET_SOURCE'

export const layoutExercisingMutations = [
ADD_CHILD,
EMBED_IN_COMPONENT,
SET_PREVIEW_SIZE,
FLEX_SET_DIRECTION,
FLEX_SET_DISTRIBUTION,
FLEX_SET_SPACING,
INSET_SET_INSETS
];

0 comments on commit 4c1dd84

Please sign in to comment.