Skip to content

Commit afe6991

Browse files
Merge pull request #1459 from Kotlin/formatHeader
Format header
2 parents 7d69835 + a533a76 commit afe6991

File tree

15 files changed

+1000
-26
lines changed

15 files changed

+1000
-26
lines changed

core/api/core.api

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2232,11 +2232,21 @@ public final class org/jetbrains/kotlinx/dataframe/api/ForEachKt {
22322232
}
22332233

22342234
public final class org/jetbrains/kotlinx/dataframe/api/FormatClause {
2235-
public fun <init> (Lorg/jetbrains/kotlinx/dataframe/DataFrame;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;)V
2236-
public synthetic fun <init> (Lorg/jetbrains/kotlinx/dataframe/DataFrame;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
2235+
public fun <init> (Lorg/jetbrains/kotlinx/dataframe/DataFrame;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;)V
2236+
public synthetic fun <init> (Lorg/jetbrains/kotlinx/dataframe/DataFrame;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
22372237
public fun toString ()Ljava/lang/String;
22382238
}
22392239

2240+
public final class org/jetbrains/kotlinx/dataframe/api/FormatHeaderKt {
2241+
public static final fun formatHeader (Lorg/jetbrains/kotlinx/dataframe/DataFrame;)Lorg/jetbrains/kotlinx/dataframe/api/HeaderFormatClause;
2242+
public static final fun formatHeader (Lorg/jetbrains/kotlinx/dataframe/DataFrame;Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/api/HeaderFormatClause;
2243+
public static final fun formatHeader (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/api/HeaderFormatClause;
2244+
public static final fun formatHeader (Lorg/jetbrains/kotlinx/dataframe/api/FormattedFrame;)Lorg/jetbrains/kotlinx/dataframe/api/HeaderFormatClause;
2245+
public static final fun formatHeader (Lorg/jetbrains/kotlinx/dataframe/api/FormattedFrame;Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/api/HeaderFormatClause;
2246+
public static final fun formatHeader (Lorg/jetbrains/kotlinx/dataframe/api/FormattedFrame;[Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/api/HeaderFormatClause;
2247+
public static final fun with (Lorg/jetbrains/kotlinx/dataframe/api/HeaderFormatClause;Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/api/FormattedFrame;
2248+
}
2249+
22402250
public final class org/jetbrains/kotlinx/dataframe/api/FormatKt {
22412251
public static final fun and (Lorg/jetbrains/kotlinx/dataframe/api/CellAttributes;Lorg/jetbrains/kotlinx/dataframe/api/CellAttributes;)Lorg/jetbrains/kotlinx/dataframe/api/CellAttributes;
22422252
public static final fun at (Lorg/jetbrains/kotlinx/dataframe/api/FormatClause;Ljava/util/Collection;)Lorg/jetbrains/kotlinx/dataframe/api/FormatClause;
@@ -2259,8 +2269,8 @@ public final class org/jetbrains/kotlinx/dataframe/api/FormatKt {
22592269
}
22602270

22612271
public final class org/jetbrains/kotlinx/dataframe/api/FormattedFrame {
2262-
public fun <init> (Lorg/jetbrains/kotlinx/dataframe/DataFrame;Lkotlin/jvm/functions/Function3;)V
2263-
public synthetic fun <init> (Lorg/jetbrains/kotlinx/dataframe/DataFrame;Lkotlin/jvm/functions/Function3;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
2272+
public fun <init> (Lorg/jetbrains/kotlinx/dataframe/DataFrame;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;)V
2273+
public synthetic fun <init> (Lorg/jetbrains/kotlinx/dataframe/DataFrame;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
22642274
public final fun getDisplayConfiguration (Lorg/jetbrains/kotlinx/dataframe/io/DisplayConfiguration;)Lorg/jetbrains/kotlinx/dataframe/io/DisplayConfiguration;
22652275
public final fun toHtml (Lorg/jetbrains/kotlinx/dataframe/io/DisplayConfiguration;)Lorg/jetbrains/kotlinx/dataframe/io/DataFrameHtmlData;
22662276
public static synthetic fun toHtml$default (Lorg/jetbrains/kotlinx/dataframe/api/FormattedFrame;Lorg/jetbrains/kotlinx/dataframe/io/DisplayConfiguration;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/io/DataFrameHtmlData;
@@ -2545,6 +2555,12 @@ public final class org/jetbrains/kotlinx/dataframe/api/HeadKt {
25452555
public static synthetic fun head$default (Lorg/jetbrains/kotlinx/dataframe/DataFrame;IILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame;
25462556
}
25472557

2558+
public final class org/jetbrains/kotlinx/dataframe/api/HeaderFormatClause {
2559+
public fun <init> (Lorg/jetbrains/kotlinx/dataframe/DataFrame;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;)V
2560+
public synthetic fun <init> (Lorg/jetbrains/kotlinx/dataframe/DataFrame;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
2561+
public fun toString ()Ljava/lang/String;
2562+
}
2563+
25482564
public final class org/jetbrains/kotlinx/dataframe/api/ImplodeKt {
25492565
public static final fun implode (Lorg/jetbrains/kotlinx/dataframe/DataFrame;Z)Lorg/jetbrains/kotlinx/dataframe/DataRow;
25502566
public static final fun implode (Lorg/jetbrains/kotlinx/dataframe/DataFrame;ZLkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataFrame;
@@ -6205,23 +6221,29 @@ public final class org/jetbrains/kotlinx/dataframe/io/DisplayConfiguration {
62056221
public static final field Companion Lorg/jetbrains/kotlinx/dataframe/io/DisplayConfiguration$Companion;
62066222
public synthetic fun <init> (Ljava/lang/Integer;Ljava/lang/Integer;ILkotlin/jvm/functions/Function3;Ljava/lang/String;ZZZZZILkotlin/jvm/internal/DefaultConstructorMarker;)V
62076223
public synthetic fun <init> (Ljava/lang/Integer;Ljava/lang/Integer;ILkotlin/jvm/functions/Function3;Ljava/lang/String;ZZZZZLkotlin/jvm/internal/DefaultConstructorMarker;)V
6224+
public synthetic fun <init> (Ljava/lang/Integer;Ljava/lang/Integer;ILkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;Ljava/lang/String;ZZZZZILkotlin/jvm/internal/DefaultConstructorMarker;)V
6225+
public synthetic fun <init> (Ljava/lang/Integer;Ljava/lang/Integer;ILkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;Ljava/lang/String;ZZZZZLkotlin/jvm/internal/DefaultConstructorMarker;)V
62086226
public final fun component1 ()Ljava/lang/Integer;
62096227
public final fun component10 ()Z
6228+
public final fun component11 ()Z
62106229
public final fun component2 ()Ljava/lang/Integer;
62116230
public final fun component3 ()I
62126231
public final fun component4 ()Lkotlin/jvm/functions/Function3;
6213-
public final fun component5-3Sl7FsM ()Ljava/lang/String;
6214-
public final fun component6 ()Z
6215-
public final fun component8 ()Z
6232+
public final fun component5 ()Lkotlin/jvm/functions/Function2;
6233+
public final fun component6-3Sl7FsM ()Ljava/lang/String;
6234+
public final fun component7 ()Z
62166235
public final fun component9 ()Z
6217-
public final fun copy-rqXL5tM (Ljava/lang/Integer;Ljava/lang/Integer;ILkotlin/jvm/functions/Function3;Ljava/lang/String;ZZZZZ)Lorg/jetbrains/kotlinx/dataframe/io/DisplayConfiguration;
6236+
public final fun copy-bMNacXk (Ljava/lang/Integer;Ljava/lang/Integer;ILkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;Ljava/lang/String;ZZZZZ)Lorg/jetbrains/kotlinx/dataframe/io/DisplayConfiguration;
6237+
public static synthetic fun copy-bMNacXk$default (Lorg/jetbrains/kotlinx/dataframe/io/DisplayConfiguration;Ljava/lang/Integer;Ljava/lang/Integer;ILkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;Ljava/lang/String;ZZZZZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/io/DisplayConfiguration;
6238+
public final synthetic fun copy-rqXL5tM (Ljava/lang/Integer;Ljava/lang/Integer;ILkotlin/jvm/functions/Function3;Ljava/lang/String;ZZZZZ)Lorg/jetbrains/kotlinx/dataframe/io/DisplayConfiguration;
62186239
public static synthetic fun copy-rqXL5tM$default (Lorg/jetbrains/kotlinx/dataframe/io/DisplayConfiguration;Ljava/lang/Integer;Ljava/lang/Integer;ILkotlin/jvm/functions/Function3;Ljava/lang/String;ZZZZZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/io/DisplayConfiguration;
62196240
public fun equals (Ljava/lang/Object;)Z
62206241
public final fun getCellContentLimit ()I
62216242
public final fun getCellFormatter ()Lkotlin/jvm/functions/Function3;
62226243
public final fun getDecimalFormat-3Sl7FsM ()Ljava/lang/String;
62236244
public final fun getDownsizeBufferedImage ()Z
62246245
public final fun getEnableFallbackStaticTables ()Z
6246+
public final fun getHeaderFormatter ()Lkotlin/jvm/functions/Function2;
62256247
public final fun getIsolatedOutputs ()Z
62266248
public final fun getNestedRowsLimit ()Ljava/lang/Integer;
62276249
public final fun getRowsLimit ()Ljava/lang/Integer;
@@ -6233,6 +6255,7 @@ public final class org/jetbrains/kotlinx/dataframe/io/DisplayConfiguration {
62336255
public final fun setDecimalFormat-h5o3lmc (Ljava/lang/String;)V
62346256
public final fun setDownsizeBufferedImage (Z)V
62356257
public final fun setEnableFallbackStaticTables (Z)V
6258+
public final fun setHeaderFormatter (Lkotlin/jvm/functions/Function2;)V
62366259
public final fun setIsolatedOutputs (Z)V
62376260
public final fun setNestedRowsLimit (Ljava/lang/Integer;)V
62386261
public final fun setRowsLimit (Ljava/lang/Integer;)V

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

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

330330
/**
331331
* @include [CommonFormatDocs]
@@ -390,7 +390,13 @@ public fun <T> FormattedFrame<T>.format(): FormatClause<T, Any?> = FormatClause(
390390
* Check out the full [Grammar][FormatDocs.Grammar].
391391
*/
392392
public fun <T, C> FormatClause<T, C>.where(filter: RowValueFilter<T, C>): FormatClause<T, C> =
393-
FormatClause(filter = this.filter and filter, df = df, columns = columns, oldFormatter = oldFormatter)
393+
FormatClause(
394+
filter = this.filter and filter,
395+
df = df,
396+
columns = columns,
397+
oldFormatter = oldFormatter,
398+
oldHeaderFormatter = oldHeaderFormatter,
399+
)
394400

395401
/**
396402
* Only format the selected columns at given row indices.
@@ -780,7 +786,11 @@ public typealias CellFormatter<C> = FormattingDsl.(cell: C) -> CellAttributes?
780786
*
781787
* You can apply further formatting to this [FormattedFrame] by calling [format()][FormattedFrame.format] once again.
782788
*/
783-
public class FormattedFrame<T>(internal val df: DataFrame<T>, internal val formatter: RowColFormatter<T, *>? = null) {
789+
public class FormattedFrame<T>(
790+
internal val df: DataFrame<T>,
791+
internal val formatter: RowColFormatter<T, *>? = null,
792+
internal val headerFormatter: HeaderColFormatter<*>? = null,
793+
) {
784794

785795
/**
786796
* Returns a [DataFrameHtmlData] without additional definitions.
@@ -826,7 +836,10 @@ public class FormattedFrame<T>(internal val df: DataFrame<T>, internal val forma
826836
/** Applies this formatter to the given [configuration] and returns a new instance. */
827837
@Suppress("UNCHECKED_CAST")
828838
public fun getDisplayConfiguration(configuration: DisplayConfiguration): DisplayConfiguration =
829-
configuration.copy(cellFormatter = formatter as RowColFormatter<*, *>?)
839+
configuration.copy(
840+
cellFormatter = formatter as RowColFormatter<*, *>?,
841+
headerFormatter = headerFormatter,
842+
)
830843
}
831844

832845
/**
@@ -858,6 +871,7 @@ public class FormatClause<T, C>(
858871
internal val columns: ColumnsSelector<T, C> = { all().cast() },
859872
internal val oldFormatter: RowColFormatter<T, C>? = null,
860873
internal val filter: RowValueFilter<T, C> = { true },
874+
internal val oldHeaderFormatter: HeaderColFormatter<*>? = null,
861875
) {
862876
override fun toString(): String =
863877
"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/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)