Skip to content

Commit a815983

Browse files
committed
fixing bottom border header bug
1 parent 7b30f5a commit a815983

File tree

3 files changed

+64
-17
lines changed
  • core
    • generated-sources/src
      • main/kotlin/org/jetbrains/kotlinx/dataframe/io
      • test/kotlin/org/jetbrains/kotlinx/dataframe/rendering
    • src/main/kotlin/org/jetbrains/kotlinx/dataframe/io

3 files changed

+64
-17
lines changed

core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/io/html.kt

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ public fun AnyFrame.toStaticHtml(
190190
configuration: DisplayConfiguration = DisplayConfiguration.DEFAULT,
191191
cellRenderer: CellRenderer = DefaultCellRenderer,
192192
includeCss: Boolean = true,
193+
openNestedDfs: Boolean = false,
193194
): DataFrameHtmlData {
194195
val df = this
195196
val id = "static_df_${nextTableId()}"
@@ -241,15 +242,20 @@ public fun AnyFrame.toStaticHtml(
241242
when (cellValue) {
242243
// uses the <details> and <summary> to create a collapsible cell for dataframes
243244
is AnyFrame ->
244-
emitTag("details") {
245+
emitTag("details", if (openNestedDfs) "open" else "") {
245246
emitTag("summary") {
246247
append("DataFrame [${cellValue.size}]")
247248
}
248249
// add the dataframe as a nested table limiting the number of rows if needed
249250
// CSS will not be included here, as it is already included in the main table
250251
append(
251252
cellValue.take(nestedRowsLimit ?: Int.MAX_VALUE)
252-
.toStaticHtml(configuration, cellRenderer, includeCss = false)
253+
.toStaticHtml(
254+
configuration,
255+
cellRenderer,
256+
includeCss = false,
257+
openNestedDfs = openNestedDfs
258+
)
253259
.body
254260
)
255261
val size = cellValue.rowsCount()
@@ -330,8 +336,11 @@ private data class ColumnWithPathWithBorder<T>(
330336
)
331337

332338
/** Returns the depth of the most-nested column in this df/group, starting at 0 */
333-
internal fun AnyFrame.maxDepth(): Int =
334-
getColumnsWithPaths { all().rec() }.maxOfOrNull { it.depth } ?: 0
339+
internal fun AnyFrame.maxDepth(startingAt: Int = 0): Int =
340+
columns().maxOfOrNull {
341+
if (it is ColumnGroup<*>) it.maxDepth(startingAt + 1)
342+
else startingAt
343+
} ?: startingAt
335344

336345
/** Returns the max number of columns needed to display this column flattened */
337346
internal fun BaseColumn<*>.maxWidth(): Int =
@@ -356,7 +365,13 @@ private fun AnyFrame.getColumnsHeaderGrid(): List<List<ColumnWithPathWithBorder<
356365
val maxDepth = maxDepth()
357366
val maxWidth = colGroup.maxWidth()
358367
val matrix =
359-
MutableList(maxDepth + 1) { MutableList(maxWidth) { ColumnWithPathWithBorder<Any?>() } }
368+
MutableList(maxDepth + 1) { depth ->
369+
MutableList(maxWidth) {
370+
// already adding bottom borders for the last row
371+
val borders = if (depth == maxDepth) setOf(Border.BOTTOM) else emptySet()
372+
ColumnWithPathWithBorder<Any?>(borders = borders)
373+
}
374+
}
360375

361376
fun ColumnWithPath<*>.addChildren(depth: Int = 0, breadth: Int = 0) {
362377
var breadth = breadth
@@ -370,9 +385,6 @@ private fun AnyFrame.getColumnsHeaderGrid(): List<List<ColumnWithPathWithBorder<
370385
if (i == 0 && breadth != 0) borders += Border.LEFT
371386
if (i == lastIndex && breadth != maxWidth - 1) borders += Border.RIGHT
372387

373-
// draw bottom border if at max depth
374-
if (depth == maxDepth) borders += Border.BOTTOM
375-
376388
if (borders.isNotEmpty()) {
377389
// draw borders in other cells
378390
// from depth - 1 (to include not just the children but the current cell too)

core/generated-sources/src/test/kotlin/org/jetbrains/kotlinx/dataframe/rendering/RenderingTests.kt

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,13 @@ package org.jetbrains.kotlinx.dataframe.rendering
33
import io.kotest.matchers.shouldBe
44
import io.kotest.matchers.string.shouldContain
55
import io.kotest.matchers.string.shouldNotContain
6+
import org.jetbrains.kotlinx.dataframe.DataFrame
67
import org.jetbrains.kotlinx.dataframe.api.add
8+
import org.jetbrains.kotlinx.dataframe.api.asColumnGroup
79
import org.jetbrains.kotlinx.dataframe.api.columnOf
810
import org.jetbrains.kotlinx.dataframe.api.dataFrameOf
911
import org.jetbrains.kotlinx.dataframe.api.emptyDataFrame
12+
import org.jetbrains.kotlinx.dataframe.api.frameColumn
1013
import org.jetbrains.kotlinx.dataframe.api.group
1114
import org.jetbrains.kotlinx.dataframe.api.into
1215
import org.jetbrains.kotlinx.dataframe.api.move
@@ -16,13 +19,20 @@ import org.jetbrains.kotlinx.dataframe.io.DisplayConfiguration
1619
import org.jetbrains.kotlinx.dataframe.io.escapeHTML
1720
import org.jetbrains.kotlinx.dataframe.io.formatter
1821
import org.jetbrains.kotlinx.dataframe.io.maxDepth
22+
import org.jetbrains.kotlinx.dataframe.io.maxWidth
1923
import org.jetbrains.kotlinx.dataframe.io.print
24+
import org.jetbrains.kotlinx.dataframe.io.read
2025
import org.jetbrains.kotlinx.dataframe.io.renderToString
2126
import org.jetbrains.kotlinx.dataframe.io.renderToStringTable
2227
import org.jetbrains.kotlinx.dataframe.io.toHTML
28+
import org.jetbrains.kotlinx.dataframe.io.toStaticHtml
2329
import org.jetbrains.kotlinx.dataframe.jupyter.DefaultCellRenderer
2430
import org.jetbrains.kotlinx.dataframe.jupyter.RenderedContent
2531
import org.jetbrains.kotlinx.dataframe.samples.api.TestBase
32+
import org.jetbrains.kotlinx.dataframe.samples.api.firstName
33+
import org.jetbrains.kotlinx.dataframe.samples.api.lastName
34+
import org.jetbrains.kotlinx.dataframe.samples.api.name
35+
import org.jetbrains.kotlinx.dataframe.samples.api.secondName
2636
import org.jsoup.Jsoup
2737
import org.junit.Test
2838
import java.net.URL
@@ -162,6 +172,19 @@ class RenderingTests : TestBase() {
162172

163173
@Test
164174
fun `max width`() {
165-
// TODO
175+
dfGroup.asColumnGroup("").maxWidth() shouldBe 8
176+
dfGroup.name.maxWidth() shouldBe 4
177+
dfGroup.name.firstName.maxWidth() shouldBe 3
178+
dfGroup.name.lastName.maxWidth() shouldBe 1
179+
dfGroup.name.firstName.secondName.maxWidth() shouldBe 1
180+
}
181+
182+
@Test
183+
fun `test static rendering TODO temp`() {
184+
val df = DataFrame.read("https://raw.githubusercontent.com/Kotlin/dataframe/master/data/jetbrains.json")
185+
186+
// df.toHTML().openInBrowser()
187+
df.toStaticHtml(openNestedDfs = true).copy(script = "").openInBrowser()
188+
// df.get(frameColumn("repos")).get(0).toStaticHtml(openNestedDfs = false).copy(script = "").openInBrowser()
166189
}
167190
}

core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/io/html.kt

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ public fun AnyFrame.toStaticHtml(
190190
configuration: DisplayConfiguration = DisplayConfiguration.DEFAULT,
191191
cellRenderer: CellRenderer = DefaultCellRenderer,
192192
includeCss: Boolean = true,
193+
openNestedDfs: Boolean = false,
193194
): DataFrameHtmlData {
194195
val df = this
195196
val id = "static_df_${nextTableId()}"
@@ -241,15 +242,20 @@ public fun AnyFrame.toStaticHtml(
241242
when (cellValue) {
242243
// uses the <details> and <summary> to create a collapsible cell for dataframes
243244
is AnyFrame ->
244-
emitTag("details") {
245+
emitTag("details", if (openNestedDfs) "open" else "") {
245246
emitTag("summary") {
246247
append("DataFrame [${cellValue.size}]")
247248
}
248249
// add the dataframe as a nested table limiting the number of rows if needed
249250
// CSS will not be included here, as it is already included in the main table
250251
append(
251252
cellValue.take(nestedRowsLimit ?: Int.MAX_VALUE)
252-
.toStaticHtml(configuration, cellRenderer, includeCss = false)
253+
.toStaticHtml(
254+
configuration,
255+
cellRenderer,
256+
includeCss = false,
257+
openNestedDfs = openNestedDfs
258+
)
253259
.body
254260
)
255261
val size = cellValue.rowsCount()
@@ -330,8 +336,11 @@ private data class ColumnWithPathWithBorder<T>(
330336
)
331337

332338
/** Returns the depth of the most-nested column in this df/group, starting at 0 */
333-
internal fun AnyFrame.maxDepth(): Int =
334-
getColumnsWithPaths { all().rec() }.maxOfOrNull { it.depth } ?: 0
339+
internal fun AnyFrame.maxDepth(startingAt: Int = 0): Int =
340+
columns().maxOfOrNull {
341+
if (it is ColumnGroup<*>) it.maxDepth(startingAt + 1)
342+
else startingAt
343+
} ?: startingAt
335344

336345
/** Returns the max number of columns needed to display this column flattened */
337346
internal fun BaseColumn<*>.maxWidth(): Int =
@@ -356,7 +365,13 @@ private fun AnyFrame.getColumnsHeaderGrid(): List<List<ColumnWithPathWithBorder<
356365
val maxDepth = maxDepth()
357366
val maxWidth = colGroup.maxWidth()
358367
val matrix =
359-
MutableList(maxDepth + 1) { MutableList(maxWidth) { ColumnWithPathWithBorder<Any?>() } }
368+
MutableList(maxDepth + 1) { depth ->
369+
MutableList(maxWidth) {
370+
// already adding bottom borders for the last row
371+
val borders = if (depth == maxDepth) setOf(Border.BOTTOM) else emptySet()
372+
ColumnWithPathWithBorder<Any?>(borders = borders)
373+
}
374+
}
360375

361376
fun ColumnWithPath<*>.addChildren(depth: Int = 0, breadth: Int = 0) {
362377
var breadth = breadth
@@ -370,9 +385,6 @@ private fun AnyFrame.getColumnsHeaderGrid(): List<List<ColumnWithPathWithBorder<
370385
if (i == 0 && breadth != 0) borders += Border.LEFT
371386
if (i == lastIndex && breadth != maxWidth - 1) borders += Border.RIGHT
372387

373-
// draw bottom border if at max depth
374-
if (depth == maxDepth) borders += Border.BOTTOM
375-
376388
if (borders.isNotEmpty()) {
377389
// draw borders in other cells
378390
// from depth - 1 (to include not just the children but the current cell too)

0 commit comments

Comments
 (0)