Skip to content

Commit

Permalink
implement vertical align
Browse files Browse the repository at this point in the history
  • Loading branch information
raimohanska committed Sep 17, 2023
1 parent 2e259c1 commit afea769
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 25 deletions.
35 changes: 32 additions & 3 deletions common/src/domain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -629,8 +629,9 @@ export function getAlign(item: TextItem) {
}

export type HorizontalAlign = "left" | "center" | "right"
export function getHorizontalAlign(item: TextItem): HorizontalAlign {
switch (getAlign(item)) {

export function getHorizontalAlign(align: Align): HorizontalAlign {
switch (align) {
case "TL":
case "ML":
case "BL":
Expand All @@ -644,11 +645,39 @@ export function getHorizontalAlign(item: TextItem): HorizontalAlign {
case "BR":
return "right"
}
console.log("Unknown align", getAlign(item))
console.log("Unknown align", align)
return "center"
}

export type VerticalAlign = "top" | "middle" | "bottom"

export function getVerticalAlign(align: Align): VerticalAlign {
switch (align) {
case "TL":
case "TC":
case "TR":
return "top"
case "ML":
case "MC":
case "MR":
return "middle"
case "BL":
case "BC":
case "BR":
return "bottom"
}
console.log("Unknown align", align)
return "middle"
}

export function setHorizontalAlign<I extends TextItem>(item: I, a: HorizontalAlign): I {
const letter = a === "left" ? "L" : a === "center" ? "C" : "R"
const align = `${getAlign(item)[0]}${letter}`
return { ...item, align }
}

export function setVerticalAlign<I extends TextItem>(item: I, a: VerticalAlign): I {
const letter = a === "top" ? "T" : a === "middle" ? "M" : "B"
const align = `${letter}${getAlign(item)[1]}`
return { ...item, align }
}
21 changes: 19 additions & 2 deletions frontend/src/board/ItemView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@ import {
BoardHistoryEntry,
canWrite,
Connection,
getAlign,
getHorizontalAlign,
getItemBackground,
getItemIds,
getItemShape,
getVerticalAlign,
Id,
isTextItem,
Item,
Expand Down Expand Up @@ -124,6 +126,7 @@ export const ItemView = ({
position: "absolute",
padding: itemPadding(i),
justifyContent: getJustifyContent(i),
alignItems: getAlignItems(i),
textAlign: getTextAlign(i),
}
})}
Expand Down Expand Up @@ -199,7 +202,7 @@ export const ItemView = ({

function getJustifyContent(item: Item) {
if (isTextItem(item)) {
switch (getHorizontalAlign(item)) {
switch (getHorizontalAlign(getAlign(item))) {
case "left":
return "flex-start"
case "center":
Expand All @@ -211,9 +214,23 @@ function getJustifyContent(item: Item) {
return null
}

function getAlignItems(item: Item) {
if (isTextItem(item)) {
switch (getVerticalAlign(getAlign(item))) {
case "top":
return "flex-start"
case "middle":
return "center"
case "bottom":
return "flex-end"
}
}
return null
}

function getTextAlign(item: Item) {
if (isTextItem(item)) {
return getHorizontalAlign(item)
return getHorizontalAlign(getAlign(item))
}
return null
}
79 changes: 59 additions & 20 deletions frontend/src/board/contextmenu/textAlignments.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,26 @@
import { HarmajaOutput, h } from "harmaja"
import * as L from "lonna"
import {
Align,
Color,
HorizontalAlign,
Item,
TextItem,
VerticalAlign,
getAlign,
getHorizontalAlign,
getVerticalAlign,
isTextItem,
setHorizontalAlign,
setVerticalAlign,
} from "../../../../common/src/domain"
import {
TextAlignHorizontalCenterIcon,
TextAlignHorizontalLeftIcon,
TextAlignHorizontalRightIcon,
TextAlignVerticalBottomIcon,
TextAlignVerticalMiddleIcon,
TextAlignVerticalTopIcon,
} from "../../components/Icons"
import { black } from "../../components/UIColors"
import { SubmenuProps } from "./ContextMenuView"
Expand All @@ -20,48 +29,78 @@ export function textAlignmentsMenu({ board, focusedItems, dispatch, submenu }: S
const textItems = L.view(focusedItems, (items) => items.items.filter(isTextItem))
const allText = L.view(focusedItems, textItems, (f, t) => f.items.length > 0 && t.length === f.items.length)

const currentAlign = L.view(focusedItems, (f) => {
const items = f.items
const align = getHA(items[0])
for (let i = 1; i < items.length; i++) {
if (getHA(items[i]) !== align) {
return null // If not all share the same, return null
}
}
return align
const currentHAlign = L.view(focusedItems, (f) => {
return getIfSame(f.items, getHorizontalAlign, "left")
})

const currentVAlign = L.view(focusedItems, (f) => {
return getIfSame(f.items, getVerticalAlign, "top")
})

function setAlign(align: HorizontalAlign) {
function setAlign(modifyAlign: (i: TextItem) => TextItem) {
focusedItems.get()
const b = board.get()
const updated = focusedItems.get().items.map((i) => (isTextItem(i) ? setHorizontalAlign(i, align) : i))
const updated = focusedItems.get().items.map((i) => (isTextItem(i) ? modifyAlign(i) : i))
dispatch({ action: "item.update", boardId: b.id, items: updated })
}

return L.view(allText, currentAlign, (all, ca) => {
return L.view(allText, currentHAlign, currentVAlign, (all, ha, va) => {
return !all
? []
: [
<div className="icon-group text-align">
<span
className="icon"
onClick={() => setAlign(aligns[(aligns.indexOf(ca ?? "left") + 1) % aligns.length])}
onClick={() => {
const hAlign: HorizontalAlign = hAligns[(hAligns.indexOf(ha) + 1) % hAligns.length]
setAlign((i) => setHorizontalAlign(i, hAlign))
}}
title="Align left"
>
{icons[ca ?? "left"](black)}
{horizontalIcons[ha](black)}
</span>
</div>,
<div className="icon-group text-align">
<span
className="icon"
onClick={() => {
const vAlign: VerticalAlign = vAligns[(vAligns.indexOf(va) + 1) % vAligns.length]
setAlign((i) => setVerticalAlign(i, vAlign))
}}
title="Align left"
>
{verticalIcons[va](black)}
</span>
</div>,
]
})
}

function getHA(item: Item | null) {
return item && isTextItem(item) ? getHorizontalAlign(item) : null
}

const icons: Record<HorizontalAlign, (color: Color) => HarmajaOutput> = {
const horizontalIcons: Record<HorizontalAlign, (color: Color) => HarmajaOutput> = {
left: (color: Color) => <TextAlignHorizontalLeftIcon color={color} />,
center: (color: Color) => <TextAlignHorizontalCenterIcon color={color} />,
right: (color: Color) => <TextAlignHorizontalRightIcon color={color} />,
}
const aligns: HorizontalAlign[] = ["left", "center", "right"]
const verticalIcons: Record<VerticalAlign, (color: Color) => HarmajaOutput> = {
top: (color: Color) => <TextAlignVerticalTopIcon color={color} />,
middle: (color: Color) => <TextAlignVerticalMiddleIcon color={color} />,
bottom: (color: Color) => <TextAlignVerticalBottomIcon color={color} />,
}
const hAligns: HorizontalAlign[] = ["left", "center", "right"]
const vAligns: VerticalAlign[] = ["top", "middle", "bottom"]

function getIfSame<A>(items: Item[], get: (item: Align) => A | null, defaultValue: A) {
let align: A | null = null
items.forEach((item) => {})
for (let i = 0; i < items.length; i++) {
const item = items[i]
const itemAlign = isTextItem(item) ? get(getAlign(item)) : null
if (align != null && itemAlign !== align) {
// If not all share the same, exit
align = null
break
}
align = itemAlign
}
return align ?? defaultValue
}
18 changes: 18 additions & 0 deletions frontend/src/components/Icons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,24 @@ export const TextAlignHorizontalCenterIcon = ({ color }: { color: Color }) => (
</svg>
)

export const TextAlignVerticalBottomIcon = ({ color }: { color: Color }) => (
<svg viewBox="0 0 24 24">
<path fill={color} d="M16 13h-3V3h-2v10H8l4 4 4-4zM4 19v2h16v-2H4z"></path>
</svg>
)

export const TextAlignVerticalMiddleIcon = ({ color }: { color: Color }) => (
<svg viewBox="0 0 24 24">
<path fill={color} d="M8 19h3v4h2v-4h3l-4-4-4 4zm8-14h-3V1h-2v4H8l4 4 4-4zM4 11v2h16v-2H4z"></path>
</svg>
)

export const TextAlignVerticalTopIcon = ({ color }: { color: Color }) => (
<svg viewBox="0 0 24 24">
<path fill={color} d="M8 11h3v10h2V11h3l-4-4-4 4zM4 3v2h16V3H4z"></path>
</svg>
)

export const AlignHorizontalLeftIcon = () => (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path d="M4 22H2V2h2v20zM22 7H6v3h16V7zm-6 7H6v3h10v-3z" />
Expand Down

0 comments on commit afea769

Please sign in to comment.