@@ -20,26 +20,21 @@ package com.vaticle.typedb.studio.view.output
2020
2121import androidx.compose.foundation.Canvas
2222import androidx.compose.foundation.background
23- import androidx.compose.foundation.clickable
2423import androidx.compose.foundation.gestures.Orientation
2524import androidx.compose.foundation.gestures.detectDragGestures
2625import androidx.compose.foundation.gestures.detectTapGestures
2726import androidx.compose.foundation.gestures.rememberScrollableState
2827import androidx.compose.foundation.gestures.scrollable
29- import androidx.compose.foundation.layout.Arrangement
3028import androidx.compose.foundation.layout.Box
3129import androidx.compose.foundation.layout.Column
3230import androidx.compose.foundation.layout.Row
33- import androidx.compose.foundation.layout.Spacer
3431import androidx.compose.foundation.layout.fillMaxHeight
3532import androidx.compose.foundation.layout.fillMaxSize
3633import androidx.compose.foundation.layout.fillMaxWidth
3734import androidx.compose.foundation.layout.height
3835import androidx.compose.foundation.layout.offset
3936import androidx.compose.foundation.layout.padding
40- import androidx.compose.foundation.layout.requiredWidth
4137import androidx.compose.foundation.layout.size
42- import androidx.compose.foundation.layout.width
4338import androidx.compose.runtime.Composable
4439import androidx.compose.runtime.LaunchedEffect
4540import androidx.compose.runtime.getValue
@@ -50,7 +45,6 @@ import androidx.compose.runtime.withFrameMillis
5045import androidx.compose.ui.Alignment
5146import androidx.compose.ui.ExperimentalComposeUiApi
5247import androidx.compose.ui.Modifier
53- import androidx.compose.ui.draw.rotate
5448import androidx.compose.ui.geometry.CornerRadius
5549import androidx.compose.ui.geometry.Offset
5650import androidx.compose.ui.geometry.Rect
@@ -60,8 +54,6 @@ import androidx.compose.ui.graphics.drawscope.DrawScope
6054import androidx.compose.ui.graphics.drawscope.Stroke
6155import androidx.compose.ui.graphics.drawscope.withTransform
6256import androidx.compose.ui.graphics.graphicsLayer
63- import androidx.compose.ui.input.pointer.PointerIconDefaults
64- import androidx.compose.ui.input.pointer.pointerHoverIcon
6557import androidx.compose.ui.input.pointer.pointerInput
6658import androidx.compose.ui.input.pointer.pointerMoveFilter
6759import androidx.compose.ui.layout.LayoutCoordinates
@@ -78,7 +70,6 @@ import androidx.compose.ui.unit.Dp
7870import androidx.compose.ui.unit.DpOffset
7971import androidx.compose.ui.unit.DpSize
8072import androidx.compose.ui.unit.dp
81- import androidx.compose.ui.unit.sp
8273import androidx.compose.ui.unit.toSize
8374import androidx.compose.ui.zIndex
8475import com.vaticle.force.graph.api.Simulation
@@ -130,11 +121,13 @@ import com.vaticle.typedb.studio.view.common.geometry.Geometry.rectIncomingLineI
130121import com.vaticle.typedb.studio.view.common.geometry.Geometry.sweepAngle
131122import com.vaticle.typedb.studio.view.common.theme.Color
132123import com.vaticle.typedb.studio.view.common.theme.Theme
124+ import com.vaticle.typedb.studio.view.material.Browser
133125import com.vaticle.typedb.studio.view.material.Form
134126import com.vaticle.typedb.studio.view.material.Frame
135127import com.vaticle.typedb.studio.view.material.Icon
136128import com.vaticle.typedb.studio.view.material.Separator
137129import com.vaticle.typedb.studio.view.material.Table
130+ import com.vaticle.typedb.studio.view.material.Tabs
138131import com.vaticle.typedb.studio.view.output.GraphOutput.State.Graph.Physics.Constants.COLLIDE_RADIUS
139132import com.vaticle.typedb.studio.view.output.GraphOutput.State.Graph.Physics.Constants.CURVE_COLLIDE_RADIUS
140133import com.vaticle.typedb.studio.view.output.GraphOutput.State.Graph.Physics.Constants.CURVE_COMPRESSION_POWER
@@ -1690,7 +1683,7 @@ internal object GraphOutput : RunOutput() {
16901683 minSize = BrowserArea .MIN_WIDTH ,
16911684 initSize = Either .first(
16921685 state.browserAreaState?.let { if (it.browser.isOpen) it.paneState.size else null }
1693- ? : BrowserArea . SIDE_TAB_WIDTH
1686+ ? : Tabs . Vertical . WIDTH
16941687 ),
16951688 initFreeze = state.browserAreaState?.browser?.isOpen != true
16961689 ) { BrowserArea .Layout (state, it) }
@@ -1918,98 +1911,26 @@ internal object GraphOutput : RunOutput() {
19181911 }
19191912 }
19201913
1921- // TODO: copied from browser/Browser.kt on 23/05/2022
1922- abstract class Browser (
1923- private val areaState : BrowserArea .State , internal val order : Int , initOpen : Boolean = false
1924- ) {
1925-
1926- companion object {
1927- internal val MIN_HEIGHT = 80 .dp
1928- }
1929-
1930- internal abstract val label: String
1931- internal abstract val icon: Icon .Code
1932- internal abstract val buttons: List <Form .IconButtonArg >
1933-
1934- internal var isOpen: Boolean by mutableStateOf(initOpen)
1935-
1936- @Composable
1937- abstract fun BrowserLayout ()
1938-
1939- fun toggle () {
1940- isOpen = ! isOpen
1941- areaState.mayUpdatePaneState()
1942- }
1943-
1944- @Composable
1945- internal fun Layout () {
1946- Column {
1947- Bar ()
1948- Separator .Horizontal ()
1949- Box (modifier = Modifier .weight(1f )) { BrowserLayout () }
1950- }
1951- }
1952-
1953- @Composable
1954- private fun Bar () {
1955- Row (
1956- modifier = Modifier .fillMaxWidth().height(Theme .PANEL_BAR_HEIGHT )
1957- .background(color = Theme .studio.surface),
1958- verticalAlignment = Alignment .CenterVertically
1959- ) {
1960- Spacer (Modifier .width(Theme .PANEL_BAR_SPACING ))
1961- Icon .Render (icon = icon)
1962- Spacer (Modifier .width(Theme .PANEL_BAR_SPACING ))
1963- Form .Text (value = label)
1964- Spacer (Modifier .weight(1f ))
1965- Buttons (* buttons.toTypedArray(), isActive = true )
1966- Buttons (Form .IconButtonArg (Icon .Code .XMARK ) { toggle() }, isActive = true )
1967- }
1968- }
1969-
1970- @Composable
1971- private fun Buttons (vararg buttons : Form .IconButtonArg , isActive : Boolean ) {
1972- buttons.forEach {
1973- Form .IconButton (
1974- icon = it.icon,
1975- hoverIcon = it.hoverIcon,
1976- modifier = Modifier .size(Theme .PANEL_BAR_HEIGHT ),
1977- iconColor = it.color(),
1978- iconHoverColor = it.hoverColor?.invoke(),
1979- disabledColor = it.disabledColor?.invoke(),
1980- bgColor = androidx.compose.ui.graphics.Color .Transparent ,
1981- roundedCorners = Theme .RoundedCorners .NONE ,
1982- enabled = isActive && it.enabled,
1983- tooltip = it.tooltip,
1984- onClick = it.onClick,
1985- )
1986- }
1987- }
1988- }
1989-
19901914 // TODO: copied from browser/BrowserArea.kt on 23/05/2022
19911915 object BrowserArea {
19921916
19931917 val WIDTH = 300 .dp
19941918 val MIN_WIDTH = 150 .dp
1995- val SIDE_TAB_WIDTH = 22 .dp
1996- private val SIDE_TAB_HEIGHT = 100 .dp
1997- private val SIDE_TAB_SPACING = 8 .dp
1998- private val ICON_SIZE = 10 .sp
1999- private val TAB_OFFSET = 40 .dp
20001919
20011920 class State constructor(state : GraphOutput .State , var paneState : Frame .PaneState ) {
20021921
20031922 private var unfreezeSize: Dp by mutableStateOf(WIDTH )
2004- internal val browser = PreviewBrowser (state, this , 0 , false )
1923+ internal val browser = PreviewBrowser (state, 0 , false ) { mayUpdatePaneState() }
20051924 internal var isOpen
20061925 get() = browser.isOpen
2007- set(value) { browser.isOpen = value }
1926+ set(value) {
1927+ browser.isOpen = value
1928+ }
20081929
20091930 fun mayUpdatePaneState () {
20101931 if (! isOpen) {
20111932 unfreezeSize = paneState.size
2012- paneState.freeze(SIDE_TAB_WIDTH )
1933+ paneState.freeze(Tabs . Vertical . WIDTH )
20131934 } else if (paneState.isFrozen) paneState.unfreeze(unfreezeSize)
20141935 }
20151936 }
@@ -2035,61 +1956,40 @@ internal object GraphOutput : RunOutput() {
20351956 )
20361957 Separator .Vertical ()
20371958 }
2038- Column (Modifier .width(SIDE_TAB_WIDTH ), verticalArrangement = Arrangement .Top ) {
2039- Tab (areaState.browser)
2040- }
2041- }
2042- }
2043-
2044- @OptIn(ExperimentalComposeUiApi ::class )
2045- @Composable
2046- private fun Tab (browser : Browser ) {
2047- @Composable
2048- fun bgColor (): androidx.compose.ui.graphics.Color =
2049- if (browser.isOpen) Theme .studio.surface else Theme .studio.backgroundDark
2050- Box (
2051- modifier = Modifier
2052- .fillMaxWidth()
2053- .height(SIDE_TAB_HEIGHT )
2054- .pointerHoverIcon(PointerIconDefaults .Hand )
2055- .clickable { browser.toggle() }
2056- ) {
2057- Row (
2058- verticalAlignment = Alignment .CenterVertically ,
2059- modifier = Modifier .requiredWidth(SIDE_TAB_HEIGHT )
2060- .rotate(90f )
2061- .offset(x = TAB_OFFSET )
2062- .background(color = bgColor())
2063- ) {
2064- Spacer (modifier = Modifier .weight(1f ))
2065- Icon .Render (icon = browser.icon, size = ICON_SIZE )
2066- Spacer (modifier = Modifier .width(SIDE_TAB_SPACING ))
2067- Form .Text (value = browser.label)
2068- Spacer (modifier = Modifier .weight(1f ))
2069- }
1959+ Tabs .Vertical .Layout (
1960+ tabs = listOf (areaState.browser),
1961+ position = Tabs .Vertical .Position .RIGHT ,
1962+ labelFn = { it.label },
1963+ iconFn = { it.icon },
1964+ isActiveFn = { it.isOpen },
1965+ ) { it.toggle() }
20701966 }
2071- Separator .Horizontal ()
20721967 }
20731968 }
20741969
2075- class PreviewBrowser (private val state : State , areaState : BrowserArea .State , order : Int , initOpen : Boolean ) :
2076- Browser (areaState, order, initOpen) {
1970+ class PreviewBrowser constructor(
1971+ private val state : State ,
1972+ order : Int ,
1973+ isOpen : Boolean ,
1974+ onUpdatePane : () -> Unit
1975+ ) : Browser(isOpen, order, onUpdatePane) {
20771976
20781977 override val label: String = Label .PREVIEW
20791978 override val icon: Icon .Code = Icon .Code .EYE
1979+ override val isActive: Boolean = true
20801980 override var buttons: List <Form .IconButtonArg > = emptyList()
20811981
20821982 private val placeholderPadding = 20 .dp
20831983
20841984 @Composable
20851985 override fun BrowserLayout () {
20861986 val focusedVertex = state.interactions.focusedVertex
2087- if (focusedVertex == null ) PlaceholderText ()
1987+ if (focusedVertex == null ) SelectVertexMessage ()
20881988 else ConceptPreview (focusedVertex.concept).Layout ()
20891989 }
20901990
20911991 @Composable
2092- private fun PlaceholderText () {
1992+ private fun SelectVertexMessage () {
20931993 Box (Modifier .fillMaxSize().padding(placeholderPadding), Alignment .Center ) {
20941994 Form .Text (Label .GRAPH_CONCEPT_PREVIEW_PLACEHOLDER , align = TextAlign .Center , softWrap = true )
20951995 }
0 commit comments