Skip to content

Commit 2be6c10

Browse files
Automated commit of generated code
1 parent afe6991 commit 2be6c10

File tree

7 files changed

+372
-15
lines changed

7 files changed

+372
-15
lines changed

core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/format.kt

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -566,7 +566,7 @@ public fun <T, C> DataFrame<T>.format(vararg columns: KProperty<C>): FormatClaus
566566
* If unspecified, all columns will be formatted.
567567
*/
568568
public fun <T, C> FormattedFrame<T>.format(columns: ColumnsSelector<T, C>): FormatClause<T, C> =
569-
FormatClause(df, columns, formatter)
569+
FormatClause(df, columns, formatter, oldHeaderFormatter = headerFormatter)
570570

571571
/**
572572
* Formats the specified [columns] or cells within this dataframe such that
@@ -702,7 +702,13 @@ public fun <T> FormattedFrame<T>.format(): FormatClause<T, Any?> = FormatClause(
702702
* Check out the full [Grammar][FormatDocs.Grammar].
703703
*/
704704
public fun <T, C> FormatClause<T, C>.where(filter: RowValueFilter<T, C>): FormatClause<T, C> =
705-
FormatClause(filter = this.filter and filter, df = df, columns = columns, oldFormatter = oldFormatter)
705+
FormatClause(
706+
filter = this.filter and filter,
707+
df = df,
708+
columns = columns,
709+
oldFormatter = oldFormatter,
710+
oldHeaderFormatter = oldHeaderFormatter,
711+
)
706712

707713
/**
708714
* Only format the selected columns at given row indices.
@@ -1173,7 +1179,11 @@ public typealias CellFormatter<C> = FormattingDsl.(cell: C) -> CellAttributes?
11731179
*
11741180
* You can apply further formatting to this [FormattedFrame] by calling [format()][FormattedFrame.format] once again.
11751181
*/
1176-
public class FormattedFrame<T>(internal val df: DataFrame<T>, internal val formatter: RowColFormatter<T, *>? = null) {
1182+
public class FormattedFrame<T>(
1183+
internal val df: DataFrame<T>,
1184+
internal val formatter: RowColFormatter<T, *>? = null,
1185+
internal val headerFormatter: HeaderColFormatter<*>? = null,
1186+
) {
11771187

11781188
/**
11791189
* Returns a [DataFrameHtmlData] without additional definitions.
@@ -1219,7 +1229,10 @@ public class FormattedFrame<T>(internal val df: DataFrame<T>, internal val forma
12191229
/** Applies this formatter to the given [configuration] and returns a new instance. */
12201230
@Suppress("UNCHECKED_CAST")
12211231
public fun getDisplayConfiguration(configuration: DisplayConfiguration): DisplayConfiguration =
1222-
configuration.copy(cellFormatter = formatter as RowColFormatter<*, *>?)
1232+
configuration.copy(
1233+
cellFormatter = formatter as RowColFormatter<*, *>?,
1234+
headerFormatter = headerFormatter,
1235+
)
12231236
}
12241237

12251238
/**
@@ -1251,6 +1264,7 @@ public class FormatClause<T, C>(
12511264
internal val columns: ColumnsSelector<T, C> = { all().cast() },
12521265
internal val oldFormatter: RowColFormatter<T, C>? = null,
12531266
internal val filter: RowValueFilter<T, C> = { true },
1267+
internal val oldHeaderFormatter: HeaderColFormatter<*>? = null,
12541268
) {
12551269
override fun toString(): String =
12561270
"FormatClause(df=$df, columns=$columns, oldFormatter=$oldFormatter, filter=$filter)"
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
package org.jetbrains.kotlinx.dataframe.api
2+
3+
import org.jetbrains.kotlinx.dataframe.ColumnsSelector
4+
import org.jetbrains.kotlinx.dataframe.DataFrame
5+
import org.jetbrains.kotlinx.dataframe.columns.ColumnWithPath
6+
import org.jetbrains.kotlinx.dataframe.columns.toColumnSet
7+
import org.jetbrains.kotlinx.dataframe.impl.api.formatHeaderImpl
8+
9+
// region docs
10+
11+
/**
12+
* A lambda used to format a column header (its displayed name) when rendering a dataframe to HTML.
13+
*
14+
* The lambda runs in the context of [FormattingDsl] and receives the [ColumnWithPath] of the header to format.
15+
* Return a [CellAttributes] (or `null`) describing the CSS you want to apply to the header cell.
16+
*
17+
* Examples:
18+
* - Center the header: `attr("text-align", "center")`
19+
* - Make it bold: `bold`
20+
* - Set a custom color: `textColor(rgb(10, 10, 10))`
21+
*/
22+
public typealias HeaderColFormatter<C> = FormattingDsl.(col: ColumnWithPath<C>) -> CellAttributes?
23+
24+
/**
25+
* An intermediate class used in the header-format operation [formatHeader].
26+
*
27+
* This class itself does nothing—it represents a selection of columns whose headers will be formatted.
28+
* Finalize this step by calling [with] to produce a new [FormattedFrame].
29+
*
30+
* Header formatting is additive and supports nested column groups: styles specified for a parent group
31+
* are inherited by its child columns unless overridden for the child.
32+
*/
33+
public class HeaderFormatClause<T, C>(
34+
internal val df: DataFrame<T>,
35+
internal val columns: ColumnsSelector<T, C> = { all().cast() },
36+
internal val oldHeaderFormatter: HeaderColFormatter<C>? = null,
37+
internal val oldCellFormatter: RowColFormatter<T, *>? = null,
38+
) {
39+
override fun toString(): String =
40+
"HeaderFormatClause(df=$df, columns=$columns, oldHeaderFormatter=$oldHeaderFormatter, oldCellFormatter=$oldCellFormatter)"
41+
}
42+
43+
// endregion
44+
45+
// region DataFrame.formatHeader
46+
47+
/**
48+
* **Experimental API. It may be changed in the future.**
49+
*
50+
* Selects [columns] whose headers should be formatted. If unspecified, all columns will be formatted.
51+
*
52+
* This does not immediately produce a [FormattedFrame]; instead it returns a [HeaderFormatClause]
53+
* which must be finalized using [HeaderFormatClause.with].
54+
*/
55+
public fun <T, C> DataFrame<T>.formatHeader(columns: ColumnsSelector<T, C>): HeaderFormatClause<T, C> =
56+
HeaderFormatClause(this, columns)
57+
58+
/**
59+
* **Experimental API. It may be changed in the future.**
60+
*
61+
* Selects [columns] whose headers should be formatted.
62+
*
63+
* This does not immediately produce a [FormattedFrame]; instead it returns a [HeaderFormatClause]
64+
* which must be finalized using [HeaderFormatClause.with].
65+
*/
66+
public fun <T> DataFrame<T>.formatHeader(vararg columns: String): HeaderFormatClause<T, Any?> =
67+
formatHeader { columns.toColumnSet() }
68+
69+
/**
70+
* **Experimental API. It may be changed in the future.**
71+
*
72+
* Selects all columns for header formatting.
73+
*
74+
* This does not immediately produce a [FormattedFrame]; instead it returns a [HeaderFormatClause]
75+
* which must be finalized using [HeaderFormatClause.with].
76+
*/
77+
public fun <T> DataFrame<T>.formatHeader(): HeaderFormatClause<T, Any?> = HeaderFormatClause(this)
78+
79+
// endregion
80+
81+
// region FormattedFrame.formatHeader
82+
83+
/**
84+
* **Experimental API. It may be changed in the future.**
85+
*
86+
* Selects [columns] whose headers should be formatted.
87+
*
88+
* This does not immediately produce a [FormattedFrame]; instead it returns a [HeaderFormatClause]
89+
* which must be finalized using [HeaderFormatClause.with].
90+
*/
91+
public fun <T, C> FormattedFrame<T>.formatHeader(columns: ColumnsSelector<T, C>): HeaderFormatClause<T, C> =
92+
HeaderFormatClause(
93+
df = df,
94+
columns = columns,
95+
oldHeaderFormatter = headerFormatter as HeaderColFormatter<C>?,
96+
oldCellFormatter = formatter,
97+
)
98+
99+
/**
100+
* **Experimental API. It may be changed in the future.**
101+
*
102+
* Selects [columns] whose headers should be formatted.
103+
*
104+
* This does not immediately produce a [FormattedFrame]; instead it returns a [HeaderFormatClause]
105+
* which must be finalized using [HeaderFormatClause.with].
106+
*/
107+
public fun <T> FormattedFrame<T>.formatHeader(vararg columns: String): HeaderFormatClause<T, Any?> =
108+
formatHeader { columns.toColumnSet() }
109+
110+
/**
111+
* **Experimental API. It may be changed in the future.**
112+
*
113+
* Selects all columns for header formatting.
114+
*
115+
* This does not immediately produce a [FormattedFrame]; instead it returns a [HeaderFormatClause]
116+
* which must be finalized using [HeaderFormatClause.with].
117+
*/
118+
public fun <T> FormattedFrame<T>.formatHeader(): HeaderFormatClause<T, Any?> =
119+
HeaderFormatClause(
120+
df = df,
121+
oldHeaderFormatter = headerFormatter,
122+
oldCellFormatter = formatter,
123+
)
124+
125+
// endregion
126+
127+
// region terminal operations
128+
129+
/**
130+
* **Experimental API. It may be changed in the future.**
131+
*
132+
* Creates a new [FormattedFrame] that uses the specified [HeaderColFormatter] to format the selected headers.
133+
*
134+
* Header formatting is additive: attributes from already-applied header formatters are combined with the newly
135+
*
136+
* returned attributes using [CellAttributes.and]. If a parent column group is selected, its attributes are
137+
* applied to its children unless explicitly overridden.
138+
*/
139+
@Suppress("UNCHECKED_CAST")
140+
public fun <T, C> HeaderFormatClause<T, C>.with(formatter: HeaderColFormatter<C>): FormattedFrame<T> =
141+
formatHeaderImpl(formatter)
142+
143+
// endregion

core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/api/format.kt

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -56,15 +56,18 @@ internal inline fun <T, C> FormatClause<T, C>.formatImpl(
5656
val clause = this
5757
val columns = clause.df.getColumnPaths(UnresolvedColumnsPolicy.Skip, clause.columns).toSet()
5858

59-
return FormattedFrame(clause.df) { row, col ->
60-
val oldAttributes = clause.oldFormatter?.invoke(FormattingDsl, row, col.cast())
61-
if (col.path in columns) {
62-
val value = col[row] as C
63-
if (clause.filter(row, value)) {
64-
return@FormattedFrame oldAttributes and formatter(FormattingDsl, row.cast(), col.cast())
59+
return FormattedFrame(
60+
df = clause.df,
61+
formatter = { row, col ->
62+
val oldAttributes = clause.oldFormatter?.invoke(FormattingDsl, row, col.cast())
63+
if (col.path in columns) {
64+
val value = col[row] as C
65+
if (clause.filter(row, value)) {
66+
return@FormattedFrame oldAttributes and formatter(FormattingDsl, row.cast(), col.cast())
67+
}
6568
}
66-
}
67-
68-
oldAttributes
69-
}
69+
oldAttributes
70+
},
71+
headerFormatter = clause.oldHeaderFormatter,
72+
)
7073
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package org.jetbrains.kotlinx.dataframe.impl.api
2+
3+
import org.jetbrains.kotlinx.dataframe.api.FormattedFrame
4+
import org.jetbrains.kotlinx.dataframe.api.FormattingDsl
5+
import org.jetbrains.kotlinx.dataframe.api.HeaderColFormatter
6+
import org.jetbrains.kotlinx.dataframe.api.HeaderFormatClause
7+
import org.jetbrains.kotlinx.dataframe.api.and
8+
import org.jetbrains.kotlinx.dataframe.columns.ColumnWithPath
9+
import org.jetbrains.kotlinx.dataframe.columns.UnresolvedColumnsPolicy
10+
import org.jetbrains.kotlinx.dataframe.impl.getColumnPaths
11+
12+
internal fun <T, C> HeaderFormatClause<T, C>.formatHeaderImpl(formatter: HeaderColFormatter<C>): FormattedFrame<T> {
13+
val selectedPaths = df.getColumnPaths(UnresolvedColumnsPolicy.Skip, columns).toSet()
14+
val oldHeader = oldHeaderFormatter
15+
16+
val composedHeader: HeaderColFormatter<Any?> = { col ->
17+
val typedCol = col as ColumnWithPath<C>
18+
val existingAttr = oldHeader?.invoke(FormattingDsl, typedCol)
19+
val newAttr = if (col.path in selectedPaths) formatter(FormattingDsl, typedCol) else null
20+
existingAttr and newAttr
21+
}
22+
23+
return FormattedFrame(df, oldCellFormatter, composedHeader)
24+
}

0 commit comments

Comments
 (0)