My periodic table composable gets cropped to the i...
# compose
k
My periodic table composable gets cropped to the initial window view for some reason. Does anyone know how to make it so it always draws the non-viewable areas as well?
Here's what my code looks like:
Copy code
@OptIn(ExperimentalComposeUiApi::class)
fun main() = application {
    Window(
        title = "Test",
        state = rememberWindowState(
            size = DpSize(1600.dp, 800.dp)
        ),
        undecorated = false,
        onCloseRequest = ::exitApplication
    ) {
        var scale by remember { mutableStateOf(1f) }
        var rotation by remember { mutableStateOf(0f) }
        var offset by remember { mutableStateOf(Offset.Zero) }
        val state = rememberTransformableState { zoomChange, offsetChange, rotationChange ->
            scale *= zoomChange
            rotation += rotationChange
            offset += offsetChange * scale
        }

        Box(modifier = Modifier
            .onRotaryScrollEvent { e ->
                println("Got scroll event: $e")
                true
            }
            .onPointerEvent(PointerEventType.Scroll) { e ->
                val event = e.changes.firstOrNull()
                if (event != null) {
                    println("scrollDelta: ${event.scrollDelta.toString()}")
                    val y = event.scrollDelta.y
                    val scaleFactor = 0.1f
                    scale = max(scale * (1 - (y * scaleFactor)), 0.5f)
                }
            }
            .graphicsLayer(
                scaleX = scale,
                scaleY = scale,
                rotationZ = rotation,
                translationX = offset.x,
                translationY = offset.y,
                clip = false
            )
            .transformable(state)
        ) {
            PeriodicTable()
        }
    }
}
k
PeriodicTable is what hides the answer to your question ;)
k
Copy code
@Composable
fun PeriodicTable() {
    Column(
        verticalArrangement = Arrangement.spacedBy(3.dp),
        modifier = Modifier
            .horizontalScroll(rememberScrollState())
    ) {
        val spaceNum = 10
        val horizontalSpacing = 3.dp
        Row(horizontalArrangement = Arrangement.spacedBy(horizontalSpacing)) {
            PeriodicItem(
                "1", "1.0080", "H", "Hydrogen", "Nonmetal"
            )
            PeriodicSpacer()
            repeat(spaceNum + 5) {
                PeriodicSpacer()
            }
            PeriodicItem(
                "2", "4.00260", "He", "Helium", "Noble Gas"
            )
        }

        Row(horizontalArrangement = Arrangement.spacedBy(horizontalSpacing)) {
            PeriodicItem(
                "3", "7.0", "Li", "Lithium", "Alkali Metal"
            )
            PeriodicItem(
                "4", "9.012183", "Be", "Beryllium", "Alkaline Earth Metal"
            )
            repeat(spaceNum) {
                PeriodicSpacer()
            }
            PeriodicItem(
                "5", "10.91", "B", "Boron", "Metalloid"
            )
            PeriodicItem(
                "6", "12.011", "C", "Carbon", "Nonmetal"
            )
            PeriodicItem(
                "7", "14.007", "N", "Nitrogen", "Nonmetal"
            )
            PeriodicItem(
                "8", "15.999", "O", "Oxygen", "Nonmetal"
            )
            PeriodicItem(
                "9", "18.99840316", "F", "Fluorine", "Halogen"
            )
            PeriodicItem(
                "10", "20.180", "Ne", "Neon", "Noble Gas"
            )
        }

        Row(horizontalArrangement = Arrangement.spacedBy(horizontalSpacing)) {
            PeriodicItem(
                "11", "22.9897693", "Na", "Sodium", "Alkali Metal"
            )
            PeriodicItem(
                "12", "24.305", "Mg", "Magnesium", "Alkaline Earth Metal"
            )
            repeat(spaceNum) {
                PeriodicSpacer()
            }
            PeriodicItem(
                "13", "26.981538", "Al", "Aluminum", "Post-Transition Metal"
            )
            PeriodicItem(
                "14", "28.085", "Si", "Silicon", "Metalloid"
            )
            PeriodicItem(
                "15", "30.97376200", "P", "Phosphorus", "Nonmetal"
            )
            PeriodicItem(
                "16", "32.07", "S", "Sulfur", "Nonmetal"
            )
            PeriodicItem(
                "17", "35.45", "Cl", "Chlorine", "Halogen"
            )
            PeriodicItem(
                "18", "39.9", "Ar", "Argon", "Noble Gas"
            )
        }

        Row(horizontalArrangement = Arrangement.spacedBy(horizontalSpacing)) {
            PeriodicItem(
                "19", "39.0983", "K", "Potassium", "Alkali Metal"
            )
            PeriodicItem(
                "20", "40.08", "Ca", "Calcium", "Alkaline Earth Metal"
            )
            PeriodicItem(
                "21", "44.95591", "Sc", "Scandium", "Transition Metal"
            )
            PeriodicItem(
                "22", "47.867", "Ti", "Titanium", "Transition Metal"
            )
            PeriodicItem(
                "23", "50.9415", "V", "Vanadium", "Transition Metal"
            )
            PeriodicItem(
                "24", "51.996", "Cr", "Chromium", "Transition Metal"
            )
            PeriodicItem(
                "25", "54.93804", "Mn", "Manganese", "Transition Metal"
            )
            PeriodicItem(
                "26", "55.84", "Fe", "Iron", "Transition Metal"
            )
            PeriodicItem(
                "27", "58.93319", "Co", "Cobalt", "Transition Metal"
            )
            PeriodicItem(
                "28", "58.693", "Ni", "Nickel", "Transition Metal"
            )
            PeriodicItem(
                "29", "63.55", "Cu", "Copper", "Transition Metal"
            )
            PeriodicItem(
                "30", "65.4", "Zn", "Zinc", "Transition Metal"
            )
            PeriodicItem(
                "31", "69.723", "Ga", "Gallium", "Post-Transition Metal"
            )
            PeriodicItem(
                "32", "72.63", "Ge", "Germanium", "Metalloid"
            )
            PeriodicItem(
                "33", "74.92159", "As", "Arsenic", "Metalloid"
            )
            PeriodicItem(
                "34", "78.97", "Se", "Selenium", "Nonmetal"
            )
            PeriodicItem(
                "35", "79.90", "Br", "Bromine", "Halogen"
            )
            PeriodicItem(
                "36", "83.80", "Kr", "Krypton", "Noble Gas"
            )
        }

        Row(horizontalArrangement = Arrangement.spacedBy(horizontalSpacing)) {
            PeriodicItem(
                "37", "85.468", "Rb", "Rubidium", "Alkali Metal"
            )
            PeriodicItem(
                "38", "87.62", "Sr", "Strontium", "Alkaline Earth Metal"
            )
            PeriodicItem(
                "39", "88.90584", "Y", "Yttrium", "Transition Metal"
            )
            PeriodicItem(
                "40", "91.22", "Zr", "Zirconium", "Transition Metal"
            )
            PeriodicItem(
                "41", "92.90637", "Nb", "Niobium", "Transition Metal"
            )
            PeriodicItem(
                "42", "95.95", "Mo", "Molybdenum", "Transition Metal"
            )
            PeriodicItem(
                "43", "96.90636", "Tc", "Technetium", "Transition Metal"
            )
            PeriodicItem(
                "44", "101.1", "Ru", "Ruthenium", "Transition Metal"
            )
            PeriodicItem(
                "45", "102.9055", "Rh", "Rhodium", "Transition Metal"
            )
            PeriodicItem(
                "46", "106.42", "Pd", "Palladium", "Transition Metal"
            )
            PeriodicItem(
                "47", "107.868", "Ag", "Silver", "Transition Metal"
            )
            PeriodicItem(
                "48", "112.41", "Cd", "Cadmium", "Transition Metal"
            )
            PeriodicItem(
                "49", "114.818", "In", "Indium", "Post-Transition Metal"
            )
            PeriodicItem(
                "50", "118.71", "Sn", "Tin", "Post-Transition Metal"
            )
            PeriodicItem(
                "51", "121.760", "Sb", "Antimony", "Metalloid"
            )
            PeriodicItem(
                "52", "127.6", "Te", "Tellurium", "Metalloid"
            )
            PeriodicItem(
                "53", "126.9045", "I", "Iodine", "Halogen"
            )
            PeriodicItem(
                "54", "131.29", "Xe", "Xenon", "Noble Gas"
            )
        }

        Row(horizontalArrangement = Arrangement.spacedBy(horizontalSpacing)) {
            PeriodicItem(
                "55", "<tel:132.9054520|132.9054520>", "Cs", "Cesium", "Alkali Metal"
            )
            PeriodicItem(
                "56", "137.33", "Ba", "Barium", "Alkaline Earth Metal"
            )
            PeriodicSpacer()
            PeriodicItem(
                "72", "178.49", "Hf", "Hafnium", "Transition Metal"
            )
            PeriodicItem(
                "73", "180.9479", "Ta", "Tantalum", "Transition Metal"
            )
            PeriodicItem(
                "74", "183.84", "W", "Tungsten", "Transition Metal"
            )
            PeriodicItem(
                "75", "186.207", "Re", "Rhenium", "Transition Metal"
            )
            PeriodicItem(
                "76", "190.2", "Os", "Osmium", "Transition Metal"
            )
            PeriodicItem(
                "77", "192.22", "Ir", "Iridium", "Transition Metal"
            )
            PeriodicItem(
                "78", "195.08", "Pt", "Platinum", "Transition Metal"
            )
            PeriodicItem(
                "79", "196.96657", "Au", "Gold", "Transition Metal"
            )
            PeriodicItem(
                "80", "200.59", "Hg", "Mercury", "Transition Metal"
            )
            PeriodicItem(
                "81", "204.383", "Tl", "Thallium", "Post-Transition Metal"
            )
            PeriodicItem(
                "82", "207", "Pb", "Lead", "Post-Transition Metal"
            )
            PeriodicItem(
                "83", "208.98040", "Bi", "Bismuth", "Post-Transition Metal"
            )
            PeriodicItem(
                "84", "208.98243", "Po", "Polonium", "Metalloid"
            )
            PeriodicItem(
                "85", "209.98715", "At", "Astatine", "Halogen"
            )
            PeriodicItem(
                "86", "222.01758", "Rn", "Radon", "Noble Gas"
            )
        }

        Row(horizontalArrangement = Arrangement.spacedBy(horizontalSpacing)) {
            PeriodicItem(
                "87", "223.01973", "Fr", "Francium", "Alkali Metal"
            )
            PeriodicItem(
                "88", "226.02541", "Ra", "Radium", "Alkaline Earth Metal"
            )
            PeriodicSpacer()
            PeriodicItem(
                "104", "267.122", "Rf", "Rutherfordium", "Transition Metal"
            )
            PeriodicItem(
                "105", "268.126", "Db", "Dubnium", "Transition Metal"
            )
            PeriodicItem(
                "106", "269.128", "Sg", "Seaborgium", "Transition Metal"
            )
            PeriodicItem(
                "107", "270.133", "Bh", "Bohrium", "Transition Metal"
            )
            PeriodicItem(
                "108", "269.1336", "Hs", "Hassium", "Transition Metal"
            )
            PeriodicItem(
                "109", "277.154", "Mt", "Meitnerium", "Transition Metal"
            )
            PeriodicItem(
                "110", "282.166", "Ds", "Darmstadtium", "Transition Metal"
            )
            PeriodicItem(
                "111", "282.169", "Rg", "Roentgenium", "Transition Metal"
            )
            PeriodicItem(
                "112", "286.179", "Cn", "Copernicium", "Transition Metal"
            )
            PeriodicItem(
                "113", "286.182", "Nh", "Nihonium", "Post-Transition Metal"
            )
            PeriodicItem(
                "114", "290.192", "Fl", "Flerovium", "Post-Transition Metal"
            )
            PeriodicItem(
                "115", "290.196", "Mc", "Moscovium", "Post-Transition Metal"
            )
            PeriodicItem(
                "116", "293.205", "Lv", "Livermorium", "Metalloid"
            )
            PeriodicItem(
                "117", "294.211", "Ts", "Tennessine", "Halogen"
            )
            PeriodicItem(
                "118", "295.216", "Og", "Oganesson", "Noble Gas"
            )
        }
        // last row ommitted (too long)
    }
Copy code
@Composable
fun PeriodicItem(
    number: String,
    atomicNumber: String,
    symbol: String,
    name: String,
    chemicalGroupBlock: String,
) {
    var atomicNumberFontSize by remember { mutableStateOf(13.sp) }
    var atomicNumberTextWidth by remember { mutableStateOf(0f) }

    var nameFontSize by remember { mutableStateOf(13.sp) }
    var nameTextWidth by remember { mutableStateOf(0f) }

    var chemicalGroupBlockFontSize by remember { mutableStateOf(13.sp) }
    var chemicalGroupBlockTextWidth by remember { mutableStateOf(0f) }

    var boxWidth by remember { mutableStateOf(0f) }

    val atomicNumberLength = atomicNumber.length
    val atomicNumberRatio = if (atomicNumberLength >= 3) 0.6 else 0.7

    Column(horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.SpaceBetween,
        modifier = periodicItemModifier(Color.Black)
            .onGloballyPositioned { layoutCoordinates ->
                // Measure the width of the Box
                boxWidth = layoutCoordinates.boundsInParent().width
            }) {
        Row(
            horizontalArrangement = Arrangement.SpaceBetween,
            verticalAlignment = Alignment.CenterVertically,
            modifier = Modifier.fillMaxWidth().padding(start = 3.dp, end = 3.dp)
        ) {
            Text(number)
            Text(atomicNumber,
                fontSize = atomicNumberFontSize,
                modifier = Modifier.onGloballyPositioned { textCoordinates ->
                atomicNumberTextWidth = textCoordinates.boundsInParent().width
                println("name: $name, $chemicalGroupBlock, boxWidth: $boxWidth, textWidth: $chemicalGroupBlockTextWidth")
                // Adjust font size if text is wider than the available box width
                if ((atomicNumberTextWidth) >= (boxWidth * atomicNumberRatio)) {
                    atomicNumberFontSize *= 0.95f  // Reduce font size by 5%
                }
            })
        }
        Text(symbol, fontSize = 25.sp, fontWeight = FontWeight.Bold)
        Text(name, fontSize = nameFontSize, fontWeight = FontWeight.SemiBold,
            maxLines = 1,
            modifier = Modifier.onGloballyPositioned { textCoordinates ->
                nameTextWidth = textCoordinates.boundsInParent().width
                if ((nameTextWidth) >= (boxWidth * 0.95)) {
                    nameFontSize *= 0.95f  // Reduce font size by 5%
                }
            })
        Text(chemicalGroupBlock, maxLines = 1,
            fontSize = chemicalGroupBlockFontSize,
            modifier = Modifier
                .onGloballyPositioned { textCoordinates ->
                    // Measure the width of the text
                    chemicalGroupBlockTextWidth = textCoordinates.boundsInParent().width
                    println("$chemicalGroupBlock, boxWidth: $boxWidth, textWidth: $chemicalGroupBlockTextWidth")
                    // Adjust font size if text is wider than the available box width
                    if ((chemicalGroupBlockTextWidth + 10) >= boxWidth) {
                        chemicalGroupBlockFontSize *= 0.95f  // Reduce font size by 5%
                    }
                })
    }
}

@Composable
fun PeriodicSpacer() {
    var boxWidth by remember { mutableStateOf(0f) }
    Column(
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.SpaceBetween,
        modifier = periodicItemModifier(Color.Transparent)
    ) {

    }
}
Interesting, this fixes it:
Copy code
@OptIn(ExperimentalComposeUiApi::class)
fun main() = application {
    Window(
        title = "Test",
        state = rememberWindowState(
            size = DpSize(1600.dp, 800.dp)
        ),
        undecorated = false,
        onCloseRequest = ::exitApplication
    ) {
        var scale by remember { mutableStateOf(1f) }
        var rotation by remember { mutableStateOf(0f) }
        var offset by remember { mutableStateOf(Offset.Zero) }
        val state = rememberTransformableState { zoomChange, offsetChange, rotationChange ->
            scale *= zoomChange
            rotation += rotationChange
            offset += offsetChange * scale
        }

        val stateVertical = rememberScrollState(0)

        Box(modifier = Modifier
            .fillMaxSize()
            .onRotaryScrollEvent { e ->
                println("Got scroll event: $e")
                true
            }
            .onPointerEvent(PointerEventType.Scroll) { e ->
                val event = e.changes.firstOrNull()
                if (event != null) {
                    println("scrollDelta: ${event.scrollDelta.toString()}")
                    val y = event.scrollDelta.y
                    val scaleFactor = 0.1f
                    scale = max(scale * (1 - (y * scaleFactor)), 0.5f)
                }
            }
            .verticalScroll(stateVertical, enabled = false)
            .graphicsLayer(
                scaleX = scale,
                scaleY = scale,
                rotationZ = rotation,
                translationX = offset.x,
                translationY = offset.y,
                clip = false
            )
            .transformable(state)
        ) {
            PeriodicTable()
        }
    }
}
20241101-0441-44.8023185.mp4
a
Modifier.graphicsLayer()
only changes how the content is drawn. It doesn't change the layout size. What you actually need is likely a
.wrapContentSize(align = Alignment.TopStart, unbounded = true)
before
.graphicsLayer()
. Also please don't post long code snippets to the channel.
👍 1
k
ok my b