From cb916acc81543b80fa60200e0ed8d8e325c7072c Mon Sep 17 00:00:00 2001 From: rcherni Date: Wed, 18 Oct 2023 12:38:12 +0100 Subject: [PATCH 01/20] Add pivot tadependency --- build.gradle.kts | 10 ++++++---- .../src/main/kotlin/org/kopi/galite/gradle/Versions.kt | 1 + 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 960213a3e..f95916a7d 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -15,10 +15,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -import org.kopi.galite.gradle._java -import org.kopi.galite.gradle._publishing -import org.kopi.galite.gradle.configureMavenCentralPom -import org.kopi.galite.gradle.signPublication +import org.kopi.galite.gradle.* plugins { id("org.jetbrains.kotlin.jvm") version "1.6.10" apply false @@ -43,11 +40,16 @@ subprojects { maven { url = uri("https://s01.oss.sonatype.org/content/repositories/snapshots/") } + maven { + url = uri("https://mvnrepository.com/artifact/org.vaadin.addons") + } } dependencies { "implementation"(kotlin("stdlib")) "implementation"(kotlin("reflect")) + // Pivot Table dependency + "implementation"("org.vaadin.addons.componentfactory", "pivottable-flow", Versions.PIVOT_TABLE) } tasks.withType { diff --git a/buildSrc/src/main/kotlin/org/kopi/galite/gradle/Versions.kt b/buildSrc/src/main/kotlin/org/kopi/galite/gradle/Versions.kt index 87c7f8edd..497718256 100644 --- a/buildSrc/src/main/kotlin/org/kopi/galite/gradle/Versions.kt +++ b/buildSrc/src/main/kotlin/org/kopi/galite/gradle/Versions.kt @@ -41,4 +41,5 @@ object Versions { const val JFREE_CHART = "1.0.19" const val WYSIWYG_EJAVA = "2.0.1" const val KOTLINX_DATAFRAME = "0.8.0-rc-7" + const val PIVOT_TABLE = "2.0.0" } From c5f93126f4f43800b45bf369369e89f6b0534721 Mon Sep 17 00:00:00 2001 From: Super User Date: Wed, 18 Oct 2023 12:41:49 +0100 Subject: [PATCH 02/20] Remove old pivot table implementation --- .../galite/visual/pivottable/Constants.kt | 71 --- .../galite/visual/pivottable/MPivotTable.kt | 175 ------- .../galite/visual/pivottable/PivotTable.kt | 426 ------------------ .../org/kopi/galite/visual/pivottable/Span.kt | 25 - .../galite/visual/pivottable/UPivotTable.kt | 27 -- .../ui/vaadin/pivottable/DPivotTable.kt | 278 ------------ .../visual/ui/vaadin/pivottable/DTable.kt | 212 --------- .../visual/ui/vaadin/pivottable/VTable.kt | 67 --- .../visual/ui/vaadin/visual/VUIFactory.kt | 14 - 9 files changed, 1295 deletions(-) delete mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivottable/Constants.kt delete mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivottable/MPivotTable.kt delete mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivottable/PivotTable.kt delete mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivottable/Span.kt delete mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivottable/UPivotTable.kt delete mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivottable/DPivotTable.kt delete mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivottable/DTable.kt delete mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivottable/VTable.kt diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivottable/Constants.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivottable/Constants.kt deleted file mode 100644 index 05e330335..000000000 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivottable/Constants.kt +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN - * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -package org.kopi.galite.visual.pivottable - -import org.kopi.galite.visual.form.VConstants -import org.kopi.galite.visual.Constants - -interface Constants : Constants { - companion object { - - // --------------------------------------------------------------------- - // TRIGGERED EVENTS (MAX 32) - // --------------------------------------------------------------------- - const val TRG_PREPIVOT = 0 - const val TRG_POSTPIVOT = 1 - const val TRG_INIT = 2 - const val TRG_FORMAT = 3 - const val TRG_COMPUTE = 4 - const val TRG_CMDACCESS = 5 - const val TRG_VOID: Int = VConstants.TRG_VOID - const val TRG_OBJECT: Int = VConstants.TRG_OBJECT - const val TRG_BOOLEAN: Int = VConstants.TRG_BOOLEAN - - // --------------------------------------------------------------------- - // PREDEFINED COMMANDS - // --------------------------------------------------------------------- - const val CMD_QUIT = 0 - const val CMD_PRINT = 1 - const val CMD_PREVIEW = 2 - const val CMD_PRINT_OPTIONS = 3 - const val CMD_EXPORT_CSV = 4 - const val CMD_EXPORT_XLS = 5 - const val CMD_EXPORT_XLSX = 6 - const val CMD_EXPORT_PDF = 7 - const val CMD_FOLD = 8 - const val CMD_UNFOLD = 9 - const val CMD_SORT = 10 - const val CMD_FOLD_COLUMN = 11 - const val CMD_UNFOLD_COLUMN = 12 - const val CMD_COLUMN_INFO = 13 - const val CMD_OPEN_LINE = 14 - const val CMD_REMOVE_CONFIGURATION = 15 - const val CMD_LOAD_CONFIGURATION = 16 - const val CMD_HELP = 17 - - // --------------------------------------------------------------------- - // TRIGGER INFO - // --------------------------------------------------------------------- - val TRG_NAMES = arrayOf( - "TRG_PREPIVOT", "TRG_POSTPIVOT", "TRG_INIT", "TRG_FORMAT", "TRG_COMPUTE", "TRG_CMDACCESS") - val TRG_TYPES = intArrayOf( - TRG_VOID, TRG_VOID, TRG_VOID, TRG_OBJECT, TRG_OBJECT, TRG_BOOLEAN - ) - } -} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivottable/MPivotTable.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivottable/MPivotTable.kt deleted file mode 100644 index cbb6d8e80..000000000 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivottable/MPivotTable.kt +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN - * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.kopi.galite.visual.pivottable - -import org.jetbrains.kotlinx.dataframe.AnyCol -import org.jetbrains.kotlinx.dataframe.columns.ColumnGroup -import org.jetbrains.kotlinx.dataframe.columns.ValueColumn -import org.jetbrains.kotlinx.dataframe.values - -class MPivotTable(private val pivotTable: PivotTable) { - private lateinit var values: MutableList> - private var valuesSize: Int = 0 - - // Data to show - private lateinit var rows: MutableList> - private lateinit var groups: MutableList> - private lateinit var groupsSpans: MutableList> - private lateinit var groupsSpanTypes: MutableList> - private lateinit var rowsSpanTypes: MutableList> - private lateinit var spanTypes: List> - private lateinit var data: List> - - fun build() { - val cols = pivotTable.dataframe.columns() - val columnGroups = cols.filterIsInstance(ColumnGroup::class.java) - val valueColumns = cols.filterIsInstance(ValueColumn::class.java) - - values = mutableListOf() - rows = mutableListOf() - groups = mutableListOf() - groupsSpans = mutableListOf() - groupsSpanTypes = mutableListOf() - rowsSpanTypes = mutableListOf() - - valuesSize = valueColumns.size - - columnGroups.forEach { column -> - column.buildHeaderGrouping() - } - - val rowGroupingValues = mutableListOf() - - rows.add(rowGroupingValues) - valueColumns.forEach { - rowGroupingValues.add(it.name()) - } - repeat(values.size + 1) { rowGroupingValues.add("") } - - repeat(pivotTable.dataframe.rowsCount()) { rowIndex -> - val aggregationValues = mutableListOf() - rows.add(aggregationValues) - valueColumns.forEach { vc -> - val value = vc.values.elementAt(rowIndex) - aggregationValues.add(pivotTable.aggregateField!!.model.format(value)) - } - - aggregationValues.add("") - - values.forEach { - aggregationValues.add(it[rowIndex]) - } - } - - buildRowsSpanTypes() - - for(j in 0 until valuesSize) { - var i = 0 - - while(i < rows.size) { - var k = i + 1 - while(k < rows.size && rows[i][j] == rows[k][j] && (j == 0 || rowsSpanTypes[k][j - 1] == Span.ROW)) { - rows[k][j] = "" - rowsSpanTypes[k][j] = Span.ROW - k++ - } - i = k - } - } - - spanTypes = groupsSpanTypes + rowsSpanTypes - data = groups + rows - } - - private fun buildRowsSpanTypes() { - rows.forEachIndexed { index, row -> - val spans = row.mapIndexed { rowIndex, _ -> - if(index == 0 && rowIndex > valuesSize) { - Span.ROW - } else if (rowIndex == valuesSize) { - Span.COL - } else { - Span.NONE - } - }.toMutableList() - rowsSpanTypes.add(spans) - } - } - - private fun ColumnGroup<*>.buildHeaderGrouping(columns: List = columns(), columnIndex: Int = 0) { - val group = mutableListOf() - val spans = mutableListOf() - val spansTypes = mutableListOf() - val groupingColumns = mutableListOf() - - add("", valuesSize, group, spans, spansTypes) - add(pivotTable.grouping.columns[columnIndex].model.label, 1, group, spans, spansTypes) - - groups.add(group) - groupsSpans.add(spans) - groupsSpanTypes.add(spansTypes) - - columns.forEach { column -> - if(column is ColumnGroup<*>) { - add(column.name(), column.columnsCount(), group, spans, spansTypes) - groupingColumns.addAll(column.columns()) - } else { - add(column.name(), valuesSize, group, spans, spansTypes) - values.add(column.values.map { pivotTable.aggregateField!!.model.format(it) }) - } - } - - if(groupingColumns.isNotEmpty()) { - buildHeaderGrouping(groupingColumns, columnIndex + 1) - } - } - - private fun add(header: String, - spanSize: Int, - group: MutableList, - spans: MutableList, - spansTypes: MutableList, ) { - group.add(header) - spans.add(spanSize) - spansTypes.add(Span.NONE) - repeat(spanSize - 1) { - group.add("") - spansTypes.add(Span.COL) - } - } - - /** - * Returns the number of columns managed by the data source object. - * - * @return the number or columns to display - */ - fun getColumnCount(): Int = data.lastOrNull()?.size ?: 0 - - /** - * Returns the number of records managed by the data source object. - * - * @return the number or rows in the model - */ - fun getRowCount(): Int = data.size - - fun getValueAt(row: Int, col: Int): String = data[row][col] - - fun isTitle(row: Int, col: Int): Boolean = (row in 0 .. groups.size) || (col in 0 .. valuesSize) - - fun getSpan(row: Int, col: Int): Span = spanTypes[row][col] -} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivottable/PivotTable.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivottable/PivotTable.kt deleted file mode 100644 index 95a384527..000000000 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivottable/PivotTable.kt +++ /dev/null @@ -1,426 +0,0 @@ -/* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN - * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.kopi.galite.visual.pivottable - -import java.io.File -import java.util.Locale - -import kotlin.reflect.full.starProjectedType - -import org.jetbrains.kotlinx.dataframe.DataFrame -import org.jetbrains.kotlinx.dataframe.aggregation.Aggregatable -import org.jetbrains.kotlinx.dataframe.api.* -import org.jetbrains.kotlinx.dataframe.AnyFrame -import org.jetbrains.kotlinx.dataframe.DataColumn -import org.kopi.galite.visual.domain.Domain -import org.kopi.galite.visual.dsl.report.ReportField -import org.kopi.galite.visual.dsl.report.ReportRow -import org.kopi.galite.visual.form.VConstants -import org.kopi.galite.visual.l10n.LocalizationManager -import org.kopi.galite.visual.report.Constants -import org.kopi.galite.visual.report.VReportColumn -import org.kopi.galite.visual.ApplicationContext -import org.kopi.galite.visual.UIFactory -import org.kopi.galite.visual.UWindow -import org.kopi.galite.visual.VWindow -import org.kopi.galite.visual.WindowBuilder -import org.kopi.galite.visual.WindowController - -open class PivotTable(title: String?, var help: String?, override val locale: Locale?) : VWindow(), Constants, VConstants { - - constructor(title: String, locale: Locale? = null) : this(title, null, locale) - - // ---------------------------------------------------------------------- - // DATA MEMBERS - // ---------------------------------------------------------------------- - private var pageTitle = "" - - /** Report's fields. */ - val fields = mutableListOf>() - - /** A report data row */ - val rows = mutableListOf() - - val columns = mutableListOf() - - lateinit var grouping: Grouping - - var funct = Function.NONE - - internal lateinit var dataframe: AnyFrame - private var aggregateFields = arrayOf() - var aggregateField: ReportField<*>? = null - private set - val model: MPivotTable = MPivotTable(this) - - init { - setTitle(title) - } - - fun aggregate(function: Function, field: ReportField) { - funct = function - aggregateFields = arrayOf(field.label!!) - aggregateField = field - } - - /** - * creates and returns a field. It uses [init] method to initialize the field. - * - * @param domain the domain of the field. - * @param init initialization method. - * @return a field. - */ - inline fun ?> field(domain: Domain, - noinline init: ReportField.() -> Unit): ReportField { - domain.kClass = T::class - - val field = ReportField(domain, init, "ANM_${fields.size}", domain.source.ifEmpty { source }) - - field.initialize() - - val pos = if(columns.size == 0) 0 else columns.size - 1 // TODO!! - columns.add(pos, field.buildReportColumn()) - fields.add(field) - - return field - } - - /** - * creates and returns a field that accept nulls. It uses [init] method to initialize the field. - * - * @param domain the domain of the field. - * @param init initialization method. - * @return a field. - */ - inline fun ?> nullableField(domain: Domain, - noinline init: ReportField.() -> Unit): ReportField { - return field(domain, init) as ReportField - } - - override fun getType() = org.kopi.galite.visual.Constants.MDL_PIVOT_TABLE - - /** - * Redisplay the pivot table after change in formatting - */ - @Deprecated("call method in display; model must not be refreshed") - fun redisplay() { - (getDisplay() as UPivotTable).redisplay() - } - - /** - * Close window - */ - @Deprecated("call method in display; model must not be closed") - fun close() { - getDisplay()!!.closeWindow() - } - - override fun destroyModel() { - /*try { TODO - callTrigger(org.kopi.galite.visual.pivottable.Constants.TRG_POSTREPORT) - } catch (v: VException) { - // ignore - }*/ - super.destroyModel() - } - - fun columnMoved(pos: IntArray) { - (getDisplay() as UPivotTable).columnMoved(pos) - } - - /** - * Sets the title - */ - fun setPageTitle(title: String) { - pageTitle = title - setTitle(title) - } - - fun getValueAt(row: Int, col: Int): String = model.getValueAt(row, col) - - // ---------------------------------------------------------------------- - // DISPLAY INTERFACE - // ---------------------------------------------------------------------- - open fun initPivotTable() { - build() - //callTrigger(Constants.TRG_PREPIVOT) TODO - } - - /** - * Localizes this pivot table. - * - * @param manager the manger to use for localization. - */ - private fun localize(manager: LocalizationManager) { - if (ApplicationContext.getDefaultLocale() != locale) { - val loc = manager.getReportLocalizer(source) - - setTitle(loc.getTitle()) - help = loc.getHelp() - columns.forEach { it.localize(loc) } - } - } - - fun build() { - localize(manager) - buildDataFrame() - model.build() - (getDisplay() as UPivotTable?)?.build() - } - - private fun buildDataFrame() { - val df = dataFrameOf(fields) - - dataframe = if (grouping.columns.isEmpty() && grouping.rows.isEmpty()) { - df.aggregate() - } else if (grouping.rows.isEmpty()) { - df.pivot().aggregate() - } else if (grouping.columns.isEmpty()) { - df.groupBy().aggregate() - } else { - df.pivot().groupBy().aggregate().sortBy() - } - } - - private fun getAllValuesOf(field: ReportField): List = rows.map { it[field] } - - private fun getAllFormattedValuesOf(field: ReportField<*>): List = rows.map { field.model.format(it[field]) } - - private fun dataFrameOf(header: Iterable>): AnyFrame = - header.map { field -> - val (values, type) = if (field == aggregateField) { - getAllValuesOf(field) to field.domain.kClass!!.starProjectedType - } else { - getAllFormattedValuesOf(field) to String::class.starProjectedType - } - - DataColumn.create( - field.model.label, - values, - type - ) - }.toDataFrame() - - private fun DataFrame.pivot(): Pivot { - return if (grouping.columns.size == 1) { - this.pivot(grouping.columns[0].label!!) - } else { - this.pivot { - grouping.columns - .subList(2, grouping.columns.size) - .fold(grouping.columns[0].label!! then grouping.columns[1].label!!) { a, b -> - a then b.label!! - } - } - } - } - - private fun DataFrame.groupBy(): GroupBy { - return if (grouping.rows.size == 1) { - this.groupBy(grouping.rows[0].label!!) - } else { - this.groupBy { - grouping.rows - .subList(2, grouping.rows.size) - .fold(grouping.rows[0].label!! and grouping.rows[1].label!!) { a, b -> - a and b.label!! - } - } - } - } - - fun Pivot<*>.groupBy(): PivotGroupBy { - return if (grouping.rows.size == 1) { - this.groupBy(grouping.rows[0].label!!) - } else { - this.groupBy { - grouping.rows - .subList(2, grouping.rows.size) - .fold(grouping.rows[0].label!! and grouping.rows[1].label!!) { a, b -> - a and b.label!! - } - } - } - } - - private fun DataFrame<*>.sortBy(): DataFrame { - return if (grouping.rows.size == 1) { - this.sortBy(grouping.rows[0].label!!) - } else { - this.sortBy { - grouping.rows - .subList(2, grouping.rows.size) - .fold(grouping.rows[0].label!! and grouping.rows[1].label!!) { a, b -> - a and b.label!! - } - } - } - } - - /** - * Adds a row to the pivot table. - * - * @param init initializes the row with values. - */ - fun add(init: ReportRow.() -> Unit) { - val row = ReportRow(fields) - row.init() - - // Last null value is added for the separator column - rows.add(row) - } - - private fun Aggregatable.aggregate(): DataFrame { - return when (funct) { - Function.MAX -> _max() - Function.MEAN -> _mean() - Function.SUM -> _sum() - Function.MIN -> _min() - else -> TODO() - } - } - - private fun Aggregatable<*>._max(): DataFrame { - return when (this) { - is Pivot<*> -> { - this.max(*aggregateFields).toDataFrame() - } - is DataFrame<*> -> { - this.max().toDataFrame() - } - is GroupBy<*, *> -> { - this.max(*aggregateFields) - } - is PivotGroupBy<*> -> { - this.max(*aggregateFields) - } - else -> { - throw UnsupportedOperationException() - } - } - } - - private fun Aggregatable<*>._mean(): DataFrame { - return when (this) { - is Pivot<*> -> { - this.mean().toDataFrame() - } - is DataFrame<*> -> { - this.mean().toDataFrame() - } - is GroupBy<*, *> -> { - this.mean(*aggregateFields) - } - is PivotGroupBy<*> -> { - this.mean(*aggregateFields) - } - else -> { - throw UnsupportedOperationException() - } - } - } - - /** - * Returns the number of columns managed by the data source object. - * - * @return the number or columns to display - */ - fun getColumnCount(): Int = model.getColumnCount() - - /** - * Returns the number of records managed by the data source object. - * - * @return the number or rows in the model - */ - fun getRowCount(): Int = model.getRowCount() - - private fun Aggregatable<*>._sum(): DataFrame { - return when (this) { - is Pivot<*> -> { - this.sum(*aggregateFields).toDataFrame() - } - is DataFrame<*> -> { - this.sum().toDataFrame() - } - is GroupBy<*, *> -> { - this.sum(*aggregateFields) - } - is PivotGroupBy<*> -> { - (this as PivotGroupBy).sum(*aggregateFields) - } - else -> { - throw UnsupportedOperationException() - } - } - } - - private fun Aggregatable<*>._min(): DataFrame { - return when (this) { - is Pivot<*> -> { - this.min().toDataFrame() - } - is DataFrame<*> -> { - this.min().toDataFrame() - } - is GroupBy<*, *> -> { - this.min(*aggregateFields) - } - is PivotGroupBy<*> -> { - this.min(*aggregateFields) - } - else -> { - throw UnsupportedOperationException() - } - } - } - - companion object { - const val TYP_CSV = 1 - const val TYP_PDF = 2 - const val TYP_XLS = 3 - const val TYP_XLSX = 4 - - init { - WindowController.windowController.registerWindowBuilder( - org.kopi.galite.visual.Constants.MDL_PIVOT_TABLE, - object : WindowBuilder { - override fun createWindow(model: VWindow): UWindow { - return UIFactory.uiFactory.createView( - model) as UPivotTable - } - } - ) - } - } - - @PublishedApi - internal val `access$sourceFile`: String get() = - this.javaClass.`package`.name.replace(".", "/") + - File.separatorChar + - this.javaClass.simpleName -} - -enum class Function { - NONE, - SUM, - MEAN, - MIN, - MAX -} - -class Grouping(val columns: List>, val rows: List>) diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivottable/Span.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivottable/Span.kt deleted file mode 100644 index 6e2e2013d..000000000 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivottable/Span.kt +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN - * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -package org.kopi.galite.visual.pivottable - -enum class Span { - NONE, - ROW, - COL -} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivottable/UPivotTable.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivottable/UPivotTable.kt deleted file mode 100644 index 0a5f75a40..000000000 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivottable/UPivotTable.kt +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN - * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -package org.kopi.galite.visual.pivottable - -import org.kopi.galite.visual.report.UReport - -/** - * `UPivotTable` is the top-level interface that must be implemented - * by all pivot tables. It is the visual component of the [PivotTable] model. - */ -interface UPivotTable : UReport diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivottable/DPivotTable.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivottable/DPivotTable.kt deleted file mode 100644 index d963e3e30..000000000 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivottable/DPivotTable.kt +++ /dev/null @@ -1,278 +0,0 @@ -/* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN - * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.kopi.galite.visual.ui.vaadin.pivottable - -import java.awt.Color - -import org.kopi.galite.visual.pivottable.PivotTable -import org.kopi.galite.visual.pivottable.UPivotTable -import org.kopi.galite.visual.report.Parameters -import org.kopi.galite.visual.report.Point -import org.kopi.galite.visual.report.UReport -import org.kopi.galite.visual.ui.vaadin.base.BackgroundThreadHandler.access -import org.kopi.galite.visual.ui.vaadin.base.BackgroundThreadHandler.accessAndPush -import org.kopi.galite.visual.ui.vaadin.visual.DWindow - -import com.vaadin.flow.component.Component -import com.vaadin.flow.component.HasComponents -import com.vaadin.flow.component.Unit -import com.vaadin.flow.component.button.Button -import com.vaadin.flow.component.dnd.DragSource -import com.vaadin.flow.component.dnd.DropEffect -import com.vaadin.flow.component.dnd.DropTarget -import com.vaadin.flow.component.dnd.EffectAllowed -import com.vaadin.flow.component.grid.Grid -import com.vaadin.flow.component.orderedlayout.HorizontalLayout -import com.vaadin.flow.component.orderedlayout.VerticalLayout -import com.vaadin.flow.component.select.Select - -/** - * The `DPivotTable` is the visual part of the [PivotTable] model. - * - * The `DPivotTable` ensure the implementation of the [UPivotTable] - * specifications. - * - * @param pivottable The report model. - */ -class DPivotTable(private val pivottable: PivotTable) : DWindow(pivottable), UPivotTable { - - //--------------------------------------------------- - // DATA MEMBERS - //--------------------------------------------------- - private val model = pivottable.model // report model - private lateinit var table: DTable - private var parameters: Parameters? = null - private val mainLayout = org.kopi.galite.visual.ui.vaadin.common.VTable(3, 2) - - init { - getModel()!!.setDisplay(this) - setSizeFull() - } - - //--------------------------------------------------- - // IMPLEMENTATIONS - //--------------------------------------------------- - override fun run() { - pivottable.initPivotTable() - table.focus() - setInfoTable() - } - - override fun build() { - // load personal configuration - parameters = Parameters(Color(71, 184, 221)) - table = DTable(VTable(model, buildRows())) - table.isColumnReorderingAllowed = true - // 200 px is approximately the header window size + the actor pane size - ui.ifPresent { ui -> - ui.page.retrieveExtendedClientDetails { - table.setHeight(it.windowInnerHeight.toFloat() - 200, Unit.PIXELS) - } - } - initLayout() - setContent(mainLayout) - resetWidth() - addTableListeners() - } - - private fun initLayout() { - addAggregations() - addAllGroupingFields() - addRowGroupingFields() - addColumnGroupingFields() - mainLayout.add(2, 1, table) - } - - private fun addAggregations() { - val aggregationLayout = VerticalLayout() - val aggregations = Select("Sum", "Mean", "Min", "Max") // TODO - val fields = Select() - - fields.setItems(pivottable.columns.map { it.label }) - - aggregationLayout.add(aggregations) - aggregationLayout.add(fields) - mainLayout.add(1, 0, aggregationLayout) - } - - private fun addAllGroupingFields() { - val fieldsContainer = HorizontalLayout() - - setDropTargetOf(fieldsContainer) - - pivottable.columns.forEach { - val button = Button(it.label) - val draggableButton = DragSource.create(button) - - draggableButton.effectAllowed = EffectAllowed.MOVE - fieldsContainer.add(button) - } - - mainLayout.add(0, 1, fieldsContainer) - } - - private fun addRowGroupingFields() { - val groupingFields = buildGroupingFieldsLayout() - - mainLayout.add(2, 0, groupingFields) - } - - private fun addColumnGroupingFields() { - val groupingFields = buildGroupingFieldsLayout() - - mainLayout.add(1, 1, groupingFields) - } - - private fun buildGroupingFieldsLayout(): VerticalLayout { - val groupingFields = VerticalLayout() - - setDropTargetOf(groupingFields) - - return groupingFields - } - - private fun setDropTargetOf(groupingFieldsLayout: T) where T: HasComponents, T: Component { - val dndLayout = DropTarget.create(groupingFieldsLayout) - - dndLayout.dropEffect = DropEffect.MOVE - - dndLayout.addDropListener { - groupingFieldsLayout.add(it.component) - } - } - - override fun redisplay() { - contentChanged() - } - - override fun removeColumn(position: Int) { - - } - - override fun addColumn(position: Int) { - - } - - override fun addColumn() { - - } - - override fun getTable(): UReport.UTable { - return table - } - - override fun contentChanged() { - if (this::table.isInitialized) { - accessAndPush(currentUI) { - table.setItems(buildRows()) - table.model.fireContentChanged() - } - } - } - - override fun columnMoved(pos: IntArray) { - - } - - override fun resetWidth() { - access(currentUI) { - table.resetWidth() - } - } - - override fun getSelectedColumn(): Int { - return table.selectedColumn - } - - override fun getSelectedCell(): Point = Point(table.selectedColumn, table.selectedRow) - - override fun setColumnLabel(column: Int, label: String) { - access(currentUI) { - table.getColumnByKey(column.toString()).setHeader(label) - } - } - - /** - * Return the columns display order. - * @return The columns display order. - */ - val displayOrder: IntArray - get() { - val displayOrder = IntArray(model.getColumnCount()) - for (i in 0 until model.getColumnCount()) { - displayOrder[i] = table.convertColumnIndexToModel(i) - } - return displayOrder - } - - /** - * Returns the number of columns displayed in the table - * @return The number of columns displayed - */ - val columnCount: Int - get() = table.getColumnCount() - - /** - * Add listeners to the report table. - */ - private fun addTableListeners() { - - } - - private fun addHeaderListeners(gridColumn: Grid.Column<*>, header: VerticalLayout) { - - } - - fun getSelectedColumnIndex(gridColumn: Grid.Column<*>): Int = gridColumn.key.toInt() - - /** - * Display table information in the footer of the table - */ - private fun setInfoTable() { - - } - - /** - * Builds the grid rows. - */ - private fun buildRows(): List { - val rows = mutableListOf() - for (i in 0 until model.getRowCount()) { - rows.add(ReportModelItem(i)) - } - return rows - } - - //--------------------------------------------------- - // TABLE MODEL ITEM - //--------------------------------------------------- - /** - * The `TableModelItem` is the report table - * data model. - * - * @param rowIndex The row index. - */ - inner class ReportModelItem(val rowIndex: Int) { - //--------------------------------------- - // IMPLEMENTATIONS - //--------------------------------------- - fun getValueAt(columnIndex: Int): String { - return model.getValueAt(rowIndex, columnIndex) - } - } -} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivottable/DTable.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivottable/DTable.kt deleted file mode 100644 index 67c80d45e..000000000 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivottable/DTable.kt +++ /dev/null @@ -1,212 +0,0 @@ -/* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN - * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.kopi.galite.visual.ui.vaadin.pivottable - -import org.kopi.galite.visual.pivottable.Span -import org.kopi.galite.visual.report.UReport.UTable - -import com.vaadin.flow.component.AttachEvent -import com.vaadin.flow.component.DetachEvent -import com.vaadin.flow.component.dependency.CssImport -import com.vaadin.flow.component.grid.Grid -import com.vaadin.flow.component.grid.GridVariant -import com.vaadin.flow.component.page.Page -import com.vaadin.flow.function.ValueProvider -import com.vaadin.flow.shared.Registration - -import elemental.json.JsonObject -import elemental.json.JsonValue - -/** - * The `DTable` is a table implementing the [UTable] - * specifications. - * - * @param model The table model. - */ - -@CssImport.Container(value = [ - CssImport("./styles/galite/report.css"), - CssImport(value = "./styles/galite/report.css", themeFor = "vaadin-grid") -]) -class DTable(val model: VTable) : Grid(), UTable { - - //--------------------------------------------------- - // DATA MEMBERS - //--------------------------------------------------- - - /** - * The table selected row. - */ - val selectedRow: Int get() = asSingleSelect().value?.rowIndex ?: -1 - - /** - * The selected column. - */ - var selectedColumn = -1 - - /** - * The indexes of the columns in the grid view - */ - var viewColumns = mutableListOf() - - lateinit var browserWindowResizeListener: Registration - - init { - setItems(model) - buildColumns() - addThemeVariants(GridVariant.LUMO_COMPACT, GridVariant.LUMO_COLUMN_BORDERS) - themeNames.add("report") - classNames.add("small") - classNames.add("borderless") - classNames.add("report") - setWidthFull() - } - - //--------------------------------------------------- - // IMPLEMENTATIONS - //--------------------------------------------------- - - override fun onAttach(attachEvent: AttachEvent) { - val page = attachEvent.ui.page - - page.setWindowHeight() - - browserWindowResizeListener = page.addBrowserWindowResizeListener { event -> - height = (event.height - 200).toString() + "px" - } - } - - private fun Page.setWindowHeight() { - val js = "return Vaadin.Flow.getBrowserDetailsParameters();" - executeJs(js).then { - height = ((it as JsonObject).get("v-wh").asNumber() - 200).toString() + "px" - } - } - - override fun onDetach(detachEvent: DetachEvent) { - browserWindowResizeListener.remove() - } - - /** - * Builds the grid columns. - */ - private fun buildColumns() { - repeat(model.getColumnCount()) { index -> - val gridColumn = addColumn(index) - - gridColumn.flexGrow = 0 - } - } - - /** - * Maps the index of the column in the grid at [viewColumnIndex] to the index of the column in the table model. - */ - override fun convertColumnIndexToModel(viewColumnIndex: Int): Int = viewColumns[viewColumnIndex] - - /** - * Maps the index of the column in the table model at [modelColumnIndex] to the index of the column in the grid. - */ - override fun convertColumnIndexToView(modelColumnIndex: Int): Int = viewColumns.indexOf(modelColumnIndex) - - /** - * Adds a new text column to this table with a column value provider and a key for the column. - * - * @param key the key of the column provider - * @return the created column - */ - fun addColumn(key: Int): Column { - val provider = ColumnValueProvider(key) - - viewColumns.add(key) - - return addColumn(provider).also { - provider.column = it - it.setKey(key.toString()) - .setResizable(true) - .setSortable(false) - .setClassNameGenerator { item -> - buildString { - val isTitle = model.model.isTitle(item.rowIndex, key) - val span = model.model.getSpan(item.rowIndex, key) - - if (isTitle) { - append("title ") - } - - if (item.rowIndex == model.getRowCount () - 1) { - append("last-row ") - } - - if (span == Span.COL) { - append("colspan") - } else if (span == Span.ROW) { - append("rowspan") - } - } - } - } - } - - override fun removeColumnByKey(columnKey: String) { - viewColumns.remove(columnKey.toInt()) - super.removeColumnByKey(columnKey) - } - - override fun removeColumn(column: Column) { - viewColumns.remove(column.key.toInt()) - super.removeColumn(column) - } - - /** - * Returns the column count. - * @return the column count. - */ - fun getColumnCount(): Int = model.getColumnCount() - - /** - * Reset all columns widths. - */ - fun resetWidth() { - for (i in 0 until model.getColumnCount()) { - resetColumnSize(i) - } - } - - /** - * Resets the column size at a given position. - * @param pos The column position. - */ - private fun resetColumnSize(pos: Int) { - - } - - /** - * Provides the value for the column with index [columnIndex] - * - * @param columnIndex the index of the column - */ - inner class ColumnValueProvider( - private val columnIndex: Int - ) : ValueProvider { - var column: Column? = null - - override fun apply(source: DPivotTable.ReportModelItem): String { - return source.getValueAt(columnIndex) - } - } -} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivottable/VTable.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivottable/VTable.kt deleted file mode 100644 index f3591230d..000000000 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivottable/VTable.kt +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN - * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.kopi.galite.visual.ui.vaadin.pivottable - -import org.kopi.galite.visual.pivottable.MPivotTable - -import com.vaadin.flow.component.grid.Grid -import com.vaadin.flow.data.provider.ListDataProvider -import com.vaadin.flow.data.provider.Query -import com.vaadin.flow.function.SerializablePredicate - -/** - * The VTable is a vaadin [Grid] data provider adapted - * to dynamic reports needs. - * - * @param model The table model. - */ -class VTable( - internal val model: MPivotTable, - reportItems: List -): ListDataProvider(reportItems) { - - init { - addFilter { - it != null - } - } - - override fun size(query: Query>?): Int { - return model.getRowCount() - } - - /** - * Notify the report table that the report content has been - * change in order to update the table content. - */ - fun fireContentChanged() { - refreshAll() - } - - /** - * Returns the column count. - * @return the column count. - */ - fun getColumnCount(): Int = model.getColumnCount() - - /** - * Returns the row count. - * @return the row count. - */ - fun getRowCount(): Int = model.getRowCount() -} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/visual/VUIFactory.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/visual/VUIFactory.kt index 7a820a417..bdab2ecb8 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/visual/VUIFactory.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/visual/VUIFactory.kt @@ -21,13 +21,11 @@ import org.kopi.galite.visual.base.UComponent import org.kopi.galite.visual.chart.VChart import org.kopi.galite.visual.form.VForm import org.kopi.galite.visual.form.VListDialog -import org.kopi.galite.visual.pivottable.PivotTable import org.kopi.galite.visual.preview.VPreviewWindow import org.kopi.galite.visual.report.VReport import org.kopi.galite.visual.ui.vaadin.chart.DChart import org.kopi.galite.visual.ui.vaadin.form.DForm import org.kopi.galite.visual.ui.vaadin.form.DListDialog -import org.kopi.galite.visual.ui.vaadin.pivottable.DPivotTable import org.kopi.galite.visual.ui.vaadin.preview.DPreviewWindow import org.kopi.galite.visual.ui.vaadin.report.DReport import org.kopi.galite.visual.UIFactory @@ -70,9 +68,6 @@ class VUIFactory : UIFactory() { is VListDialog -> { createListDialog(model) } - is PivotTable -> { - createPivotTable(model) - } else -> { throw IllegalArgumentException("NO UI IMPLEMENTATION FOR " + model.javaClass) } @@ -154,13 +149,4 @@ class VUIFactory : UIFactory() { internal fun createListDialog(model: VListDialog): DListDialog { return DListDialog(model) } - - /** - * Creates the [DPivotTable] from a given model. - * @param model The pivot table model - * @return The [DPivotTable] view. - */ - internal fun createPivotTable(model: PivotTable): DPivotTable { - return DPivotTable(model) - } } From e8472eebaf53e344c2ff6c8e5b1995533fd5c265 Mon Sep 17 00:00:00 2001 From: Super User Date: Wed, 18 Oct 2023 14:19:03 +0100 Subject: [PATCH 03/20] implement pivot table structure --- .../org/kopi/galite/visual/domain/Domain.kt | 35 + .../galite/visual/dsl/form/DictionaryForm.kt | 7 + .../org/kopi/galite/visual/dsl/form/Form.kt | 10 + .../visual/dsl/pivotTable/FieldAlignment.kt | 26 + .../visual/dsl/pivotTable/PivotTable.kt | 406 +++++++ .../visual/dsl/pivotTable/ReportField.kt | 191 +++ .../pivotTable/ReportLocalizationWriter.kt | 70 ++ .../galite/visual/dsl/pivotTable/ReportRow.kt | 92 ++ .../galite/visual/form/VDictionaryForm.kt | 18 + .../pivotTable/CellStyleCacheManager.kt | 109 ++ .../galite/visual/pivotTable/ColumnStyle.kt | 93 ++ .../galite/visual/pivotTable/Constants.kt | 113 ++ .../galite/visual/pivotTable/MPivotTable.kt | 1049 +++++++++++++++++ .../kopi/galite/visual/pivotTable/PConfig.kt | 63 + .../galite/visual/pivotTable/Parameters.kt | 60 + .../kopi/galite/visual/pivotTable/Point.kt | 39 + .../visual/pivotTable/ReportListener.kt | 37 + .../galite/visual/pivotTable/UPivotTable.kt | 104 ++ .../kopi/galite/visual/pivotTable/VBaseRow.kt | 30 + .../visual/pivotTable/VBooleanCodeColumn.kt | 70 ++ .../visual/pivotTable/VBooleanColumn.kt | 72 ++ .../pivotTable/VCCDepthFirstCircuitN.kt | 60 + .../visual/pivotTable/VCalculateColumn.kt | 36 + .../galite/visual/pivotTable/VCellFormat.kt | 44 + .../galite/visual/pivotTable/VCodeColumn.kt | 104 ++ .../galite/visual/pivotTable/VDateColumn.kt | 81 ++ .../visual/pivotTable/VDecimalCodeColumn.kt | 75 ++ .../visual/pivotTable/VDecimalColumn.kt | 108 ++ .../visual/pivotTable/VDefaultReportActor.kt | 51 + .../galite/visual/pivotTable/VGroupRow.kt | 117 ++ .../visual/pivotTable/VHelpGenerator.kt | 117 ++ .../visual/pivotTable/VIntegerCodeColumn.kt | 103 ++ .../visual/pivotTable/VIntegerColumn.kt | 73 ++ .../galite/visual/pivotTable/VMonthColumn.kt | 62 + .../visual/pivotTable/VNoRowException.kt | 32 + .../galite/visual/pivotTable/VPivotTable.kt | 560 +++++++++ .../galite/visual/pivotTable/VReportColumn.kt | 146 +++ .../visual/pivotTable/VReportCommand.kt | 112 ++ .../galite/visual/pivotTable/VReportRow.kt | 81 ++ .../visual/pivotTable/VSeparatorColumn.kt | 56 + .../visual/pivotTable/VStringCodeColumn.kt | 83 ++ .../galite/visual/pivotTable/VStringColumn.kt | 57 + .../galite/visual/pivotTable/VTimeColumn.kt | 81 ++ .../visual/pivotTable/VTimestampColumn.kt | 81 ++ .../galite/visual/pivotTable/VWeekColumn.kt | 61 + .../visual/pivotTable/triggers/Triggers.kt | 286 +++++ .../vaadin/pivotTable/ColumnStyleGenerator.kt | 50 + .../ui/vaadin/pivotTable/ColumnsSelector.kt | 61 + .../ui/vaadin/pivotTable/DPivotTable.kt | 455 +++++++ .../visual/ui/vaadin/pivotTable/DTable.kt | 255 ++++ .../ui/vaadin/pivotTable/ReportCellStyler.kt | 137 +++ .../visual/ui/vaadin/pivotTable/VTable.kt | 75 ++ .../visual/ui/vaadin/visual/VUIFactory.kt | 13 + .../galite/visual/dsl/form/Form-ar_TN.xml | 1 + .../galite/visual/dsl/form/Form-de_AT.xml | 1 + .../galite/visual/dsl/form/Form-en_GB.xml | 1 + .../galite/visual/dsl/form/Form-fr_FR.xml | 1 + .../org/kopi/galite/demo/bill/BillForm.kt | 6 + .../kotlin/org/kopi/galite/demo/bill/BillP.kt | 113 ++ .../demo/billproduct/BillProductForm.kt | 6 + .../galite/demo/billproduct/BillProductP.kt | 67 ++ .../org/kopi/galite/demo/client/ClientForm.kt | 1 + .../kopi/galite/demo/command/CommandForm.kt | 1 + .../kopi/galite/demo/product/ProductForm.kt | 1 + .../kopi/galite/demo/provider/ProviderForm.kt | 6 + .../kopi/galite/demo/provider/ProviderP.kt | 110 ++ .../org/kopi/galite/demo/stock/StockForm.kt | 6 + .../org/kopi/galite/demo/stock/StockP.kt | 93 ++ .../kopi/galite/demo/taxRule/TaxRuleForm.kt | 6 + .../org/kopi/galite/demo/taxRule/TaxRuleP.kt | 82 ++ 70 files changed, 6909 insertions(+) create mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/FieldAlignment.kt create mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTable.kt create mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/ReportField.kt create mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/ReportLocalizationWriter.kt create mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/ReportRow.kt create mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/CellStyleCacheManager.kt create mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/ColumnStyle.kt create mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/Constants.kt create mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/MPivotTable.kt create mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/PConfig.kt create mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/Parameters.kt create mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/Point.kt create mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/ReportListener.kt create mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/UPivotTable.kt create mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VBaseRow.kt create mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VBooleanCodeColumn.kt create mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VBooleanColumn.kt create mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VCCDepthFirstCircuitN.kt create mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VCalculateColumn.kt create mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VCellFormat.kt create mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VCodeColumn.kt create mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VDateColumn.kt create mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VDecimalCodeColumn.kt create mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VDecimalColumn.kt create mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VDefaultReportActor.kt create mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VGroupRow.kt create mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VHelpGenerator.kt create mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VIntegerCodeColumn.kt create mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VIntegerColumn.kt create mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VMonthColumn.kt create mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VNoRowException.kt create mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VPivotTable.kt create mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VReportColumn.kt create mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VReportCommand.kt create mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VReportRow.kt create mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VSeparatorColumn.kt create mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VStringCodeColumn.kt create mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VStringColumn.kt create mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VTimeColumn.kt create mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VTimestampColumn.kt create mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VWeekColumn.kt create mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/triggers/Triggers.kt create mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/ColumnStyleGenerator.kt create mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/ColumnsSelector.kt create mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/DPivotTable.kt create mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/DTable.kt create mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/ReportCellStyler.kt create mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/VTable.kt create mode 100644 galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/bill/BillP.kt create mode 100644 galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/billproduct/BillProductP.kt create mode 100644 galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/provider/ProviderP.kt create mode 100644 galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/stock/StockP.kt create mode 100644 galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/taxRule/TaxRuleP.kt diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/domain/Domain.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/domain/Domain.kt index 091b8b533..044ed1488 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/domain/Domain.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/domain/Domain.kt @@ -274,6 +274,41 @@ open class Domain(val width: Int? = null, } } + /** + * Builds the pivot table column model + */ + open fun buildReportFieldModel(field: org.kopi.galite.visual.dsl.pivotTable.ReportField<*>, function: org.kopi.galite.visual.pivotTable.VCalculateColumn?, format: org.kopi.galite.visual.pivotTable.VCellFormat?): org.kopi.galite.visual.pivotTable.VReportColumn { + return with(field) { + when (kClass) { + Int::class, Long::class -> + org.kopi.galite.visual.pivotTable.VIntegerColumn(ident, options, align.value, groupID, function, width ?: 0, format) + String::class -> + org.kopi.galite.visual.pivotTable.VStringColumn( + ident, options, align.value, groupID, function, width ?: 0, + height ?: 0, format + ) + BigDecimal::class -> + org.kopi.galite.visual.pivotTable.VDecimalColumn( + ident, options, align.value, groupID, function, width ?: 0, + height ?: 0, format + ) + Boolean::class -> + org.kopi.galite.visual.pivotTable.VBooleanColumn(ident, options, align.value, groupID, function, format) + org.joda.time.LocalDate::class, LocalDate::class, java.sql.Date::class, java.util.Date::class -> + org.kopi.galite.visual.pivotTable.VDateColumn(ident, options, align.value, groupID, function, width ?: 0, format) + Month::class -> + org.kopi.galite.visual.pivotTable.VMonthColumn(ident, options, align.value, groupID, function, format) + Week::class -> + org.kopi.galite.visual.pivotTable.VWeekColumn(ident, options, align.value, groupID, function, format) + org.joda.time.LocalTime::class, LocalTime::class -> + org.kopi.galite.visual.pivotTable.VTimeColumn(ident, options, align.value, groupID, function, format) + Instant::class, LocalDateTime::class, DateTime::class -> + org.kopi.galite.visual.pivotTable.VTimestampColumn(ident, options, align.value, groupID, function, format) + else -> throw java.lang.RuntimeException("Type ${kClass!!.qualifiedName} is not supported") + } + } + } + /** * Returns the default alignment */ diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/form/DictionaryForm.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/form/DictionaryForm.kt index c26e6f74a..316448fd1 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/form/DictionaryForm.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/form/DictionaryForm.kt @@ -21,6 +21,7 @@ import java.util.Locale import org.kopi.galite.visual.ApplicationContext import org.kopi.galite.visual.VException import org.kopi.galite.visual.cross.VDynamicReport +import org.kopi.galite.visual.dsl.pivotTable.PivotTable import org.kopi.galite.visual.dsl.report.Report import org.kopi.galite.visual.form.VDictionaryForm @@ -123,6 +124,12 @@ abstract class DictionaryForm(title: String, locale: Locale? = null) : Form(titl VDynamicReport.createDynamicReport(this.block) } + protected fun Block.createPivotTable(reportbuilder: () -> PivotTable) { + model.createPivotTable(block) { + reportbuilder().model + } + } + // ---------------------------------------------------------------------- // DICTIONARY FORM MODEL // ---------------------------------------------------------------------- diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/form/Form.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/form/Form.kt index 5101cab45..3858cac67 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/form/Form.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/form/Form.kt @@ -370,6 +370,7 @@ abstract class Form(title: String, locale: Locale? = null) : Window(title, local save delete dynamicReport + pivotTable help showHideFilter report @@ -451,6 +452,8 @@ abstract class Form(title: String, locale: Locale? = null) : Window(title, local open val dynamicReport by lazy { actor(CreateDynamicReport()) } + open val pivotTable by lazy { actor(CreatePivotTable()) } + open val showHideFilter by lazy { actor(ShowHideFilter()) } open val help by lazy { actor(Help()) } @@ -713,6 +716,13 @@ abstract class Form(title: String, locale: Locale? = null) : Window(title, local } } + class CreatePivotTable : Actor(menu = ActionMenu(), label = "Pivot Table", help = "Create pivot table.", userActor = false) { + init { + key = Key.F10 + icon = Icon.REPORT + } + } + class ShowHideFilter : Actor(menu = ActionMenu(), label = "Show/Hide filter", help = "Show or hide block filters.", userActor = false) { init { key = Key.SHIFT_F12 diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/FieldAlignment.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/FieldAlignment.kt new file mode 100644 index 000000000..372972cb6 --- /dev/null +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/FieldAlignment.kt @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +package org.kopi.galite.visual.dsl.pivotTable + +import org.kopi.galite.visual.report.Constants + +enum class FieldAlignment(val value: Int) { + DEFAULT(Constants.ALG_DEFAULT), + CENTER(Constants.ALG_CENTER), + LEFT(Constants.ALG_LEFT), + RIGHT(Constants.ALG_RIGHT), +} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTable.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTable.kt new file mode 100644 index 000000000..fa4d62972 --- /dev/null +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTable.kt @@ -0,0 +1,406 @@ +/* + * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package org.kopi.galite.visual.dsl.pivotTable + +import java.io.IOException +import java.util.Locale +import org.jetbrains.exposed.sql.ExpressionWithColumnType +import org.jetbrains.exposed.sql.Op + +import org.kopi.galite.visual.domain.Domain +import org.kopi.galite.visual.dsl.common.Action +import org.kopi.galite.visual.dsl.common.LocalizationWriter +import org.kopi.galite.visual.dsl.common.ReportTrigger +import org.kopi.galite.visual.dsl.common.Trigger +import org.kopi.galite.visual.dsl.common.Window +import org.kopi.galite.visual.form.VConstants +import org.kopi.galite.visual.form.VField +import org.kopi.galite.visual.pivotTable.Constants +import org.kopi.galite.visual.pivotTable.VPivotTable +import org.kopi.galite.visual.pivotTable.VSeparatorColumn +import org.kopi.galite.visual.ApplicationContext + +/** + * Represents a report that contains fields [fields] and displays a table of [reportRows]. + + * @param title The title of this form. + * @param help The help text. + * @param locale the window locale. + */ +abstract class PivotTable(title: String, val help: String?, locale: Locale? = null) : Window(title, locale) { + + constructor(title: String, locale: Locale? = null) : this(title, null, locale) + + /** Report's fields. */ + val fields = mutableListOf>() + + /** Report's data rows. */ + val reportRows = mutableListOf() + + /** + * creates and returns a field. It uses [init] method to initialize the field. + * + * @param domain the domain of the field. + * @param init initialization method. + * @return a field. + */ + inline fun ?> field(domain: Domain, + noinline init: ReportField.() -> Unit): ReportField { + domain.kClass = T::class + + val field = ReportField(domain, init, "ANM_${fields.size}", domain.source.ifEmpty { `access$sourceFile` }) + + field.initialize() + + val pos = if(model.model.columns.size == 0) 0 else model.model.columns.size - 1 // TODO!! + model.model.columns.add(pos, field.buildReportColumn()) + fields.add(field) + field.addFieldTriggers() + + return field + } + + fun ReportField<*>.addFieldTriggers() { + // FIELD TRIGGERS + val fieldTriggerArray = arrayOfNulls(Constants.TRG_TYPES.size) + if (computeTrigger != null) { + fieldTriggerArray[Constants.TRG_COMPUTE] = computeTrigger!! + } + if (formatTrigger != null) { + fieldTriggerArray[Constants.TRG_FORMAT] = formatTrigger!! + } + // TODO : Add field triggers here + this@PivotTable.model.VKT_Fields_Triggers.add(fieldTriggerArray) + } + + /** + * creates and returns a field that accept nulls. It uses [init] method to initialize the field. + * + * @param domain the domain of the field. + * @param init initialization method. + * @return a field. + */ + inline fun ?> nullableField(domain: Domain, + noinline init: ReportField.() -> Unit): ReportField { + return field(domain, init) as ReportField + } + + /** + * creates and returns fields. It uses [init] method to initialize the fields. + * + * @param fieldsNumber the number of fields to create. + * @param domain the domain of the field. + * @param init initialization method. + * @return a field. + */ + inline fun ?> field(fieldsNumber: Int, + domain: Domain, + noinline init: ReportField.() -> Unit): List> { + return (0 until fieldsNumber).map { + nullableField(domain, init).also { field -> + field.model.label = "${field.label}_${it + 1}" + } + } + } + + /** + * creates and returns fields that accept nulls. It uses [init] method to initialize the fields. + * + * @param fieldsNumber the number of fields to create. + * @param domain the domain of the field. + * @param init initialization method. + * @return a field. + */ + inline fun ?> nullableField(fieldsNumber: Int, + domain: Domain, + noinline init: ReportField.() -> Unit): List> { + return (0 until fieldsNumber).map { + field(domain, init).also { field -> + field.model.label = "${field.label}_${it + 1}" + } + } + } + + /** + * Adds a row to the report. + * + * @param init initializes the row with values. + */ + fun add(init: ReportRow.() -> Unit) { + val row = ReportRow(fields) + row.init() + + val list = row.addReportLine() + // Last null value is added for the separator column + model.model.addLine((list + listOf(null)).toTypedArray()) + + reportRows.add(row) + } + + private fun ReportRow.addReportLine(): List { + return fields.map { field -> + data[field] + } + } + + /** + * Adds report trigger to this block. + * + * @param reportTriggerEvents the trigger events to add + * @param method the method to execute when trigger is called + */ + fun trigger(vararg reportTriggerEvents: ReportTriggerEvent, method: () -> T): Trigger { + val event = reportEventList(reportTriggerEvents) + val reportAction = Action(null, method) + val trigger = ReportTrigger(event, reportAction) + + triggers.add(trigger) + // REPORT TRIGGERS + for (i in VConstants.TRG_TYPES.indices) { + if (trigger.events shr i and 1 > 0) { + model.VKT_Report_Triggers[0][i] = trigger + } + } + + return trigger + } + + private fun reportEventList(reportTriggerEvents: Array>): Long { + var self = 0L + + reportTriggerEvents.forEach { trigger -> + self = self or (1L shl trigger.event) + } + + return self + } + + /** + * Returns the row's data. + * + * @param rowNumber the index of the desired row. + */ + fun getRow(rowNumber: Int): MutableMap, Any?> = reportRows[rowNumber].data + + /** + * Returns rows of data for a specific [field]. + * + * @param field the field. + */ + fun getRowsForField(field: ReportField<*>) = reportRows.map { it.data[field] } + + /** + * Adds default report commands + */ + open val reportCommands = false + + /////////////////////////////////////////////////////////////////////////// + // REPORT TRIGGERS + /////////////////////////////////////////////////////////////////////////// + /** + * Block Triggers + * + * @param event the event of the trigger + */ + open class ReportTriggerEvent(val event: Int) + + /** + * Executed before the report is displayed. + */ + val PREREPORT = ReportTriggerEvent(Constants.TRG_PREREPORT) + + /** + * Executed after the report is closed. + */ + val POSTREPORT = ReportTriggerEvent(Constants.TRG_POSTREPORT) + + // ---------------------------------------------------------------------- + // METHODS FOR SQL + // ---------------------------------------------------------------------- + /** + * creates an SQL condition, so that the column have to fit the + * requirements (value and search operator) of the field. + */ + protected fun buildSQLCondition(column: ExpressionWithColumnType, field: VField): Op { + return field.getSearchCondition(column) ?: Op.TRUE + } + + /** + * Returns true if there is trigger associated with given event. + */ + protected fun hasTrigger(event: Int): Boolean = model.hasTrigger(event) + + /** + * Returns true if there is trigger associated with given event. + */ + protected fun hasCommandTrigger(event: Int, index: Int): Boolean = model.hasCommandTrigger(event, index) + + fun setMenu() { + model.setMenu() + } + + // ---------------------------------------------------------------------- + // HELP + // ---------------------------------------------------------------------- + + fun genHelp(): String? = model.genHelp() + + fun showHelp() { + model.showHelp() + } + + fun addDefaultReportCommands() { + model.addDefaultReportCommands() + } + + + /** + * Sets the title + */ + fun setPageTitle(title: String) { + model.setPageTitle(title) + } + + fun setPageTitleParams(param: Any) { + model.setPageTitleParams(param) + } + + fun setPageTitleParams(param1: Any, param2: Any) { + model.setPageTitleParams(param1, param2) + } + + fun setPageTitleParams(params: Array) { + model.setPageTitleParams(params) + } + + fun setFirstPageHeader(firstPageHeader: String) { + model.setFirstPageHeader(firstPageHeader) + } + + fun foldSelection() { + model.foldSelection() + } + + fun unfoldSelection() { + model.unfoldSelection() + } + + fun foldSelectedColumn() { + model.foldSelectedColumn() + } + + fun unfoldSelectedColumn() { + model.unfoldSelectedColumn() + } + + /** + * Sort the displayed tree wrt to a column + */ + fun sortSelectedColumn() { + model.sortSelectedColumn() + } + + /** + * Sort the displayed tree wrt to a column + */ + fun editLine() { + model.editLine() + } + + fun setColumnData() { + model.setColumnData() + } + + fun setColumnInfo() { + model.setColumnInfo() + } + + override fun addCommandTrigger() { + model.VKT_Commands_Triggers.add(arrayOfNulls(Constants.TRG_TYPES.size)) + } + + // ---------------------------------------------------------------------- + // XML LOCALIZATION GENERATION + // ---------------------------------------------------------------------- + + override fun genLocalization(destination: String?, locale: Locale?) { + if (locale != null) { + val baseName = this::class.simpleName + requireNotNull(baseName) + val localizationDestination = destination + ?: (this.javaClass.classLoader.getResource("")?.path + + this.javaClass.`package`.name.replace(".", "/")) + try { + val writer = ReportLocalizationWriter() + genLocalization(writer) + writer.write(localizationDestination, baseName, locale) + } catch (ioe: IOException) { + ioe.printStackTrace() + System.err.println("cannot write : $baseName") + } + } + } + + fun genLocalization(writer: LocalizationWriter) { + (writer as ReportLocalizationWriter).genReport(title, help, fields, menus, actors) + } + + // ---------------------------------------------------------------------- + // REPORT MODEL + // ---------------------------------------------------------------------- + override val model: VPivotTable = object : VPivotTable() { + init { + // TODO: for separator column + if(VKT_Fields_Triggers.size == 0) { + VKT_Fields_Triggers.add(arrayOfNulls(Constants.TRG_TYPES.size)) + } else { + VKT_Fields_Triggers.add(VKT_Fields_Triggers.size - 1, arrayOfNulls(Constants.TRG_TYPES.size)) + } + } + + override fun init() { + fields.forEach { + it.initField() + + if (it.group != null) { + it.groupID = fields.indexOf(it.group) + it.model.groups = it.groupID + } + } + } + + override val locale: Locale get() = this@PivotTable.locale ?: ApplicationContext.getDefaultLocale() + } + + init { + model.setTitle(title) + model.setPageTitle(title) + model.help = help + model.source = sourceFile + + if (reportCommands) { + addDefaultReportCommands() + } + + model.model.columns.add(VSeparatorColumn()) // TODO!!! + } + + @PublishedApi + internal val `access$sourceFile`: String + get() = sourceFile +} \ No newline at end of file diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/ReportField.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/ReportField.kt new file mode 100644 index 000000000..9bdb08982 --- /dev/null +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/ReportField.kt @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +package org.kopi.galite.visual.dsl.pivotTable + +import java.math.BigDecimal + +import org.kopi.galite.visual.domain.Domain +import org.kopi.galite.visual.dsl.common.Action +import org.kopi.galite.visual.dsl.common.LocalizationWriter +import org.kopi.galite.visual.dsl.common.ReportTrigger +import org.kopi.galite.visual.dsl.common.Trigger +import org.kopi.galite.visual.dsl.field.Field +import org.kopi.galite.visual.pivotTable.Constants +import org.kopi.galite.visual.pivotTable.VCalculateColumn +import org.kopi.galite.visual.pivotTable.VCellFormat +import org.kopi.galite.visual.pivotTable.VDecimalColumn +import org.kopi.galite.visual.pivotTable.VReportColumn +import org.kopi.galite.visual.VCommand + +/** + * This class represents the definition of a report field. + * + * @param domain The domain of this field. + * @param ident The identifier of this field, used to identify the field the localization file. + */ +class ReportField(override val domain: Domain, + val init: ReportField.() -> Unit, + ident: String? = null, + override val source: String?) : Field(domain, ident) { + /** the options of the field */ + internal var options: Int = 0 + + /** + * The fields you want to be grouped by the actual field. This creates clickable groups in your report. + * + * Example : + * + * val invoice = field() + * + * val customer = field() { + * group = invoice + * } + * + * In this report, you can click on the customer field to group invoices. + * + */ + var group: ReportField<*>? = null + + /** the alignment of the text */ + var align: FieldAlignment = FieldAlignment.DEFAULT + + /** the commands accessible in this field */ + lateinit var commands: Array + + /** the triggers executed by this field */ + internal val triggers = mutableListOf() + + /** compute trigger */ + internal var computeTrigger: Trigger? = null + + /** format trigger */ + internal var formatTrigger: Trigger? = null + + internal var groupID = -1 + + /** + * true if the field is hidden, false otherwise + */ + private val isHidden: Boolean get() = options and Constants.CLO_HIDDEN > 0 + + /** + * true if the field is hidden, false otherwise + */ + override var hidden: Boolean? = false + set(value) { + options = if (value == true) Constants.CLO_HIDDEN else Constants.CLO_VISIBLE + field = value + } + + fun initialize() { + initField() + if(domain.kClass == BigDecimal::class) { + align = FieldAlignment.RIGHT + } + } + + fun initField() { + init() + } + + /** + * executed when the report is displayed and can be used to compute expressions on the report columns and show + * the result. + * + * @param method The method to execute when compute trigger is executed. + */ + fun compute(method: () -> VCalculateColumn): ReportTrigger { + val fieldAction = Action(null, method) + return ReportTrigger(0L or (1L shl Constants.TRG_COMPUTE), fieldAction).also { + computeTrigger = it + } + } + + /** + * Changes the values of this field in a specific format. + * + * @param method The method to execute when compute trigger is executed. + */ + fun format(method: (value: T) -> String?): ReportTrigger { + val formatMethod = { + object : VCellFormat() { + override fun format(value: Any?): String = method(value as T).orEmpty() + } + } + val fieldAction = Action(null, formatMethod) + return ReportTrigger(0L or (1L shl Constants.TRG_FORMAT), fieldAction).also { + formatTrigger = it + } + } + + lateinit var model: VReportColumn + + fun buildReportColumn(): VReportColumn { + val function: VCalculateColumn? = if (computeTrigger != null) { + computeTrigger!!.action.method() as VCalculateColumn + } else { + null + } + + val format: VCellFormat? = if (formatTrigger != null) { + formatTrigger!!.action.method() as VCellFormat + } else { + null + } + + model = domain.buildReportFieldModel(this, function, format).also { column -> + column.label = label ?: "" + column.help = help + } + + return model + } + + // ---------------------------------------------------------------------- + // XML LOCALIZATION GENERATION + // ---------------------------------------------------------------------- + /** + * Generates localization for the field in the xml file + */ + override fun genLocalization(writer: LocalizationWriter) { + if (!isHidden) { + (writer as ReportLocalizationWriter).genField(ident, label, help) + } + } +} + +// ---------------------------------------------------------------------- +// DECIMAL FIELD FUNCTIONS +// ---------------------------------------------------------------------- + +/** + * Sets display scale to maxScale + * all values will be set to the same scale + */ +fun ReportField.setDisplayScale(scale: Int) { + (model as VDecimalColumn).setDisplayScale(scale) +} + +/** + * Sets maxScale + * all values with scale superior to maxScale will have + * maxScale as scale, and the other values will keep their scale. + */ +fun ReportField.setMaxScale(scale: Int) { + (model as VDecimalColumn).setMaxScale(scale) +} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/ReportLocalizationWriter.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/ReportLocalizationWriter.kt new file mode 100644 index 000000000..9b3a65199 --- /dev/null +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/ReportLocalizationWriter.kt @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +package org.kopi.galite.visual.dsl.pivotTable + +import org.jdom2.Element +import org.kopi.galite.visual.dsl.common.Actor +import org.kopi.galite.visual.dsl.common.LocalizationWriter +import org.kopi.galite.visual.dsl.common.Menu + +/** + * This class implements an XML localization file generator + */ +class ReportLocalizationWriter : LocalizationWriter() { + fun genReport(title: String?, + help: String?, + fields: MutableList>, + menus: MutableList, + actors: MutableList) { + val self = Element("report") + + self.setAttribute("title", title) + if (help != null) { + self.setAttribute("help", help) + } + pushNode(self) + // coll.genLocalization(this) TODO + + // Menus + menus.forEach { menu -> + menu.genLocalization(this) + } + + // Actors + actors.forEach { actor -> + actor.genLocalization(this) + } + + fields.forEach { field -> + field.genLocalization(this) + } + // do not pop: this is the root element + } + + fun genField(ident: String, label: String?, help: String?) { + val self = Element("field") + self.setAttribute("ident", ident) + if (label != null) { + self.setAttribute("label", label) + } + if (help != null) { + self.setAttribute("help", help) + } + peekNode(null).addContent(self) + } +} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/ReportRow.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/ReportRow.kt new file mode 100644 index 000000000..1de7dcae2 --- /dev/null +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/ReportRow.kt @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package org.kopi.galite.visual.dsl.pivotTable + +import org.jetbrains.exposed.sql.statements.api.ExposedBlob +import org.kopi.galite.type.Month +import org.kopi.galite.type.Type0 +import org.kopi.galite.type.Week + +/** + * Represents a data row of a [PivotTable]. + * + * @param reportFields the fields that exists in the report. + */ +class ReportRow(private val reportFields: MutableList>) { + /** A report data row */ + val data = mutableMapOf, Any?>() + + /** + * Returns data value of a specific [ReportField] in this report row. + * + * @param field the field. + * @return data value for a specific [ReportField]. + */ + @Suppress("UNCHECKED_CAST") + fun getValueOf(field: ReportField): T = data[field] as T + + /** + * Gets the value of the field in this report row. + * + * @param field the field. + * @return data value for a specific [ReportField]. + */ + operator fun get(field: ReportField): T = getValueOf(field) + + /** + * Sets the value of the field in this report row. + * + * @param field the field. + * @param value the field's value. + */ + operator fun set(field: ReportField, value: T) { + if (field in reportFields) { + data.putIfAbsent(field, value) + } + } + + /** + * Sets the value of the field in this report row. + * + * @param field the field. + * @param value the field's value. + */ + @JvmName("setType0") + operator fun , K> set(field: ReportField, value: K) { + if (field in reportFields) { + data.putIfAbsent(field, field.toType0(value)) + } + } +} + +/** + * Represents the value in sql + */ +fun ReportField<*>.toType0(value: T): Any? { + return when(value) { + is ExposedBlob -> value + is Int -> { + when (domain.kClass) { + Month::class -> Month(value / 100, value % 100) + Week::class -> Week(value / 100, value % 100) + else -> null + } + } + else -> null + } +} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/form/VDictionaryForm.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/form/VDictionaryForm.kt index 671fbce30..64b3e6fc6 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/form/VDictionaryForm.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/form/VDictionaryForm.kt @@ -26,6 +26,7 @@ import org.kopi.galite.visual.VRuntimeException import org.kopi.galite.visual.cross.VReportSelectionForm import org.kopi.galite.visual.form.VConstants.Companion.MOD_UPDATE import org.kopi.galite.visual.fullcalendar.VFullCalendarBlock +import org.kopi.galite.visual.pivotTable.VPivotTable import org.kopi.galite.visual.report.VNoRowException import org.kopi.galite.visual.report.VReport @@ -224,6 +225,23 @@ abstract class VDictionaryForm protected constructor(source: String? = null) : V b.setRecordChanged(0, false) } + /** + * Implements interface for COMMAND CreatePivotTable + */ + fun createPivotTable(b: VBlock, reportBuilder: () -> VPivotTable) { + b.validate() + try { + setWaitInfo(Message.getMessage("report_generation")) + val report = reportBuilder() + report.doNotModal() + unsetWaitInfo() + } catch (e: VNoRowException) { + unsetWaitInfo() + error(MessageCode.getMessage("VIS-00057")) + } + b.setRecordChanged(0, false) + } + companion object { /** * static call to createReport. diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/CellStyleCacheManager.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/CellStyleCacheManager.kt new file mode 100644 index 000000000..4f14a2e34 --- /dev/null +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/CellStyleCacheManager.kt @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package org.kopi.galite.visual.pivotTable + +import java.awt.Color +import java.io.Serializable + +import org.apache.poi.hssf.util.HSSFColor +import org.apache.poi.ss.usermodel.BorderStyle +import org.apache.poi.ss.usermodel.CellStyle +import org.apache.poi.ss.usermodel.FillPatternType +import org.apache.poi.ss.usermodel.HorizontalAlignment +import org.apache.poi.ss.usermodel.IndexedColors +import org.apache.poi.ss.usermodel.VerticalAlignment +import org.apache.poi.ss.usermodel.Workbook +import org.apache.poi.xssf.usermodel.XSSFCellStyle +import org.apache.poi.xssf.usermodel.XSSFColor + +/** + * Manage the CellStyle cache. + * In order to not have the 4000 style limit, cell styles are cached base on their + * hash codes within a [Set] and reused when it two or more cells have the same + * style. + * Use [.setCellStyle] for caching functions. + */ +class CellStyleCacheManager : Serializable { + + //--------------------------------------------------- + // DATA MEMBERS + //--------------------------------------------------- + private val stylesCache: MutableMap = HashMap() + + //--------------------------------------------------- + // IMPLEMENTATIONS + //--------------------------------------------------- + /** + * Returns the cell style corresponding to the given alignment, data format and color. + * If the style is not cached yet, it will be created and added to the cache. + * @param exporter The excel exporter instance. + * @param wb The workbook instance. + * @param alignment The style alignment. + * @param dataFormat The style data format. + * @param color The style background color. + * @return The style instance. + */ + fun getStyle( + wb: Workbook, + alignment: Short, + dataFormat: Short, + color: Color, + ): CellStyle { + val key = StyleKey(alignment, dataFormat, color) + if (!stylesCache.containsKey(key)) { + val style: CellStyle = wb.createCellStyle() + + style.verticalAlignment = VerticalAlignment.TOP + style.borderBottom = BorderStyle.THIN + style.bottomBorderColor = IndexedColors.BLACK.getIndex() + style.borderLeft = BorderStyle.THIN + style.leftBorderColor = IndexedColors.BLACK.getIndex() + style.borderRight = BorderStyle.THIN + style.rightBorderColor = IndexedColors.BLACK.getIndex() + style.borderTop = BorderStyle.THIN + style.topBorderColor = IndexedColors.BLACK.getIndex() + style.fillPattern = FillPatternType.SOLID_FOREGROUND + style.wrapText = true + style.alignment = HorizontalAlignment.forInt(alignment.toInt()) + if (dataFormat.toInt() != -1) { + style.dataFormat = dataFormat + } + stylesCache[key] = style + } + return stylesCache[key]!! + } + + //--------------------------------------------------- + // INNER CLASSES + //--------------------------------------------------- + inner class StyleKey(private val alignment: Short, private val dataFormat: Short, private val color: Color) { + + //--------------------------------------- + // IMPLEMENTATIONS + //--------------------------------------- + override fun equals(other: Any?): Boolean = + if (other is StyleKey) { + alignment == other.alignment && dataFormat == other.dataFormat && color == other.color + } else { + super.equals(other) + } + + override fun hashCode(): Int = alignment + dataFormat + color.hashCode() + } +} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/ColumnStyle.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/ColumnStyle.kt new file mode 100644 index 000000000..126ea8208 --- /dev/null +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/ColumnStyle.kt @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package org.kopi.galite.visual.pivotTable + +import java.awt.Color +import java.awt.Font +import java.io.Serializable + +import org.kopi.galite.util.base.InconsistencyException + +class ColumnStyle : Serializable { + + var foregroundCode = 0 + var backgroundCode = 0 + var fontName = 0 + var fontStyle = 0 + var state = 0 + + /** + * Gets the background color of this component. + * + * @return color The color to become this component's background color. + */ + fun getBackground(): Color = when (backgroundCode) { + Constants.CLR_WHITE -> Color.white + Constants.CLR_BLACK -> Color.black + Constants.CLR_RED -> Color.red + Constants.CLR_GREEN -> Color.green + Constants.CLR_BLUE -> Color.blue + Constants.CLR_YELLOW -> Color.yellow + Constants.CLR_PINK -> Color.pink + Constants.CLR_CYAN -> Color.cyan + Constants.CLR_GRAY -> Color.gray + else -> + throw InconsistencyException( + message = "The background's color doesn't exist within the specified colors scope" + ) + } + + /** + * Gets the foreground color of this component. + * + * @return color The color to become this component's foreground color. + */ + fun getForeground(): Color = when (foregroundCode) { + Constants.CLR_WHITE -> Color.white + Constants.CLR_BLACK -> Color.black + Constants.CLR_RED -> Color.red + Constants.CLR_GREEN -> Color.green + Constants.CLR_BLUE -> Color.blue + Constants.CLR_YELLOW -> Color.yellow + Constants.CLR_PINK -> Color.pink + Constants.CLR_CYAN -> Color.cyan + Constants.CLR_GRAY -> Color.gray + else -> throw InconsistencyException( + message = "The foreground's color doesn't exist within the specified colors scope" + ) + } + + /** + * Gets the font of this component. + * + * @return font The font to become this component's font. + */ + fun getFont(): Font { + val font = when (fontName) { + 0 -> org.kopi.galite.visual.Constants.FNT_FIXED_WIDTH + 1 -> "Helvetica" + 2 -> "Geneva" + 3 -> "Courier" + else -> throw InconsistencyException( + message = "Font doesn't exist within the specified scope" + ) + } + return Font(font, fontStyle, 12) + } +} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/Constants.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/Constants.kt new file mode 100644 index 000000000..3c19b9664 --- /dev/null +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/Constants.kt @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package org.kopi.galite.visual.pivotTable + +import org.kopi.galite.visual.form.VConstants +import org.kopi.galite.visual.Constants + +interface Constants : Constants { + companion object { + // -------------------------------------------------------------------- + // COLUMN OPTIONS + // -------------------------------------------------------------------- + const val CLO_VISIBLE = 0 + const val CLO_HIDDEN = 1 + + // --------------------------------------------------------------------- + // ALIGNMENT + // --------------------------------------------------------------------- + const val ALG_DEFAULT = 0 + const val ALG_LEFT = 1 + const val ALG_CENTER = 2 + const val ALG_RIGHT = 4 + + // --------------------------------------------------------------------- + // COLOR + // --------------------------------------------------------------------- + const val CLR_WHITE = 0 + const val CLR_BLACK = 1 + const val CLR_RED = 2 + const val CLR_GREEN = 3 + const val CLR_BLUE = 4 + const val CLR_YELLOW = 5 + const val CLR_PINK = 6 + const val CLR_CYAN = 7 + const val CLR_GRAY = 8 + + // --------------------------------------------------------------------- + // PRINT OPTIONS + // --------------------------------------------------------------------- + const val SUM_AT_HEAD = 1 + const val SUM_AT_TAIL = 2 + + // --------------------------------------------------------------------- + // TRIGGERED EVENTS (MAX 32) + // --------------------------------------------------------------------- + const val TRG_PREREPORT = 0 + const val TRG_POSTREPORT = 1 + const val TRG_INIT = 2 + const val TRG_FORMAT = 3 + const val TRG_COMPUTE = 4 + const val TRG_CMDACCESS = 5 + const val TRG_VOID: Int = VConstants.TRG_VOID + const val TRG_OBJECT: Int = VConstants.TRG_OBJECT + const val TRG_BOOLEAN: Int = VConstants.TRG_BOOLEAN + + // --------------------------------------------------------------------- + // CELL STATE + // --------------------------------------------------------------------- + const val STA_SEPARATOR = -2 + const val STA_FOLDED = -1 + const val STA_STANDARD = 0 + const val STA_EMPTY = 1 + const val STA_NEGATIVE = 2 + const val STA_NULL = 3 + const val STA_DEFAULT = 4 + + // --------------------------------------------------------------------- + // PREDEFINED COMMANDS + // --------------------------------------------------------------------- + const val CMD_QUIT = 0 + const val CMD_PRINT = 1 + const val CMD_PREVIEW = 2 + const val CMD_PRINT_OPTIONS = 3 + const val CMD_EXPORT_CSV = 4 + const val CMD_EXPORT_XLS = 5 + const val CMD_EXPORT_XLSX = 6 + const val CMD_EXPORT_PDF = 7 + const val CMD_FOLD = 8 + const val CMD_UNFOLD = 9 + const val CMD_SORT = 10 + const val CMD_FOLD_COLUMN = 11 + const val CMD_UNFOLD_COLUMN = 12 + const val CMD_COLUMN_INFO = 13 + const val CMD_OPEN_LINE = 14 + const val CMD_REMOVE_CONFIGURATION = 15 + const val CMD_LOAD_CONFIGURATION = 16 + const val CMD_HELP = 17 + + // --------------------------------------------------------------------- + // TRIGGER INFO + // --------------------------------------------------------------------- + val TRG_NAMES = arrayOf( + "TRG_PREREPORT", "TRG_POSTREPORT", "TRG_INIT", "TRG_FORMAT", "TRG_COMPUTE", "TRG_CMDACCESS") + val TRG_TYPES = intArrayOf( + TRG_VOID, TRG_VOID, TRG_VOID, TRG_OBJECT, TRG_OBJECT, TRG_BOOLEAN) + } +} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/MPivotTable.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/MPivotTable.kt new file mode 100644 index 000000000..6cf488afb --- /dev/null +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/MPivotTable.kt @@ -0,0 +1,1049 @@ +/* + * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package org.kopi.galite.visual.pivotTable + +import java.io.Serializable +import java.math.BigDecimal +import java.time.Instant +import java.time.LocalDate +import java.time.LocalDateTime +import java.time.LocalTime + +import javax.swing.event.EventListenerList + +import kotlin.math.max +import org.kopi.galite.type.format + +import org.kopi.galite.visual.MessageCode +import org.kopi.galite.visual.VExecFailedException + +import com.graphbuilder.math.Expression +import com.graphbuilder.math.ExpressionTree +import com.graphbuilder.math.FuncMap +import com.graphbuilder.math.VarMap + +class MPivotTable : Constants, Serializable { + + // -------------------------------------------------------------------- + // DATA MEMBERS + // -------------------------------------------------------------------- + // Columns contains all columns defined by the user + // accessiblecolumns is a part of columns which contains only visible columns + var columns = mutableListOf() // array of column definitions + var accessibleColumns: Array = arrayOf() // array of visible or hide columns + private set + + // Root is the root of the tree (which is our model to manipulate data) + private var root: VGroupRow? = null // root of grouping tree + + // Baserows contains data give by the request of the user + // visibleRows contains all data which will be displayed. It's like a buffer. visibleRows + // is changed when a column move or one or more row are folded + internal var userRows: ArrayList? = ArrayList(500) + lateinit var baseRows: Array // array of base data rows + private var visibleRows: Array? = null // array of visible rows + private var maxRowCount = 0 + + // Sortedcolumn contain the index of the sorted column + // sortingOrder store the type of sort of the sortedColumn : ascending or descending + private var sortedColumn = 0 // the table is sorted wrt. to this column + private var sortingOrder = 0 // 1: ascending, -1: descending + + // displayOrder contains index column model in display order + // reverseOrder is calculate with displayOrder and contains index column display into model order + private lateinit var displayOrder: IntArray // column mapping from display to model + private lateinit var reverseOrder: IntArray // column mapping from model to display + + // The displayLevels variable is a table which contains the level of each column + private lateinit var displayLevels: IntArray // column levels in display order + private val listenerList = EventListenerList() // List of listeners + + fun computeColumnWidth(column: Int): Int { + var max = 0 + + baseRows.forEach { row -> + if (row!!.getValueAt(column) != null) { + val value = row.getValueAt(column).let { value -> + when (value) { + is BigDecimal -> value.format() + is LocalDate -> value.format() + is LocalTime -> value.format() + is Instant -> value.format() + is LocalDateTime -> value.format() + else -> value.toString() + } + } + + max = max(max, value.length) + } + } + return max + 2 + } + + fun removeColumn(position: Int) { + var position = position + val cols = arrayOfNulls(columns.size - 1) + var hiddenColumns = 0 + + columns.forEach { + if (it!!.options and Constants.CLO_HIDDEN != 0) { + hiddenColumns += 1 + } + } + position += hiddenColumns + // copy columns before position. + for (i in 0 until position) { + cols[i] = columns[i] + } + // copy columns after position. + for (i in position until columns.size - 1) { + cols[i] = columns[i + 1] + } + position -= hiddenColumns + columns = cols.clone().toMutableList() + createAccessibleTab() + val rows = arrayOfNulls(baseRows.size) + + baseRows.forEachIndexed { index, element -> + val data = arrayOfNulls(getAccessibleColumnCount()) + + for (j in 0 until position) { + data[j] = element!!.getValueAt(j) + } + // skip position. + for (j in position until getAccessibleColumnCount()) { + data[j] = element!!.getValueAt(j + 1) + } + rows[index] = VBaseRow(data) + } + baseRows = rows.filterIsInstance().toTypedArray() + } + + fun initializeAfterRemovingColumn(position: Int) { + val columnCount: Int = getAccessibleColumnCount() + val newDisplayOrder = IntArray(columnCount) + + reverseOrder = IntArray(columnCount) + displayLevels = IntArray(columnCount) + for (i in 0 until position) { + newDisplayOrder[i] = displayOrder[i] + } + for (i in position until columnCount) { + newDisplayOrder[i] = displayOrder[i + 1] + } + for (i in 0 until columnCount) { + reverseOrder[i] = i + displayLevels[i] = -1 + } + displayOrder = newDisplayOrder + } + + /** + * Adds a column at runtime. + */ + fun addColumn(label: String, position: Int) { + val cols = arrayOfNulls(columns.size + 1) + + // add the new column; + cols[columns.size] = VDecimalColumn(null, 0, 4, -1, null, 15, 7, null) + cols[columns.size]!!.label = label + cols[columns.size]!!.isAddedAtRuntime = true + // copy the other columns. + columns.forEachIndexed { index, element -> + cols[index] = element + } + columns = cols.clone().toMutableList() + initializeAfterAddingColumn() + val rows = arrayOfNulls(baseRows.size) + + baseRows.forEachIndexed { index, element -> + val data = arrayOfNulls(getAccessibleColumnCount()) + + for (j in 0 until getAccessibleColumnCount() - 1) { + data[j] = element!!.getValueAt(j) + } + // fill the new column with null , column data will be set by user. + data[getAccessibleColumnCount() - 1] = null + rows[index] = VBaseRow(data) + } + baseRows = rows.filterIsInstance().toTypedArray() + } + + private fun initializeAfterAddingColumn() { + createAccessibleTab() + val columnCount: Int = getAccessibleColumnCount() + val newDisplayOrder = IntArray(columnCount) + + displayLevels = IntArray(columnCount) + reverseOrder = IntArray(columnCount) + for (i in 0 until columnCount - 1) { + newDisplayOrder[i] = displayOrder[i] + } + newDisplayOrder[columnCount - 1] = columnCount - 1 + displayOrder = newDisplayOrder + for (i in 0 until columnCount) { + reverseOrder[i] = i + displayLevels[i] = -1 + } + } + + fun computeDataForColumn(column: Int, columnIndexes: IntArray, formula: String) { + val x: Expression = try { + ExpressionTree.parse(formula) + } catch (e: Exception) { + throw VExecFailedException(MessageCode.getMessage("VIS-00064", formula, "\n$e")) + } + val params: Array = x.variableNames + val paramColumns = IntArray(params.size) + val functions = IntArray(params.size) + val NONE = -1 + val MAX = 0 + val MIN = 1 + val OVR = 2 + val SUM = 3 + + for (i in params.indices) { + try { + when { + params[i].startsWith("C") -> { + paramColumns[i] = params[i].substring(1).toInt() + functions[i] = NONE + } + params[i].startsWith("maxC") -> { + paramColumns[i] = params[i].substring(4).toInt() + functions[i] = MAX + } + params[i].startsWith("minC") -> { + paramColumns[i] = params[i].substring(4).toInt() + functions[i] = MIN + } + params[i].startsWith("ovrC") -> { + paramColumns[i] = params[i].substring(4).toInt() + functions[i] = OVR + } + params[i].startsWith("sumC") -> { + paramColumns[i] = params[i].substring(4).toInt() + functions[i] = SUM + } + else -> { + throw VExecFailedException( + MessageCode.getMessage("VIS-00061", + "${params[i]}\n", + "Cx, maxCx, minCx, ovrCx, sumCx")) + } + } + } catch (e: NumberFormatException) { + throw VExecFailedException(MessageCode.getMessage("VIS-00062", params[i].substring(1))) + } + // test column indexes. + var test = false + + for (j in columnIndexes.indices) { + if (paramColumns[i] == columnIndexes[j]) { + test = true + break + } + } + if (!test) { + throw VExecFailedException(MessageCode.getMessage("VIS-00063", params[i].substring(1))) + } + } + val vm = VarMap(false /* case sensitive */) + val fm: FuncMap? = null // no functions in expression + var tmp: Float + + for (i in baseRows.indices) { + for (j in paramColumns.indices) { + when (functions[j]) { + NONE -> { + val value = if (baseRows[i]!!.getValueAt(paramColumns[j]) == null) { + 0.0 + } else { + // !!! wael 20070622 : use 0 instead of null values. + (baseRows[i]!!.getValueAt(paramColumns[j]) as BigDecimal).toDouble() + } + vm.setValue(params[j], value) + } + MAX -> { + var max: Float + // init max + max = if (baseRows[0]!!.getValueAt(paramColumns[j]) == null) { + 0F + } else { + (baseRows[0]!!.getValueAt(paramColumns[j]) as BigDecimal).toFloat() + } + // calculate max value. + baseRows.forEach { + tmp = if (it!!.getValueAt(paramColumns[j]) == null) { + 0F + } else { + (it.getValueAt(paramColumns[j]) as BigDecimal).toFloat() + } + if (tmp > max) { + max = tmp + } + } + vm.setValue(params[j], max.toDouble()) + } + MIN -> { + var min: Float + + // init max + min = if (baseRows[0]!!.getValueAt(paramColumns[j]) == null) { + 0F + } else { + (baseRows[0]!!.getValueAt(paramColumns[j]) as BigDecimal).toFloat() + } + // calculate min value. + baseRows.forEach { + tmp = if (it!!.getValueAt(paramColumns[j]) == null) { + 0F + } else { + (it.getValueAt(paramColumns[j]) as BigDecimal).toFloat() + } + if (tmp < min) { + min = tmp + } + } + vm.setValue(params[j], min.toDouble()) + } + OVR -> { + var ovr = 0f + // calculate average. + baseRows.forEach { + tmp = if (it!!.getValueAt(paramColumns[j]) == null) { + 0F + } else { + (it.getValueAt(paramColumns[j]) as BigDecimal).toFloat() + } + ovr += tmp / baseRows.size + } + vm.setValue(params[j], ovr.toDouble()) + } + SUM -> { + var sum = 0f + // calculate sum. + baseRows.forEach { + tmp = if (it!!.getValueAt(paramColumns[j]) == null) { + 0F + } else { + (it.getValueAt(paramColumns[j]) as BigDecimal).toFloat() + } + sum += tmp + } + vm.setValue(params[j], sum.toDouble()) + } + } + } + try { + baseRows[i]!!.setValueAt(column, BigDecimal(x.eval(vm, fm))) + } catch (e: NumberFormatException) { + // this exception occurs with INFINITE double values. (ex : division by ZERO) + // return a null value (can not evaluate expression) + baseRows[i]!!.setValueAt(column, null) + } catch (e: Exception) { + throw VExecFailedException(MessageCode.getMessage("VIS-00066")) + } + } + } + + /** + * Add a row to the list of rows defined by the user + */ + fun addLine(line: Array) { + userRows!!.add(VBaseRow(line)) + } + + /** + * Build the base row table + initialisation + */ + internal fun build() { + // build accessible columns + if (userRows!!.size == 0) { + throw VNoRowException(MessageCode.getMessage("VIS-00015")) + } + createAccessibleTab() + baseRows = userRows!!.toTypedArray() + userRows = null + + // build working tables + val columnCount = getAccessibleColumnCount() + displayOrder = IntArray(columnCount) + reverseOrder = IntArray(columnCount) + displayLevels = IntArray(columnCount) + for (i in 0 until columnCount) { + displayOrder[i] = i + reverseOrder[i] = i + displayLevels[i] = -1 + } + } + // -------------------------------------------------------------------- + // MEMBER ACCESS + // -------------------------------------------------------------------- + /** + * Return a column definition + * + * @param column the index of the desired column + * @return the desired column + */ + fun getModelColumn(column: Int): VReportColumn = columns[column]!! + + /** + * Returns the number of model columns + * + * @return the number or columns to display + */ + fun getModelColumnCount(): Int = columns.size + + /** + * Return a column definition + * + * @param column the index of the desired column + * @return the desired column + */ + fun getAccessibleColumn(column: Int): VReportColumn? = accessibleColumns[column] + + /** + * Returns the number of columns visible or hide + * + * @return the number or columns in the model + */ + fun getAccessibleColumnCount(): Int = accessibleColumns.size + + /** + * Return a row definition + * + * @param row the index of the desired row + * @return the desired row + */ + fun getRow(row: Int): VReportRow? = visibleRows!![row] + + /** + * Return the tree used by the model + */ + fun getTree(): VGroupRow? = root + + // -------------------------------------------------------------------- + // GROUPING TREE + // -------------------------------------------------------------------- + internal fun createTree() { + // compute grouping columns in displayed column order + computeGroupings() + + // sort base rows wrt to each grouping column + sortBaseRows() + + // build the grouping tree recursively + buildGroupingTree() + + // compute all intermediate columns + calculateColumns() + + // create the array of displayed rows + updateTableModel() + } + + /** + * Returns an array of grouping columns in displayed column order + * For each column, the value is the column of the next (lower) level + * grouping or -1 if the column has no further sub-grouping. + * The columns are given in displayed column order + */ + private fun computeGroupings() { + val columnCount = accessibleColumns.size + val defaultGroups = IntArray(columnCount) + val displayGroups = IntArray(columnCount) + var separatorPos = Int.MAX_VALUE + + // retrieve the groups in original column order + for (i in 0 until columnCount) { + defaultGroups[i] = accessibleColumns[i]!!.groups + } + + // reorder the groups in displayed column order + for (i in 0 until columnCount) { + when { + defaultGroups[displayOrder[i]] == -1 -> { + displayGroups[i] = -1 + } + defaultGroups[displayOrder[i]] >= reverseOrder.size -> { + displayGroups[i] = reverseOrder.size + } // not shown + else -> { + displayGroups[i] = reverseOrder[defaultGroups[displayOrder[i]]] + } + } + } + + // retrieve separator + for (i in 0 until columnCount) { + if (accessibleColumns[displayOrder[i]] is VSeparatorColumn) { + separatorPos = i + } + } + var level = 0 + + //top is reached + run { + var i = 0 + while (i < displayGroups.size) { + displayLevels[i] = level + if (accessibleColumns[displayOrder[i]]!!.isVisible) { + if (displayGroups[i] == -1 || i == separatorPos) { + while (i < displayGroups.size) { + displayLevels[i] = level + i++ + } + break + } else if (displayGroups[i] > i) { + while (i + 1 < displayGroups.size && displayGroups[i + 1] <= i + 1 && displayGroups[i + 1] != -1) { + displayLevels[i + 1] = level + i++ + } + level++ + } + } + i++ + } + } + + // renumber levels from highest to lowest (0) + for (i in 0 until columnCount) { + displayLevels[i] = level - displayLevels[i] + } + } + + /** + * Sort base rows wrt to each grouping column + * Note: we assume that the sorting algorithm ist stable: we thus + * can sort the complete table for each column, starting with the + * last grouping column. + */ + private fun sortBaseRows() { + visibleRows = arrayOfNulls(baseRows.size) + sortBaseRows(0) + } + + private fun sortBaseRows(column: Int) { + if (displayLevels[column] > 0) { + var next = column + 1 + + while (displayLevels[next] == displayLevels[next - 1]) { + next += 1 + } + sortBaseRows(next) + } + // sort in ascending order + var i = column + while (!accessibleColumns[i]!!.isVisible) { + i += 1 + } + if (i >= 0) { + sortArray(baseRows, displayOrder[i], 1) + // this value is overwritten in each pass: at the end + // of the recursion it will hold the first column + sortedColumn = displayOrder[i] + sortingOrder = 1 + } + } + + /** + * Build the grouping tree + */ + private fun buildGroupingTree() { + maxRowCount = baseRows.size + 1 + root = VGroupRow(arrayOfNulls(getModelColumnCount()), displayLevels[0] + 1) + // even if column 0 is hidden, it has the highest level + buildGroupingTree(root!!, 0, baseRows.size - 1, 0) + visibleRows = arrayOfNulls(maxRowCount) + root!!.visible = true + for (i in 0 until root!!.childCount) { + (root!!.getChildAt(i) as VReportRow).visible = true + } + } + + private fun buildGroupingTree(tree: VReportRow, loRow: Int, hiRow: Int, start: Int) { + var loRow = loRow + var start = start + + if (displayLevels[start] == 0) { // even if the 0-index column is hidden, its displayLevels == 0 + for (i in loRow..hiRow) { + tree.add(baseRows[i]) + } + } else { + // get the interval of columns at this level + var next: Int = start + 1 + + while (displayLevels[next] == displayLevels[start]) { + next++ + } + while (!accessibleColumns[start]!!.isVisible) { + // to get the first visible column of this level + start++ + } + + do { + val value = baseRows[loRow]!!.getValueAt(displayOrder[start]) + var split = loRow + + while (split <= hiRow && (value == null && baseRows[split]!!.getValueAt(displayOrder[start]) == null + || value != null && value == baseRows[split]!!.getValueAt(displayOrder[start]))) { + split += 1 + } + val newRow = VGroupRow(arrayOfNulls(getModelColumnCount()), displayLevels[start]) + + maxRowCount++ + for (i in 0 until next) { + newRow.setValueAt(displayOrder[i], baseRows[loRow]!!.getValueAt(displayOrder[i])) + } + buildGroupingTree(newRow, loRow, split - 1, next) + tree.add(newRow) + loRow = split + } while (loRow <= hiRow) + } + } + + /** + * Sorts an array of rows wrt to given column using straight two-way merge sorting. + * + * @param array The array to sort + * @param column The index of the column on which to sort + * @param order The sorting order (1: ascending, -1: descending) + */ + private fun sortArray(array: Array, column: Int, order: Int) { + mergeSort(array, column, order, 0, array.size - 1, visibleRows) + } + + private fun mergeSort(array: Array, + column: Int, + order: Int, + lo: Int, + hi: Int, + scratch: Array?) { + // a one-element array is always sorted + if (lo < hi) { + val mid = (lo + hi) / 2 + + // split into 2 sublists and sort them + mergeSort(array, column, order, lo, mid, scratch) + mergeSort(array, column, order, mid + 1, hi, scratch) + + // Merge sorted sublists + var t_lo = lo + var t_hi = mid + 1 + + for (k in lo..hi) { + if (t_lo > mid || + t_hi <= hi && + order * array[t_hi]!!.compareTo(array[t_lo]!!, column, getModelColumn(column)) < 0) { + scratch!![k] = array[t_hi++] + } else { + scratch!![k] = array[t_lo++] + } + } + + // Copy back to array + for (k in lo..hi) { + array[k] = scratch!![k] + } + } + } + + /** + * Calculate all columns which need to be calculated + */ + fun calculateColumns() { + for (i in columns.indices) { + val function: VCalculateColumn? = columns[i]!!.function + + if (function != null) { + function.init() + function.calculate(root!!, i) + } + } + } + + /** + * fill table of visible rows + */ + private fun updateTableModel() { + maxRowCount = addRowsInArray(root, 0) + fireContentChanged() + } + + /** + * add visible rows in a vector + * + * @param node node to test. + * @param pos position of the node. + */ + private fun addRowsInArray(node: VReportRow?, pos: Int): Int { + var position = pos + + if (node!!.visible) { + visibleRows!![position++] = node + for (i in 0 until node.childCount) { + val row = node.getChildAt(i) as VReportRow + + if (row.level == 0) { + if (row.visible) { + visibleRows!![position++] = row + } + } else { + position = addRowsInArray(node.getChildAt(i) as VReportRow, position) + } + } + } + return position + } + // -------------------------------------------------------------------- + // EVENTS FROM DISPLAY + // -------------------------------------------------------------------- + /** + * Sort the displayed tree wrt to a column + * + * @param column the model column index used for sorting in display order. + */ + fun sortColumn(column: Int) { + sortTree(column) + calculateColumns() + updateTableModel() + } + + /** + * Sort the displayed tree wrt to a column + * + * @param column the model column index used for sorting in display order. + * @param order sort order. + */ + fun sortColumn(column: Int, order: Int) { + sortTree(root, column, order) + calculateColumns() + updateTableModel() + } + + /** + * Sort the display tree wrt to a column; if it is already sorted + * wrt to this column, invert the sorting order. + * + * @param column The model column index given in display order + */ + private fun sortTree(column: Int) { + val order: Int = if (column != sortedColumn) 1 else -sortingOrder + + sortTree(root, column, order) + sortedColumn = column + sortingOrder = order + } + + private fun sortTree(tree: VReportRow?, column: Int, order: Int) { + + // place the children of the root in an array + val rowTab: Array = arrayOfNulls(tree!!.childCount) + + for (i in 0 until tree.childCount) { + rowTab[i] = tree.getChildAt(i) as VReportRow + } + + // sort the array wrt to column: if already sorted, invert order + sortArray(rowTab, column, order) + + // re-add the rows as children + tree.removeAllChildren() + for (i in rowTab.indices) { + tree.add(rowTab[i]) + } + + // sort sub-trees recursively + if (tree.level > 1) { + for (i in 0 until tree.childCount) { + sortTree(tree.getChildAt(i) as VReportRow, column, order) + } + } + } + + /** + * Returns true is the specified column is fold + */ + fun isColumnFold(column: Int): Boolean { + return if (root!!.level > 1) { + val level = displayLevels[reverseOrder[column]] + + !root!!.isUnfolded(level) + } else { + false + } + } + + /** + * Returns true if the specified row is fold at the specified column + */ + fun isRowFold(row: Int, column: Int): Boolean { + return if (root!!.level > 1) { + val level = displayLevels[reverseOrder[column]] + var currentRow = visibleRows!![row] + + while (currentRow!!.level < level) { + currentRow = currentRow.parent as? VReportRow + } + if (currentRow is VGroupRow?) !currentRow.isUnfolded(level) else true + } else { + false + } + } + + /** + * Folds the specified column + */ + fun foldingColumn(column: Int) { + if (root!!.level > 1) { + val level = displayLevels[reverseOrder[column]] + + root!!.setChildNodesInvisible(level) + updateTableModel() + } + } + + /** + * Unfolds the specified column + */ + fun unfoldingColumn(column: Int) { + if (root!!.level > 1) { + val level = displayLevels[reverseOrder[column]] + + root!!.setChildNodesVisible(level) + updateTableModel() + } + } + + /** + * Folds the specified column + */ + fun setColumnFolded(column: Int, fold: Boolean) { + accessibleColumns[column]!!.isFolded = fold + fireContentChanged() + } + + /** + * Folds the specified column + */ + fun switchColumnFolding(column: Int) { + accessibleColumns[column]!!.isFolded = (!accessibleColumns[column]!!.isFolded) + fireContentChanged() + } + + /** + * Folds the specified row to specified column + * + * @param column the model index of the column + */ + fun foldingRow(row: Int, column: Int) { + if (root!!.level > 1) { + val level = displayLevels[reverseOrder[column]] + var currentRow = visibleRows!![row] + + while (currentRow!!.level < level) { + currentRow = currentRow.parent as? VReportRow + } + if (currentRow is VGroupRow?) { + currentRow.setChildNodesInvisible(level) + } + updateTableModel() + } + } + + /** + * Unfolds the specified row to specified column + * + * @param column the model index of the column + */ + fun unfoldingRow(row: Int, column: Int) { + if (root!!.level > 1) { + val level = displayLevels[reverseOrder[column]] + val currentRow = visibleRows!![row] + + if (currentRow is VGroupRow) { + currentRow.setChildNodesVisible(level) + } + updateTableModel() + } + } + + /** + * Returns true if the specified row is fold at the specified column + */ + fun isRowLine(row: Int): Boolean { + return if (visibleRows != null) { + row in 0 until maxRowCount && visibleRows!![row]!!.level == 0 + } else { + false + } + } + + /** + * @param newOrder the table of the display order columns + */ + fun columnMoved(newOrder: IntArray) { + displayOrder = newOrder + + // rebuild column mapping from model to display + displayOrder.forEachIndexed { index, element -> + reverseOrder[element] = index + } + createTree() + } + // -------------------------------------------------------------------- + // REDEFINITION OF METHODS IN AbstractTableModel + // -------------------------------------------------------------------- + /** + * Returns the number of columns managed by the data source object. + * + * @return the number or columns to display + */ + fun getColumnCount(): Int = accessibleColumns.size + + /** + * Returns the number of records managed by the data source object. + * + * @return the number or rows in the model + */ + fun getRowCount(): Int = maxRowCount + + /** + * Returns always false since report cells are never editable. + * + * @param row the index of the row whose value is to be looked up + * @param column the index of the column whose value is to be looked up + * @return true if the cell is editable. + */ + fun isCellEditable(row: Int, column: Int): Boolean = false + + /** + * Returns an attribute value for a cell. + * + * @param row the index of the row whose value is to be looked up + * @param column the index of the column whose value is to be looked up (column of the model) + * @return the value Object at the specified cell + */ + fun getValueAt(row: Int, column: Int): Any? { + var x: Any? = null + + try { + x = visibleRows!![row]!!.getValueAt(column) + } catch (e: Exception) { + e.printStackTrace() + } + return if (visibleRows!![row]!!.level < displayLevels[reverseOrder[column]]) null else x + } + + /** + * Returns the name of a column. + * Note, this name does not need to be unique. + * + * @param column the index of the column + * @return the name of the column + */ + fun getColumnName(column: Int): String { + val label = accessibleColumns[column]!!.label + + if (label.isEmpty()) { + return "" + } + return if (accessibleColumns[column]!!.isFolded) label.substring(0, 1) else label + } + + /** + * Makes the table of accessible columns from the columns variable + */ + private fun createAccessibleTab() { + val columnCount = columns.size + var accessiblecolumnCount = 0 + + for (i in 0 until columnCount) { + if (columns[i]!!.options and Constants.CLO_HIDDEN == 0) { + accessiblecolumnCount += 1 + } + } + accessibleColumns = arrayOfNulls(accessiblecolumnCount) + accessiblecolumnCount = 0 + for (i in 0 until columnCount) { + if (columns[i]!!.options and Constants.CLO_HIDDEN == 0) { + accessibleColumns[accessiblecolumnCount++] = columns[i] + } + } + } + + fun getDisplayLevels(column: Int): Int = displayLevels[column] + + fun getReverseOrder(column: Int): Int = reverseOrder[column] + + fun getDisplayOrder(column: Int): Int = displayOrder[column] + + /** + * Returns the number of base rows. + */ + fun getBaseRowCount(): Int = baseRows.size + + /** + * Returns the number of visible rows. + */ + fun getVisibleRowCount(): Int = visibleRows!!.size + + // -------------------------------------------------------------------- + // LISTENERS HANDLING + // -------------------------------------------------------------------- + /** + * Adds a listener to the list that's notified each time a change + * to the data model occurs. + * + * @param l The ReportListener + */ + fun addReportListener(l: ReportListener) { + listenerList.add(ReportListener::class.java, l) + } + + /** + * Removes a listener from the list that's notified each time a + * change to the data model occurs. + * + * @param l The ReportListener + */ + fun removeReportListener(l: ReportListener) { + listenerList.remove(ReportListener::class.java, l) + } + + /** + * Notifies all listeners that the report model has changed. + */ + protected fun fireContentChanged() { + val listeners = listenerList.listenerList + var i = listeners.size - 2 + + while (i >= 0) { + if (listeners[i] == ReportListener::class.java) { + (listeners[i + 1] as ReportListener).contentChanged() + } + i -= 2 + } + } + + companion object { + private const val serialVersionUID = 0L + } +} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/PConfig.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/PConfig.kt new file mode 100644 index 000000000..770dd5d66 --- /dev/null +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/PConfig.kt @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package org.kopi.galite.visual.pivotTable + +import java.io.Serializable + +import org.kopi.galite.visual.util.PPaperType + +/** + * PConfig Class that allows to set the configuration parameters + * @param papertype different formats of paper + * @param paperlayout the layout of the paper (Portrait or Landscape) + * @param topmargin top sheet margin in points + * @param bottommargin bottom sheet margin in points + * @param leftmargin left sheet margin in points + * @param rightmargin right sheet margin in points + * @param headermargin header sheet margin in points + * @param footermargin footer sheet margin in points + * @param visibleRows true if only visible rows must be displayed + * @param order order to used for printing + * @param groupFormfeed cut the form at each big nivel + * @param grid_H horizontal grid + * @param grid_V vertical grid + * @param border border size + * @param reportScale report scale + */ +data class PConfig(val papertype: Int = PPaperType.PPT_A4.code, + val paperlayout: String = "Landscape", + val topmargin: Int = 30, + val bottommargin: Int = 30, + val leftmargin: Int = 30, + val rightmargin: Int = 30, + val headermargin: Int = 5, + val footermargin: Int = 10, + val visibleRows: Boolean = true, + val order: Int = Constants.SUM_AT_TAIL, + val groupFormfeed: Boolean = false, + val grid_H: Double = 0.1, + val grid_V: Double = 0.1, + val border: Double = 1.0, + val reportScale: Double = MIN_REPORT_SCALE) : Serializable { + + companion object { + const val MIN_REPORT_SCALE = 3.0 + const val MAX_REPORT_SCALE = 12.0 + } +} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/Parameters.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/Parameters.kt new file mode 100644 index 000000000..4db217948 --- /dev/null +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/Parameters.kt @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package org.kopi.galite.visual.pivotTable + +import java.awt.Color +import java.awt.Font +import java.io.Serializable + +import org.kopi.galite.visual.Constants + +/** + * Parameters class . + * + * @param color a color defined in Constants + */ +class Parameters(color: Color) : Serializable { + /**Returns the size of the font*/ + val font = Font(Constants.FNT_FIXED_WIDTH, Font.PLAIN, 12) + private val bgcolors: Array = arrayOfNulls(10) + private val fgcolors = Array(10) { Color(0, 0, 0) } + + init { + val reverseColor = Color(255 - color.red, 255 - color.green, 255 - color.blue) + for (i in bgcolors.indices) { + bgcolors[i] = Color(255 - i * reverseColor.red / 17, + 255 - i * reverseColor.green / 17, + 255 - i * reverseColor.blue / 17) + } + } + + /** + * Returns the background color which corresponds to the level + */ + fun getBackground(level: Int): Color { + return if (level >= bgcolors.size) Color.white else bgcolors[level]!! + } + + /** + * Returns the foreground color which corresponds to the level + */ + fun getForeground(level: Int): Color { + return if (level >= fgcolors.size) Color.black else fgcolors[level] + } +} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/Point.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/Point.kt new file mode 100644 index 000000000..b4e8fdd43 --- /dev/null +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/Point.kt @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package org.kopi.galite.visual.pivotTable + +import java.io.Serializable + +/** + * A point representing a location in `(x,y)` coordinate space, + * specified in integer precision. + */ +data class Point(val x: Int = 0, val y: Int = 0) : Serializable { + + /** + * Returns a string representation of this point and its location + * in the `(x,y)` coordinate space. This method is + * intended to be used only for debugging purposes, and the content + * and format of the returned string may vary between implementations. + * The returned string may be empty but may not be `null`. + * + * @return a string representation of this point + */ + override fun toString() = javaClass.name + "[x=" + x + ",y=" + y + "]" +} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/ReportListener.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/ReportListener.kt new file mode 100644 index 000000000..489954724 --- /dev/null +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/ReportListener.kt @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package org.kopi.galite.visual.pivotTable + +import java.io.Serializable +import java.util.EventListener + +/** + * `TableModelListener` defines the interface for an object that listens + * to changes in [MPivotTable] content. + * + * @see javax.swing.table.TableModel + */ +interface ReportListener : EventListener, Serializable { + /** + * This fine grain notification tells listeners that + * the report model has changed and the display should + * update it self + */ + fun contentChanged() +} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/UPivotTable.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/UPivotTable.kt new file mode 100644 index 000000000..4b1cb23ae --- /dev/null +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/UPivotTable.kt @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package org.kopi.galite.visual.pivotTable + +import org.kopi.galite.visual.UWindow + +/** + * `UReport` is the top-level interface that must be implemented + * by all dynamic reports. It is the visual component of the [VPivotTable] model. + */ +interface UPivotTable : UWindow, ReportListener { + /** + * Builds the report; + */ + fun build() + + /** + * Redisplays the report + */ + fun redisplay() + + /** + * Fired when report columns has moved. + * @param pos The new columns positions + */ + fun columnMoved(pos: IntArray) + + /** + * Removes a column having the position `position` + * @param position The column position + */ + fun removeColumn(position: Int) + + /** + * Adds a column at the position `position` + * @param position The column position + */ + fun addColumn(position: Int) + + /** + * Adds a column at the end of the report + */ + fun addColumn() + + /** + * Returns the report table. + */ + fun getTable(): UTable + + /** + * Reset columns width + */ + fun resetWidth() + + /** + * Returns the selected column + */ + fun getSelectedColumn(): Int + + /** + * Returns the coordinate of the selected cell + * The index of the column is relative to the model + */ + fun getSelectedCell(): Point + + /** + * Sets the column label. + * @param column The column number. + * @param label The column label + */ + fun setColumnLabel(column: Int, label: String) + + /** + * [UTable] is a report table ensuring conversion between + * visible indexes and model indexes + */ + interface UTable { + /** + * Maps the index of the column in the view at [viewColumnIndex] to the index of the column in the table model. + */ + fun convertColumnIndexToModel(viewColumnIndex: Int): Int + + /** + * Maps the index of the column in the table model at [modelColumnIndex] to the index of the column in the view. + */ + fun convertColumnIndexToView(modelColumnIndex: Int): Int + } +} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VBaseRow.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VBaseRow.kt new file mode 100644 index 000000000..407f1eda2 --- /dev/null +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VBaseRow.kt @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package org.kopi.galite.visual.pivotTable + +class VBaseRow(data: Array) : VReportRow(data) { + /** + * Return the level of the node. For base rows it is always 0 + */ + override fun getLevel(): Int = 0 + + companion object { + private const val serialVersionUID = 0L + } +} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VBooleanCodeColumn.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VBooleanCodeColumn.kt new file mode 100644 index 000000000..2c797e81c --- /dev/null +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VBooleanCodeColumn.kt @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package org.kopi.galite.visual.pivotTable + +import org.kopi.galite.util.base.InconsistencyException + +/** + * Represents a report column description + * + * @param ident The column identifier + * @param options The column options as bitmap + * @param align The column alignment + * @param groups The index of the column grouped by this one or -1 + * @param function An (optional) summation function + */ +class VBooleanCodeColumn(ident: String?, + type: String?, + source: String?, + options: Int, + align: Int, + groups: Int, + function: VCalculateColumn?, + width: Int, + format: VCellFormat?, + names: Array, + private val codes: BooleanArray) + : VCodeColumn(ident, + type, + source, + options, + align, + groups, + function, + width, + format, + names) { + + init { + if (codes.size > 2) { + throw InconsistencyException("Can't define more than two codes for a boolean column") + } + } + + override fun compareTo(object1: Any, object2: Any): Int { + return if (object1 == object2) 0 else if (true == object1) 1 else -1 + } + + /** + * Get the index of the value. + */ + override fun getIndex(value: Any): Int { + return if ((value as Boolean) == codes[0]) 0 else 1 + } +} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VBooleanColumn.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VBooleanColumn.kt new file mode 100644 index 000000000..4634a7fbc --- /dev/null +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VBooleanColumn.kt @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package org.kopi.galite.visual.pivotTable + +import org.kopi.galite.visual.VlibProperties + +/** + * Represents a report column description + * + * @param ident The column identifier + * @param options The column options as bitmap + * @param align The column alignment + * @param groups The index of the column grouped by this one or -1 + * @param function An (optional) summation function + */ +class VBooleanColumn(ident: String?, + options: Int, + align: Int, + groups: Int, + function: VCalculateColumn?, + format: VCellFormat?) + : VReportColumn(ident, + options, + align, + groups, + function, + VlibProperties.getString("true").length.coerceAtLeast(VlibProperties.getString("false").length), + 1, + format ?: VBooleanFormat()) { + /** + * Compare two objects. + * + * @param object1 the first operand of the comparison + * @param object2 the second operand of the comparison + * @return -1 if the first operand is smaller than the second + * 1 if the second operand if smaller than the first + * 0 if the two operands are equal + */ + override fun compareTo(object1: Any, object2: Any): Int { + return if (object1 == object2) 0 else if (true == object1) 1 else -1 + } + + private class VBooleanFormat : VCellFormat() { + override fun format(value: Any?): String { + return if (value == null) "" else if (true == value) trueRep else falseRep + } + } + + companion object { + // -------------------------------------------------------------------- + // DATA MEMBERS + // -------------------------------------------------------------------- + private val trueRep = VlibProperties.getString("true") + private val falseRep = VlibProperties.getString("false") + } +} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VCCDepthFirstCircuitN.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VCCDepthFirstCircuitN.kt new file mode 100644 index 000000000..c6f45cc50 --- /dev/null +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VCCDepthFirstCircuitN.kt @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package org.kopi.galite.visual.pivotTable + +abstract class VCCDepthFirstCircuitN : VCalculateColumn() { + /** + * Initialisation of the calculation + */ + override fun init() {} + + /** + * Evaluates nodes + */ + override fun evalNode(row: VReportRow, column: Int): Any? = null + + /** + * Evaluates leafs + */ + open fun evalLeaf(row: VReportRow, column: Int): Any? = null + + /** + * Add calculated data into the report row + */ + override fun calculate(tree: VGroupRow, column: Int) { + if (tree.level > 1) { + val childCount: Int = tree.childCount + + for (i in 0 until childCount) { + calculate(tree.getChildAt(i) as VGroupRow, column) + } + } else { + val childCount: Int = tree.childCount + + for (i in 0 until childCount) { + val evaluatedObject = evalLeaf(tree.getChildAt(i) as VBaseRow, column) + + if (evaluatedObject != null) { + (tree.getChildAt(i) as VBaseRow).setValueAt(column, evaluatedObject) + } + } + } + tree.setValueAt(column, evalNode(tree, column)) + } +} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VCalculateColumn.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VCalculateColumn.kt new file mode 100644 index 000000000..6e2741ce3 --- /dev/null +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VCalculateColumn.kt @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package org.kopi.galite.visual.pivotTable + +abstract class VCalculateColumn { + /** + * Initialisation of the calculation + */ + abstract fun init() + + /** + * Evaluates nodes + */ + open fun evalNode(row: VReportRow, column: Int): Any? = null + + /** + * Add calculated data into the report row + */ + abstract fun calculate(tree: VGroupRow, column: Int) +} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VCellFormat.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VCellFormat.kt new file mode 100644 index 000000000..8c204f74c --- /dev/null +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VCellFormat.kt @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package org.kopi.galite.visual.pivotTable + +import java.math.BigDecimal +import java.time.Instant +import java.time.LocalDate +import java.time.LocalDateTime +import java.time.LocalTime + +import org.kopi.galite.type.format + +open class VCellFormat { + /** + * Return a formatted string of the Object + * @return the value formatted + */ + open fun format(value: Any?): String { + return when (value) { + is BigDecimal -> value.format() + is LocalDate -> value.format() + is LocalTime -> value.format() + is Instant -> value.format() + is LocalDateTime -> value.format() + else -> value?.toString() ?: "" + } + } +} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VCodeColumn.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VCodeColumn.kt new file mode 100644 index 000000000..c20fa1c8d --- /dev/null +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VCodeColumn.kt @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package org.kopi.galite.visual.pivotTable + +import kotlin.math.max + +import org.kopi.galite.visual.l10n.FieldLocalizer +import org.kopi.galite.visual.l10n.TypeLocalizer + +/** + * Represents a report column description + * + * @param ident The column identifier + * @param options The column options as bitmap + * @param align The column alignment + * @param groups The index of the column grouped by this one or -1 + * @param function An (optional) summation function + */ +abstract class VCodeColumn(ident: String?, + private val type: String?, + private val source: String?, + options: Int, align: Int, + groups: Int, function: VCalculateColumn?, + width: Int, + format: VCellFormat?, + private val idents: Array) + : VReportColumn(ident, + options, + align, + groups, + function, + width, + 1, + format) { + + protected var names: Array? = null // array of external representations + + /** + * Compares two objects. + * + * @param object1 the first operand of the comparison + * @param object2 the second operand of the comparison + * @return -1 if the first operand is smaller than the second + * 1 if the second operand if smaller than the first + * 0 if the two operands are equal + */ + abstract override fun compareTo(object1: Any, object2: Any): Int + + /** + * Return a string representation. + */ + override fun format(o: Any?): String { + return if (isFolded || o == null) { + "" + } else { + format?.format(o) ?: if (names != null) names!![getIndex(o)]!! else idents[getIndex(o)] + } + } + + /** + * Get the index of the value. + */ + abstract fun getIndex(value: Any): Int + + // ---------------------------------------------------------------------- + // LOCALIZATION + // ---------------------------------------------------------------------- + /** + * Localizes this field + * + * @param parentLocalizer the caller localizer + */ + override fun localize(parentLocalizer: FieldLocalizer) { + val loc: TypeLocalizer = parentLocalizer.manager.getTypeLocalizer(source, type) + names = Array(idents.size) { i -> + val label = loc.getCodeLabel(idents[i]) + this.width = max(this.width, label.length) + label + } + } + + fun initLabels(labels: Array) { + names = labels.map { + this.width = max(this.width, it.length) + it + }.toTypedArray() + } +} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VDateColumn.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VDateColumn.kt new file mode 100644 index 000000000..0efbf674d --- /dev/null +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VDateColumn.kt @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package org.kopi.galite.visual.pivotTable + +import java.time.LocalDate + +import org.kopi.galite.type.format +import org.kopi.galite.util.base.InconsistencyException + +/** + * Represents a report column description + * + * @param ident The column identifier + * @param options The column options as bitmap + * @param align The column alignment + * @param groups The index of the column grouped by this one or -1 + * @param function An (optional) summation function + * @param width The width of the cells + * @param format The format of the cells + */ +class VDateColumn(ident: String?, + options: Int, + align: Int, + groups: Int, + function: VCalculateColumn?, + width: Int, + format: VCellFormat?) + : VReportColumn(ident, + options, + align, + groups, + function, + 10, // width, default date format + 1, + format ?: VDateFormat()) { + /** + * Compare two objects. + * + * @param object1 the first operand of the comparison + * @param object2 the second operand of the comparison + * @return -1 if the first operand is smaller than the second + * 1 if the second operand if smaller than the first + * 0 if the two operands are equal + */ + override fun compareTo(object1: Any, object2: Any): Int = (object1 as LocalDate).compareTo(object2 as LocalDate) + + /** + * Returns the width of cells in this column in characters + */ + override fun getPrintedWidth(): Double = width * 0.7 + + /** + * Default date formatter. + */ + private class VDateFormat : VCellFormat() { + + override fun format(value: Any?): String = + when(value) { + null -> "" + is LocalDate -> value.format() + is java.sql.Date -> value.toLocalDate().format() + else -> throw InconsistencyException("bad type for $value") + } + } +} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VDecimalCodeColumn.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VDecimalCodeColumn.kt new file mode 100644 index 000000000..6ba645915 --- /dev/null +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VDecimalCodeColumn.kt @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package org.kopi.galite.visual.pivotTable + +import java.math.BigDecimal + +import org.kopi.galite.util.base.InconsistencyException + +class VDecimalCodeColumn(ident: String?, + type: String?, + source: String?, + options: Int, + align: Int, + groups: Int, + function: VCalculateColumn?, + width: Int, + format: VCellFormat?, + names: Array, + // array of internal representations + private val codes: Array) + : VCodeColumn(ident, + type, + source, + options, + align, + groups, + function, + width, + format, + names) { + /** + * Get the index of the value. + */ + override fun getIndex(value: Any): Int { + for (i in codes.indices) { + if (value == codes[i]) { + return i + } + } + throw InconsistencyException(">>>>$value") + } + + /** + * Returns the width of cells in this column in characters + */ + override fun getPrintedWidth(): Double = width * 0.7 + + /** + * Compares two objects. + * + * @param object1 the first operand of the comparison + * @param object2 the second operand of the comparison + * @return -1 if the first operand is smaller than the second + * 1 if the second operand if smaller than the first + * 0 if the two operands are equal + */ + override fun compareTo(object1: Any, object2: Any): Int = (object1 as BigDecimal) + .compareTo(object2 as BigDecimal) +} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VDecimalColumn.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VDecimalColumn.kt new file mode 100644 index 000000000..f0622e103 --- /dev/null +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VDecimalColumn.kt @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package org.kopi.galite.visual.pivotTable + +import java.math.BigDecimal + +import org.kopi.galite.visual.form.VDecimalField +import org.kopi.galite.type.format +import org.kopi.galite.util.base.InconsistencyException + +/** + * Represents a report column description + * + * @param ident The column identifier + * @param options The column options as bitmap + * @param align The column alignment + * @param groups The index of the column grouped by this one or -1 + * @param function An (optional) summation function + * @param maxScale The maximum of scale + * @param format The format of the cells + */ +class VDecimalColumn(ident: String?, + options: Int, + align: Int, + groups: Int, + function: VCalculateColumn?, + digits: Int, + maxScale: Int, + format: VCellFormat?) + : VReportColumn(ident, + options, + align, + groups, + function, + VDecimalField.computeWidth(digits, maxScale, null, null), + 1, + format ?: VFixedFormat(maxScale, true)) { + + var formula: String? = null + var maxScale = maxScale + private set + + /** + * Compare two objects. + * + * @param object1 the first operand of the comparison + * @param object2 the second operand of the comparison + * @return -1 if the first operand is smaller than the second + * 1 if the second operand if smaller than the first + * 0 if the two operands are equal + */ + override fun compareTo(object1: Any, object2: Any): Int = + (object1 as BigDecimal).compareTo(object2 as BigDecimal) + + /** + * Returns the width of cells in this column in characters + */ + override fun getPrintedWidth(): Double = width * 0.7 + + /** + * sets all column values to the same scale + */ + private class VFixedFormat(private val maxScale: Int, private val exactScale: Boolean) : VCellFormat() { + + override fun format(value: Any?): String = + when(value) { + null -> "" + is Int -> value.toString() + is BigDecimal -> if ((value).scale() > maxScale || exactScale) (value).setScale(maxScale, java.math.RoundingMode.HALF_UP).format() else value.format() + else -> throw InconsistencyException("bad type for $value") + } + } + + /** + * Sets display scale to maxScale + * all values will be set to the same scale + */ + fun setDisplayScale(scale: Int) { + format = VFixedFormat(scale, true) + maxScale = scale + } + + /** + * Sets maxScale + * all values with scale superior than maxScale will have + * maxScale as scale, and the other values will keep their scale. + */ + fun setMaxScale(scale: Int) { + format = VFixedFormat(scale, false) + maxScale = scale + } +} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VDefaultReportActor.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VDefaultReportActor.kt new file mode 100644 index 000000000..0dc08f683 --- /dev/null +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VDefaultReportActor.kt @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package org.kopi.galite.visual.pivotTable + +import org.kopi.galite.visual.VActor +import org.kopi.galite.visual.VlibProperties + +class VDefaultReportActor(menuIdent: String, + actorIdent: String, + iconName: String, + acceleratorKey: Int, + acceleratorModifier: Int) + : VActor(menuIdent, + null, + actorIdent, + null, + null, + acceleratorKey, + acceleratorModifier) { + + init { + this.iconName = iconName + localize() + } + + // ---------------------------------------------------------------------- + // LOCALIZATION + // ---------------------------------------------------------------------- + + private fun localize() { + menuName = VlibProperties.getString(menuIdent) + menuItem = VlibProperties.getString(ident) + help = VlibProperties.getString("$ident-help") + } +} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VGroupRow.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VGroupRow.kt new file mode 100644 index 000000000..cfd49ee5e --- /dev/null +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VGroupRow.kt @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package org.kopi.galite.visual.pivotTable + +/** + * Represents a description for a grouping row + * + * @param data The grouping row data + * @param level the grouping row level + */ +class VGroupRow(data: Array, private val level: Int) : VReportRow(data) { + + /** + * Sets data row + * + * @param column the index of the column + * @param value the value for the column + */ + override fun setValueAt(column: Int, value: Any?) { + data[column] = value + } + + /** + * Return the level of the node in the grouping tree + */ + override fun getLevel(): Int { + return level + } + + /** + * Returns true if all the child nodes of the level generation are visible. + * + * @param level level to test + */ + fun isUnfolded(level: Int): Boolean { + for (i in 0 until childCount) { + val child = getChildAt(i) as VReportRow + if (child.level > level) { + if ((child as VGroupRow).isUnfolded(level)) { + return true + } + } else { + if (child.visible) { + return true + } + } + } + return false + } + + /** + * Sets child node of the level generation to visible + * + * @param level level to be set visible + */ + fun setChildNodesVisible(level: Int) { + for (i in 0 until childCount) { + val child = getChildAt(i) as VReportRow + child.visible = true + if (getLevel() > level + 1) { + (child as VGroupRow).setChildNodesVisible(level) + } + } + } + + /** + * Sets child node of the level generation to invisible + * + * @param level level to be set visible + */ + fun setChildNodesInvisible(level: Int) { + for (i in 0 until childCount) { + val child = getChildAt(i) as VReportRow + when { + child.level > level -> + (child as VGroupRow).setChildNodesInvisible(level) + child is VGroupRow -> + child.setChildNodesInvisible() + else -> child.visible = false + } + } + } + + private fun setChildNodesInvisible() { + visible = false + if (getLevel() > 0) { + for (i in 0 until childCount) { + val row = getChildAt(i) as VReportRow + if (row is VGroupRow) { + row.setChildNodesInvisible() + } else { + row.visible = false + } + } + } + } + + companion object { + private const val serialVersionUID = 0L + } +} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VHelpGenerator.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VHelpGenerator.kt new file mode 100644 index 000000000..0a446449c --- /dev/null +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VHelpGenerator.kt @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package org.kopi.galite.visual.pivotTable + +import java.io.BufferedWriter +import java.io.File +import java.io.FileOutputStream +import java.io.IOException +import java.io.OutputStreamWriter +import java.io.PrintWriter + +import org.kopi.galite.visual.base.Utils +import org.kopi.galite.visual.VCommand +import org.kopi.galite.visual.VHelpGenerator + +/** + * This class implements a pretty printer + */ +class VHelpGenerator : VHelpGenerator() { + // ---------------------------------------------------------------------- + // ACCESSORS + // ---------------------------------------------------------------------- + /** + * prints a compilation unit + */ + fun helpOnReport(name: String, + commands: List, + model: MPivotTable, + help: String?): String? { + return try { + val file: File = Utils.getTempFile(name.replace("[:\\\\/*\"?|<>']".toRegex(), " "), "htm") + printer = PrintWriter(BufferedWriter(OutputStreamWriter(FileOutputStream(file), "UTF-8"))) + printer.println("") + printer.println("") + printer.println("
") + printer.println("$name") + printer.println("") + printer.println("") + printer.println("") + printer.println("") + printer.println("") + printer.println("") + printer.println("") + printer.println("

$name

") + if (help != null) { + printer.println("

$help

") + } + helpOnCommands(commands) + val columnCount: Int = model.getModelColumnCount() + printer.println("") + printer.println("") + printer.println("") + printer.println("") + printer.println("") + printer.println("
    
") + printer.println("
") + printer.println("
") + for (i in 0 until columnCount) { + val column: VReportColumn = model.getModelColumn(i) + if (column.options and Constants.CLO_HIDDEN == 0) { + column.helpOnColumn(this) + } + } + printer.println("
") + printer.println("
") + printer.println("
") + printer.println("
") + printer.println("kopiLeft Services SARL, Tunis TN
") + printer.println("kopiRight Managed Solutions GmbH, Wien AT
") + val version = Utils.getVersion() + for (i in version.indices) { + printer.println("" + version[i] + "
") + } + printer.println("
") + printer.println("
") + printer.println("") + printer.println("") + printer.close() + file.path + } catch (e: IOException) { + System.err.println("IO ERROR $e") + null + } + } + + /** + * prints a compilation unit + */ + fun helpOnColumn(label: String?, + help: String?) { + if (label == null) { + return + } + printer.println("
") + printer.println("

$label

") + printer.println("
") + if (help != null) { + printer.println("

$help

") + } + } +} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VIntegerCodeColumn.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VIntegerCodeColumn.kt new file mode 100644 index 000000000..c6da43658 --- /dev/null +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VIntegerCodeColumn.kt @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package org.kopi.galite.visual.pivotTable + +/** + * Represents a report column description + * + * @param ident The column identifier + * @param options The column options as bitmap + * @param align The column alignment + * @param groups The index of the column grouped by this one or -1 + * @param function An (optional) summation function + * @param width The width of the cells + * @param format The format of the cells + * @param names The names of the cells + * @param codes The codes of the cells, represents an array of internal representations + */ +class VIntegerCodeColumn(ident: String?, + type: String?, + source: String?, + options: Int, + align: Int, + groups: Int, + function: VCalculateColumn?, + width: Int, + format: VCellFormat?, + names: Array, + private var codes: IntArray) + : VCodeColumn(ident, + type, + source, + options, + align, + groups, + function, + width, + format, + names) { + + private var fastIndex = -1 // if array = {fastIndex, fastIndex + 1, ...} + + init { + fastIndex = codes[0] + for (i in 1 until codes.size) { + if (codes[i] != fastIndex + i) { + fastIndex = -1 + break + } + } + } + + /** + * Get the index of the value. + */ + override fun getIndex(value: Any): Int { + if (fastIndex != -1) { + return (value as Int) - fastIndex + } + for (i in codes.indices) { + if ((value as Int) == codes[i]) { + return i + } + } + return -1 + } + + /** + * Returns the width of cells in this column in characters + */ + override fun getPrintedWidth(): Double = width * 0.7 + + /** + * Compares two objects. + * + * @param object1 the first operand of the comparison + * @param object2 the second operand of the comparison + * @return -1 if the first operand is smaller than the second + * 1 if the second operand if smaller than the first + * 0 if the two operands are equal + */ + override fun compareTo(object1: Any, object2: Any): Int { + val v1 = (object1 as Int) + val v2 = (object2 as Int) + + return if (v1 < v2) -1 else if (v1 > v2) 1 else 0 + } +} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VIntegerColumn.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VIntegerColumn.kt new file mode 100644 index 000000000..fd57c20ab --- /dev/null +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VIntegerColumn.kt @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package org.kopi.galite.visual.pivotTable + +/** + * Represents a report column description + * + * @param ident The column ident + * @param options The column options as bitmap + * @param align The column alignment + * @param groups The index of the column grouped by this one or -1 + * @param function An (optional) summation function + */ +class VIntegerColumn(ident: String?, + options: Int, + align: Int, + groups: Int, + function: VCalculateColumn?, + width: Int, + format: VCellFormat?) + : VReportColumn(ident, + options, + align, + groups, + function, + width, + 1, + format ?: VIntegerFormat()) { + + /** + * Compare two objects. + * + * @param object1 the first operand of the comparison + * @param object2 the second operand of the comparison + * @return -1 if the first operand is smaller than the second + * 1 if the second operand if smaller than the first + * 0 if the two operands are equal + */ + override fun compareTo(object1: Any, object2: Any): Int { + val v1 = (object1 as Int) + val v2 = (object2 as Int) + + return if (v1 < v2) -1 else if (v1 > v2) 1 else 0 + } + + /** + * Returns the width of cells in this column in characters + */ + override fun getPrintedWidth(): Double = width * 0.7 + + private class VIntegerFormat : VCellFormat() { + override fun format(value: Any?): String { + // don't do substring when value.length() > columnWidth + return value?.toString() ?: "" + } + } +} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VMonthColumn.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VMonthColumn.kt new file mode 100644 index 000000000..aa88dd2fb --- /dev/null +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VMonthColumn.kt @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +package org.kopi.galite.visual.pivotTable + +import org.kopi.galite.type.Month + +/** + * Represents a report column description + * + * @param ident The column ident + * @param options The column options as bitmap + * @param align The column alignment + * @param groups The index of the column grouped by this one or -1 + * @param function An (optional) summation function + */ +class VMonthColumn(ident: String?, + options: Int, + align: Int, + groups: Int, + function: VCalculateColumn?, + format: VCellFormat?) + : VReportColumn(ident, + options, + align, + groups, + function, + 7, + 1, + format) { + /** + * Compare two objects. + * + * @param object1 the first operand of the comparison + * @param object2 the second operand of the comparison + * @return -1 if the first operand is smaller than the second + * 1 if the second operand if smaller than the first + * 0 if the two operands are equal + */ + override fun compareTo(object1: Any, object2: Any): Int { + return (object1 as Month).compareTo(object2 as Month) + } + + /** + * Returns the width of cells in this column in characters + */ + override fun getPrintedWidth(): Double = width * 0.7 +} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VNoRowException.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VNoRowException.kt new file mode 100644 index 000000000..e713a0d4f --- /dev/null +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VNoRowException.kt @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package org.kopi.galite.visual.pivotTable + +import org.kopi.galite.visual.VRuntimeException + +/** + * This class represents exceptions occurring during execution process. + * + * @param message the associated message. It's optional + */ +class VNoRowException(message: String? = null) : VRuntimeException(message) { + companion object { + private const val serialVersionUID = 0L + } +} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VPivotTable.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VPivotTable.kt new file mode 100644 index 000000000..77da59c70 --- /dev/null +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VPivotTable.kt @@ -0,0 +1,560 @@ +/* + * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package org.kopi.galite.visual.pivotTable + +import java.awt.event.KeyEvent +import java.io.File +import java.net.MalformedURLException +import java.text.MessageFormat + +import kotlin.jvm.Throws + +import org.jetbrains.annotations.TestOnly +import org.kopi.galite.visual.cross.VDynamicReport +import org.kopi.galite.visual.dsl.common.Trigger +import org.kopi.galite.visual.form.VConstants +import org.kopi.galite.visual.l10n.LocalizationManager +import org.kopi.galite.visual.print.Printable +import org.kopi.galite.visual.print.Printable.Companion.DOC_UNKNOWN +import org.kopi.galite.util.base.InconsistencyException +import org.kopi.galite.visual.ApplicationContext +import org.kopi.galite.visual.UIFactory +import org.kopi.galite.visual.UWindow +import org.kopi.galite.visual.VCommand +import org.kopi.galite.visual.VException +import org.kopi.galite.visual.VHelpViewer +import org.kopi.galite.visual.VRuntimeException +import org.kopi.galite.visual.VWindow +import org.kopi.galite.visual.WindowBuilder +import org.kopi.galite.visual.WindowController + +/** + * Represents a report model. + */ +abstract class VPivotTable internal constructor() : VWindow(), Constants, VConstants { + companion object { + + init { + WindowController.windowController.registerWindowBuilder( + org.kopi.galite.visual.Constants.MDL_REPORT, + object : WindowBuilder { + override fun createWindow(model: VWindow): UWindow { + return UIFactory.uiFactory.createView( + model) as UPivotTable + } + } + ) + } + } + + // ---------------------------------------------------------------------- + // DATA MEMBERS + // ---------------------------------------------------------------------- + private var cmdFold: VCommand? = null + private var cmdUnfold: VCommand? = null + private var cmdSort: VCommand? = null + private var cmdOpenLine: VCommand? = null + private var cmdFoldColumn: VCommand? = null + private var cmdUnfoldColumn: VCommand? = null + private var cmdColumnInfo: VCommand? = null + private var cmdEditColumn: VCommand? = null + val model: MPivotTable = MPivotTable() + private var built = false + private var pageTitle = "" + private var firstPageHeader = "" + var VKT_Report_Triggers = mutableListOf>(arrayOfNulls(Constants.TRG_TYPES.size)) + var VKT_Fields_Triggers = mutableListOf>() + var VKT_Commands_Triggers = mutableListOf>() + private val activeCommands = ArrayList() + var printOptions: PConfig = PConfig() // The print options + var media: String? = null // The media for this document + var help: String? = null + + override fun getType() = org.kopi.galite.visual.Constants.MDL_REPORT + + /** + * Redisplay the report after change in formatting + */ + @Deprecated("call method in display; model must not be refreshed") + fun redisplay() { + (getDisplay() as UPivotTable).redisplay() + } + + /** + * Close window + */ + @Deprecated("call method in display; model must not be closed") + fun close() { + getDisplay()!!.closeWindow() + } + + override fun destroyModel() { + try { + callTrigger(Constants.TRG_POSTREPORT) + } catch (v: VException) { + // ignore + } + super.destroyModel() + } + + /** + * initialise fields + */ + protected abstract fun init() + + /** + * build everything after loading + */ + protected fun build() { + init() + // localize the report using the default locale + localize() + model.build() + model.createTree() + (getDisplay() as UPivotTable?)?.build() + built = true + + // all commands are by default enabled + activeCommands.clear() + commands.forEachIndexed { i, vCommand -> + when { + vCommand.getIdent() == "Fold" -> cmdFold = vCommand + vCommand.getIdent() == "Unfold" -> cmdUnfold = vCommand + vCommand.getIdent() == "Sort" -> cmdSort = vCommand + vCommand.getIdent() == "FoldColumn" -> cmdFoldColumn = vCommand + vCommand.getIdent() == "UnfoldColumn" -> cmdUnfoldColumn = vCommand + vCommand.getIdent() == "OpenLine" -> cmdOpenLine = vCommand + vCommand.getIdent() == "ColumnInfo" -> cmdColumnInfo = vCommand + vCommand.getIdent() == "EditColumnData" -> cmdEditColumn = vCommand + else -> { + setCommandEnabled(vCommand, i, true) + } + } + } + } + + fun columnMoved(pos: IntArray) { + (getDisplay() as UPivotTable).columnMoved(pos) + } + // ---------------------------------------------------------------------- + // LOCALIZATION + // ---------------------------------------------------------------------- + override fun getLocalizationManger(): LocalizationManager { + return LocalizationManager(ApplicationContext.getDefaultLocale(), ApplicationContext.getDefaultLocale()) + } + + /** + * Localizes this report + * + */ + open fun localize() { + localize(manager) + } + + /** + * Localizes this report + * + * @param manager the manger to use for localization + */ + private fun localize(manager: LocalizationManager) { + if(ApplicationContext.getDefaultLocale() != locale) { + val loc = manager.getReportLocalizer(source) + + setPageTitle(loc.getTitle()) + help = loc.getHelp() + model.columns.forEach { it?.localize(loc) } + } + } + + // ---------------------------------------------------------------------- + // DISPLAY INTERFACE + // ---------------------------------------------------------------------- + open fun initReport() { + build() + callTrigger(Constants.TRG_PREREPORT) + } + // ---------------------------------------------------------------------- + // INTERFACE (COMMANDS) + // ---------------------------------------------------------------------- + /** + * Enables/disables the actor. + */ + fun setCommandEnabled(command: VCommand, index: Int, enable: Boolean) { + @Suppress("NAME_SHADOWING") + var enable = enable + + if (enable) { + // we need to check if VKT_Triggers is not empty + // ex : org.kopi.galite.visual.cross.VDynamicReport + if (VKT_Commands_Triggers.isNotEmpty() && hasCommandTrigger(Constants.TRG_CMDACCESS, index)) { + + val active: Boolean = try { + callCommandTrigger(Constants.TRG_CMDACCESS, index) as Boolean + } catch (e: VException) { + // trigger call error ==> command is considered as active + true + } + enable = active + } + command.setEnabled(enable) + activeCommands.add(command) + } else { + activeCommands.remove(command) + command.setEnabled(false) + } + } + + /** + * Enables/disables the actor. + */ + fun setCommandEnabled(command: VCommand, enable: Boolean) { + command.setEnabled(enable) + + if (enable) { + activeCommands.add(command) + } else { + activeCommands.remove(command) + } + } + + /** + * Sets the title + */ + fun setPageTitle(title: String) { + pageTitle = title + setTitle(title) + } + + fun setPageTitleParams(param: Any) { + setPageTitleParams(arrayOf(param)) + } + + fun setPageTitleParams(param1: Any, param2: Any) { + setPageTitleParams(arrayOf(param1, param2)) + } + + fun setPageTitleParams(params: Array) { + setPageTitle(MessageFormat.format(pageTitle, *params)) + } + + fun setFirstPageHeader(firstPageHeader: String) { + this.firstPageHeader = firstPageHeader + } + + fun getColumn(i: Int): VReportColumn { + return model.getModelColumn(i) + } + + fun foldSelection() { + val column = getSelectedColumn() + + if (column != -1) { + model.foldingColumn(column) + } else { + val (x, y) = getSelectedCell() + if (y != -1 && x != -1) { + model.foldingRow(y, x) + } + } + setMenu() + } + + fun unfoldSelection() { + val column = getSelectedColumn() + + if (column != -1) { + model.unfoldingColumn(column) + } else { + val (x, y) = getSelectedCell() + if (y != -1 && x != -1) { + model.unfoldingRow(y, x) + } + } + setMenu() + } + + fun foldSelectedColumn() { + val column = getSelectedColumn() + + if (column != -1) { + model.setColumnFolded(column, true) + } + (getDisplay() as UPivotTable).resetWidth() + setMenu() + } + + fun unfoldSelectedColumn() { + val column = getSelectedColumn() + + if (column != -1) { + model.setColumnFolded(column, false) + } + (getDisplay() as UPivotTable).resetWidth() + setMenu() + } + + /** + * Sort the displayed tree wrt to a column + */ + fun sortSelectedColumn() { + model.sortColumn(getSelectedColumn()) + } + + /** + * Sort the displayed tree wrt to a column + */ + @Throws(VException::class) + fun editLine() { + if (cmdOpenLine != null) { + cmdOpenLine!!.action.invoke() + } + } + + @Throws(VException::class) + fun setColumnData() { + if (cmdEditColumn != null) { + cmdEditColumn!!.action.invoke() + } + } + + @Throws(VException::class) + fun setColumnInfo() { + if (cmdColumnInfo != null) { + cmdColumnInfo!!.action.invoke() + } + } + + /** + * Returns the ID + */ + fun getValueOfFieldId(): Int { + var idCol = -1 + var id = -1 + var i = 0 + + while (i < model.getModelColumnCount() && idCol == -1) { + if (model.getModelColumn(i).ident == "ID") { + idCol = i + } + i++ + } + if (idCol != -1 && getSelectedCell().y != -1) { + id = (model.getRow(getSelectedCell().y)?.getValueAt(idCol) as Int) + } + return if (id == -1) { + throw VRuntimeException() + } else { + id + } + } + + /** + * Return the value of a field in the selected row + * by passing its name(key) + */ + fun getValueOfField(key: Any): Any? { + var col = -1 + var i = 0 + + while (i < model.getModelColumnCount() && col == -1) { + if (model.getModelColumn(i).ident == key) { + col = i + } + i++ + } + return if (col != -1 && getSelectedCell().y != -1) { + model.getRow(getSelectedCell().y)?.getValueAt(col) + } else null + } + + // ---------------------------------------------------------------------- + // PRIVATE METHODS + // ---------------------------------------------------------------------- + override fun executeVoidTrigger(trigger: Trigger?) { + trigger?.action?.method?.invoke() + } + + open fun executeObjectTrigger(trigger: Trigger?): Any = throw InconsistencyException("SHOULD BE REDEFINED") + + fun executeBooleanTrigger(trigger: Trigger?): Boolean = throw InconsistencyException("SHOULD BE REDEFINED") + + fun executeIntegerTrigger(trigger: Trigger?): Int = throw InconsistencyException("SHOULD BE REDEFINED") + + fun getDocumentType(): Int = DOC_UNKNOWN + + /** + * overridden by forms to implement triggers + * default triggers + */ + protected fun execTrigger(block: Any, trigger: Trigger?): Any? { + executeVoidTrigger(trigger) + return null + } + + /** + * Calls trigger for given event, returns last trigger called 's value. + */ + internal fun callCommandTrigger(event: Int, index: Int): Any? { + return callTrigger(event, index, VKT_Commands_Triggers) + } + + /** + * Calls trigger for given event, returns last trigger called 's value. + */ + internal fun callTrigger(event: Int): Any? { + return callTrigger(event, 0, VKT_Report_Triggers) + } + + /** + * Calls trigger for given event, returns last trigger called 's value. + */ + internal fun callFieldTrigger(event: Int, index: Int): Any? { + return callTrigger(event, index, VKT_Fields_Triggers) + } + + /** + * Calls trigger for given event, returns last trigger called 's value. + */ + private fun callTrigger(event: Int, index: Int, triggers: List>): Any? { + return when (Constants.TRG_TYPES[event]) { + Constants.TRG_VOID -> { + executeVoidTrigger(triggers[index][event]) + null + } + Constants.TRG_OBJECT -> executeObjectTrigger(triggers[index][event]) + Constants.TRG_BOOLEAN -> executeBooleanTrigger(triggers[index][event]) + else -> throw InconsistencyException("BAD TYPE" + Constants.TRG_TYPES[event]) + } + } + + /** + * Returns true if there is trigger associated with given event. + */ + internal fun hasTrigger(event: Int): Boolean = VKT_Report_Triggers[0][event] != null + + /** + * Returns true if there is trigger associated with given event. + */ + internal fun hasCommandTrigger(event: Int, index: Int): Boolean = VKT_Commands_Triggers[index][event] != null + + fun setMenu() { + if (!built) { + // only when commands are displayed + return + } + val column = getSelectedColumn() + val (x, y) = getSelectedCell() + val foldEnabled = column != -1 && !model.isColumnFold(column) || x != -1 && y != -1 && !model.isRowFold(y, x) + val unfoldEnabled = column != -1 || x != -1 && y != -1 + + if (cmdFold != null) { + setCommandEnabled(cmdFold!!, foldEnabled) + } + if (cmdUnfold != null) { + setCommandEnabled(cmdUnfold!!, unfoldEnabled) + } + if (cmdSort != null) { + setCommandEnabled(cmdSort!!, column != -1) + } + if (cmdOpenLine != null) { + setCommandEnabled(cmdOpenLine!!, model.isRowLine(y)) + } + if (cmdFoldColumn != null) { + setCommandEnabled(cmdFoldColumn!!, column != -1) + } + if (cmdUnfoldColumn != null) { + setCommandEnabled(cmdUnfoldColumn!!, column != -1) + } + if (cmdColumnInfo != null) { + setCommandEnabled(cmdColumnInfo!!, column != -1) + } + if (cmdEditColumn != null) { + setCommandEnabled(cmdEditColumn!!, column != -1 && model.getAccessibleColumn(column)!!.isAddedAtRuntime) + } + } + // ---------------------------------------------------------------------- + // IMPLEMENTATION + // ---------------------------------------------------------------------- + /** + * Returns the selected column or -1 if no column is selected. + */ + private fun getSelectedColumn(): Int = (getDisplay() as UPivotTable).getSelectedColumn() + + /** + * Returns the selected cell or !!! ??? if no cell is selected. + */ + private fun getSelectedCell(): Point = (getDisplay() as UPivotTable).getSelectedCell() + + // ---------------------------------------------------------------------- + // HELP + // ---------------------------------------------------------------------- + + fun genHelp(): String? { + val surl = StringBuffer() + val fileName: String? = VHelpGenerator().helpOnReport(pageTitle, + commands, + model, + help) + + return if (fileName == null) { + null + } else { + try { + surl.append(File(fileName).toURI().toURL().toString()) + } catch (mue: MalformedURLException) { + throw InconsistencyException(mue) + } + surl.toString() + } + } + + fun showHelp() { + VHelpViewer().showHelp(genHelp()) + } + + fun addDefaultReportCommands() { + initDefaultActors() + initDefaultCommands() + } + + private fun initDefaultActors() { + addActors(arrayOf( + VDefaultReportActor("File", "Quit", VDynamicReport.QUIT_ICON, KeyEvent.VK_ESCAPE, 0), + VDefaultReportActor("File", "Print", VDynamicReport.PRINT_ICON, KeyEvent.VK_F6, 0), + VDefaultReportActor("File", "ExportCSV", VDynamicReport.EXPORT_ICON, KeyEvent.VK_F8, 0), + VDefaultReportActor("File", "ExportXLSX", VDynamicReport.EXPORT_ICON, KeyEvent.VK_F9, KeyEvent.SHIFT_MASK), + VDefaultReportActor("File", "ExportPDF", VDynamicReport.EXPORT_ICON, KeyEvent.VK_F9, 0), + VDefaultReportActor("Action", "Fold", VDynamicReport.FOLD_ICON, KeyEvent.VK_F2, 0), + VDefaultReportActor("Action", "Unfold", VDynamicReport.UNFOLD_ICON, KeyEvent.VK_F3, 0), + VDefaultReportActor("Action", "FoldColumn", VDynamicReport.FOLD_COLUMN_ICON, KeyEvent.VK_UNDEFINED, 0), + VDefaultReportActor("Action", "UnfoldColumn", VDynamicReport.UNFOLD_COLUMN_ICON, KeyEvent.VK_UNDEFINED, 0), + VDefaultReportActor("Action", "Sort", VDynamicReport.SERIALQUERY_ICON, KeyEvent.VK_F4, 0), + VDefaultReportActor("Help", "Help", VDynamicReport.HELP_ICON, KeyEvent.VK_F1, 0), + )) + } + + private fun initDefaultCommands() { + actors.forEachIndexed { index, vActor -> + commands.add(VCommand(VConstants.MOD_ANY, this, vActor, index, vActor.ident)) + } + } + + @TestOnly + fun _hasTrigger(event: Int): Boolean = hasTrigger(event) +} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VReportColumn.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VReportColumn.kt new file mode 100644 index 000000000..218bc01db --- /dev/null +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VReportColumn.kt @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package org.kopi.galite.visual.pivotTable + +import org.kopi.galite.visual.l10n.FieldLocalizer +import org.kopi.galite.visual.l10n.ReportLocalizer +import org.kopi.galite.visual.util.LineBreaker + +/** + * Represents a report column description + * + * @param ident The identifier of the field + * @param options The column options as bitmap + * @param align The column alignment + * @param groups The index of the column grouped by this one or -1 + * @param function An (optional) function + * @param width The width of a cell in characters + * @param height The height of a cell in characters + * @param format format of the cells + */ +abstract class VReportColumn( + val ident: String?, + val options: Int, + val align: Int, + var groups: Int, + val function: VCalculateColumn?, + var width: Int, + var height: Int, + protected var format: VCellFormat?) { + + // ---------------------------------------------------------------------- + // DATA MEMBERS + // ---------------------------------------------------------------------- + var label: String = "" + var help: String? = null + var isVisible: Boolean = true + open var isFolded: Boolean = false + var isAddedAtRuntime: Boolean = false + var userDefinedLabel: Boolean = false + private var styles: Array? = null + + /** + * Returns true if this Column is hidden + */ + open fun isHidden(): Boolean { + return options and Constants.CLO_HIDDEN > 0 + } + + /** + * Returns the width of cells in this column in characters + */ + open fun getPrintedWidth(): Double { + return width.toDouble() + } + + open fun format(o: Any?): String { + return if (isFolded || o == null) { + "" + } else if (format != null) { + format!!.format(o) + } else if (height == 1) { + val str = o.toString() + val strLength = str.length + if (strLength <= width) str else str.substring(0, width) + } else { + o.toString() + } + } + + fun formatWithLineBreaker(o: Any?): String { + return LineBreaker.modelToText(format(o), width) + } + + /** + * Compare two objects. + * + * @param object1 the first operand of the comparison + * @param object2 the second operand of the comparison + * @return -1 if the first operand is smaller than the second + * 1 if the second operand if smaller than the first + * 0 if the two operands are equal + */ + abstract fun compareTo(object1: Any, object2: Any): Int + + fun helpOnColumn(help: VHelpGenerator) { + help.helpOnColumn(label, this.help) + } + // ---------------------------------------------------------------------- + // LOCALIZATION + // ---------------------------------------------------------------------- + /** + * Localizes this field + * + * @param parent the caller localizer + */ + fun localize(parent: ReportLocalizer) { + if (!isHidden() && ident != "") { + val loc: FieldLocalizer = parent.getFieldLocalizer(ident!!) + + label = loc.getLabel() ?: "" + help = loc.getHelp() + localize(loc) + } + } + + /** + * Localizes this field + * + * @param parentLocalizer the caller localizer + */ + protected open fun localize(parentLocalizer: FieldLocalizer) { + // by default nothing to do + } + + fun getStyles(): Array { + return if (styles == null) { + val style = ColumnStyle() + style.fontName = 0 + style.backgroundCode = Constants.CLR_WHITE + style.foregroundCode = Constants.CLR_BLACK + arrayOf(style) + } else { + styles!! + } + } + + fun setStyles(styles: Array) { + this.styles = styles + } +} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VReportCommand.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VReportCommand.kt new file mode 100644 index 000000000..217da3460 --- /dev/null +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VReportCommand.kt @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package org.kopi.galite.visual.pivotTable + +import org.kopi.galite.visual.dsl.common.Trigger +import org.kopi.galite.visual.print.DefaultPrintManager +import org.kopi.galite.visual.print.PrintManager +import org.kopi.galite.visual.Action +import org.kopi.galite.visual.ActionHandler +import org.kopi.galite.visual.PrinterManager +import org.kopi.galite.visual.VActor +import org.kopi.galite.visual.VCommand +import org.kopi.galite.visual.VHelpGenerator + +class VReportCommand( + val report: VPivotTable, + actor: VActor +) : VCommand(0xFFFF, null, actor, actor.number, actor.ident), ActionHandler { + + override fun setEnabled(enabled: Boolean) { + if (actor != null) { + actor!!.isEnabled = enabled + actor!!.number = trigger + actor!!.handler = this + } + } + + /** + * Performs the appropriate action asynchronously. + * You can use this method to perform any operation out of the UI event process + * + * @param action the action to perform. + * @param block This action should block the UI thread ? + */ + @Deprecated("use method performAsyncAction", ReplaceWith("performAsyncAction(action, block)")) + override fun performAction(action: Action, block: Boolean) { + report.performAsyncAction(action) + /*try { + executeVoidTrigger(getTrigger()); + } catch (Exception e) { + e.printStackTrace(); + }*/ + } + + /** + * Performs the appropriate action asynchronously. + * You can use this method to perform any operation out of the UI event process + * + * @param action the action to perform. + */ + override fun performAsyncAction(action: Action) { + report.performAsyncAction(action) + /*try { + executeVoidTrigger(getTrigger()); + } catch (Exception e) { + e.printStackTrace(); + }*/ + } + + /** + * Performs a void trigger + * + * @param VKT_Type the number of the trigger + */ + override fun executeVoidTrigger(VKT_Type: Int) { + when (VKT_Type) { + Constants.CMD_QUIT -> report.close() + Constants.CMD_FOLD -> report.foldSelection() + Constants.CMD_UNFOLD -> report.unfoldSelection() + Constants.CMD_SORT -> report.sortSelectedColumn() + Constants.CMD_FOLD_COLUMN -> report.foldSelectedColumn() + Constants.CMD_UNFOLD_COLUMN -> report.unfoldSelectedColumn() + Constants.CMD_HELP -> report.showHelp() + } + } + + /** + * Performs a void trigger + * + * @param trigger the trigger + */ + override fun executeVoidTrigger(trigger: Trigger?) { + // DO NOTHING ! + } + + // ---------------------------------------------------------------------- + // HELP HANDLING + // ---------------------------------------------------------------------- + override fun helpOnCommand(help: VHelpGenerator) { + if (actor == null) { + return + } + actor!!.helpOnCommand(help) + } + +} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VReportRow.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VReportRow.kt new file mode 100644 index 000000000..e8af5c565 --- /dev/null +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VReportRow.kt @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package org.kopi.galite.visual.pivotTable + +import javax.swing.tree.DefaultMutableTreeNode + +abstract class VReportRow(val data: Array) : DefaultMutableTreeNode() { + var visible = false + + /** + * Return the level of the node in the grouping tree, starting with 0 at + * the base rows (leafs). + * + * @return the level of the node in the grouping tree + */ + abstract override fun getLevel(): Int + + /** + * Return the object at column + * + * @param column the index of the column + * @return the object to be displayed + */ + fun getValueAt(column: Int): Any? = data[column] + + /** + * Sets data at column of certain index + * + * @param column the index of the column + * @param value the value for the column + */ + open fun setValueAt(column: Int, value: Any?) { + data[column] = value + } + + /** + * Clone Array's objects + */ + fun cloneArray() = data.clone() + + /** + * Compare two VReportRows within specified column + * + * @param other Report row to compare to + * @param position position in data + * @param column + * @return + */ + fun compareTo(other: VReportRow, position: Int, column: VReportColumn): Int { + val data = data[position] + val rowData = other.data[position] + + // check for nulls: define null less than everything + return when { + data == null && rowData == null -> 0 + data == null -> -1 + rowData == null -> 1 + else -> column.compareTo(data, rowData) + } + } + + companion object { + private const val serialVersionUID = 0L + } +} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VSeparatorColumn.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VSeparatorColumn.kt new file mode 100644 index 000000000..48cc374da --- /dev/null +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VSeparatorColumn.kt @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package org.kopi.galite.visual.pivotTable + +/** + * Represents a report column description + * + * @param ident The column identifier + * @param options The column options as bitmap + * @param align The column alignment + * @param groups The index of the column grouped by this one or -1 + * @param function An (optional) summation function + */ +class VSeparatorColumn: VReportColumn("", 0, 0, 0, null, 1, 1, null) { + /** + * No text here + */ + override fun format(o: Any?): String { + return "" + } + + /** + * Compare two objects. + * + * @param object1 the first operand of the comparison + * @param object2 the second operand of the comparison + * @return -1 if the first operand is smaller than the second + * 1 if the second operand if smaller than the first + * 0 if the two operands are equal + */ + override fun compareTo(object1: Any, object2: Any): Int { + return 0 + } + + /** + * Returns the visibility of the column + */ + override var isFolded: Boolean = false + get() = true +} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VStringCodeColumn.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VStringCodeColumn.kt new file mode 100644 index 000000000..050b9e874 --- /dev/null +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VStringCodeColumn.kt @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package org.kopi.galite.visual.pivotTable + +import org.kopi.galite.util.base.InconsistencyException + +/** + * Represents a report column description + * + * @param ident The column ident + * @param options The column options as bitmap + * @param align The column alignment + * @param groups The index of the column grouped by this one or -1 + * @param function An (optional) summation function + */ +class VStringCodeColumn(ident: String?, + type: String?, + source: String?, + options: Int, + align: Int, + groups: Int, + function: VCalculateColumn?, + width: Int, + format: VCellFormat?, + names: Array, + private val codes: Array) + : VCodeColumn(ident, + type, + source, + options, + align, + groups, + function, + width, + format, + names) { + + /** + * Get the index of the value. + */ + override fun getIndex(value: Any): Int { + codes.forEachIndexed { index, code -> + if (value == code) { + return index + } + } + throw InconsistencyException(">>>>$value") + } + + /** + * Returns the width of cells in this column in characters + */ + override fun getPrintedWidth(): Double = width * 0.7 + + /** + * Compares two objects. + * + * @param object1 the first operand of the comparison + * @param object2 the second operand of the comparison + * @return -1 if the first operand is smaller than the second + * 1 if the second operand if smaller than the first + * 0 if the two operands are equal + */ + override fun compareTo(object1: Any, object2: Any): Int { + return (object1 as String).compareTo((object2 as String)) + } +} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VStringColumn.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VStringColumn.kt new file mode 100644 index 000000000..f158104c6 --- /dev/null +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VStringColumn.kt @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package org.kopi.galite.visual.pivotTable + +/** + * Represents a report column description + * + * @param ident The column ident + * @param options The column options as bitmap + * @param align The column alignment + * @param groups The index of the column grouped by this one or -1 + * @param function An (optional) summation function + */ +class VStringColumn(ident: String?, + options: Int, + align: Int, + groups: Int, + function: VCalculateColumn?, + width: Int, + height: Int, + format: VCellFormat?) + : VReportColumn(ident, + options, + align, + groups, + function, + width, + height, + format) { + + /** + * Compare two objects. + * + * @param object1 the first operand of the comparison + * @param object2 the second operand of the comparison + * @return -1 if the first operand is smaller than the second + * 1 if the second operand if smaller than the first + * 0 if the two operands are equal + */ + override fun compareTo(object1: Any, object2: Any): Int = (object1 as String).compareTo((object2 as String)) +} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VTimeColumn.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VTimeColumn.kt new file mode 100644 index 000000000..98db3c070 --- /dev/null +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VTimeColumn.kt @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package org.kopi.galite.visual.pivotTable + +import java.sql.Time +import java.time.LocalTime + +import org.kopi.galite.type.format +import org.kopi.galite.util.base.InconsistencyException + +/** + * Represents a report column description + * + * @param ident The column ident + * @param options The column options as bitmap + * @param align The column alignment + * @param groups The index of the column grouped by this one or -1 + * @param function An (optional) summation function + */ +class VTimeColumn(ident: String?, + options: Int, + align: Int, + groups: Int, + function: VCalculateColumn?, + format: VCellFormat?) + : VReportColumn(ident, + options, + align, + groups, + function, + 5, // width, default time format + 1, + format ?: VTimeFormat()) { + /** + * Compares two objects. + * + * @param object1 the first operand of the comparison + * @param object2 the second operand of the comparison + * @return -1 if the first operand is smaller than the second + * 1 if the second operand if smaller than the first + * 0 if the two operands are equal + */ + override fun compareTo(object1: Any, object2: Any): Int { + return (object1 as LocalTime).compareTo(object2 as LocalTime) + } + + /** + * Returns the width of cells in this column in characters + */ + override fun getPrintedWidth(): Double = width * 0.7 + + /** + * Default time formatter. + */ + private class VTimeFormat : VCellFormat() { + + override fun format(value: Any?): String = + when(value) { + null -> "" + is LocalTime -> value.format() + is Time -> value.toLocalTime().format() + else -> throw InconsistencyException("bad type for $value") + } + } +} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VTimestampColumn.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VTimestampColumn.kt new file mode 100644 index 000000000..52b0b14d0 --- /dev/null +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VTimestampColumn.kt @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package org.kopi.galite.visual.pivotTable + +import java.time.Instant +import java.time.LocalDateTime + +import org.kopi.galite.type.format +import org.kopi.galite.util.base.InconsistencyException + +/** + * Represents a report column description + * + * @param ident The column ident + * @param options The column options as bitmap + * @param align The column alignment + * @param groups The index of the column grouped by this one or -1 + * @param function An (optional) summation function + */ +class VTimestampColumn(ident: String?, + options: Int, + align: Int, + groups: Int, + function: VCalculateColumn?, + format: VCellFormat?) + : VReportColumn(ident, + options, + align, + groups, + function, + 10 + 1 + 8, // width, default timestamp format (date + space + time) + 1, + format ?: VTimestampFormat()) { + /** + * Compares two objects. + * + * @param object1 the first operand of the comparison + * @param object2 the second operand of the comparison + * @return -1 if the first operand is smaller than the second + * 1 if the second operand if smaller than the first + * 0 if the two operands are equal + */ + override fun compareTo(object1: Any, object2: Any): Int { + return (object1 as Instant).compareTo(object2 as Instant) + } + + /** + * Returns the width of cells in this column in characters + */ + override fun getPrintedWidth(): Double = width * 0.7 + + /** + * Default timestamp formatter. + */ + private class VTimestampFormat : VCellFormat() { + + override fun format(value: Any?): String = + when(value) { + null -> "" + is Instant -> value.format() + is LocalDateTime -> value.format() + else -> throw InconsistencyException("bad type for $value") + } + } +} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VWeekColumn.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VWeekColumn.kt new file mode 100644 index 000000000..99bf14bf4 --- /dev/null +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VWeekColumn.kt @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package org.kopi.galite.visual.pivotTable + +import org.kopi.galite.type.Week + +/** + * Represents a report column description + * + * @param ident The column ident + * @param options The column options as bitmap + * @param align The column alignment + * @param groups The index of the column grouped by this one or -1 + * @param function An (optional) summation function + */ +class VWeekColumn(ident: String?, + options: Int, + align: Int, + groups: Int, + function: VCalculateColumn?, + format: VCellFormat?) + : VReportColumn(ident, + options, + align, + groups, + function, + 7, // width, default week format + 1, + format) { + /** + * Compare two objects. + * + * @param object1 the first operand of the comparison + * @param object2 the second operand of the comparison + * @return -1 if the first operand is smaller than the second + * 1 if the second operand if smaller than the first + * 0 if the two operands are equal + */ + override fun compareTo(object1: Any, object2: Any): Int = (object1 as Week).compareTo(object2 as Week) + + /** + * Returns the width of cells in this column in characters + */ + override fun getPrintedWidth(): Double = width * 0.7 +} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/triggers/Triggers.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/triggers/Triggers.kt new file mode 100644 index 000000000..890095228 --- /dev/null +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/triggers/Triggers.kt @@ -0,0 +1,286 @@ +/* + * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package org.kopi.galite.visual.report.triggers + +import java.math.BigDecimal + +import org.kopi.galite.visual.dsl.report.ReportField +import org.kopi.galite.visual.report.VBaseRow +import org.kopi.galite.visual.report.VCCDepthFirstCircuitN +import org.kopi.galite.visual.report.VCalculateColumn +import org.kopi.galite.visual.report.VGroupRow +import org.kopi.galite.visual.report.VReportRow + +/////////////////////////////////////////////////////////////////////////// +// This file regroups predefined report triggers +/////////////////////////////////////////////////////////////////////////// + +/** + * Compute the integer sum in a report column + */ +fun ReportField.sumInteger(): VCalculateColumn { + + return object : VCCDepthFirstCircuitN() { + + override fun evalNode(row: VReportRow, column: Int): Any { + val childCount = row.childCount + var result = 0 + + for (i in 0 until childCount) { + val child = row.getChildAt(i) as VReportRow + val value = child.getValueAt(column) as Int? + + if (value != null) { + result += value + } + } + return result + } + } +} + +/** + * Compute the number of entries in a report column + */ +fun ReportField.countInteger(): VCalculateColumn { + return object : VCCDepthFirstCircuitN() { + override fun evalNode(row: VReportRow, column: Int): Any { + val childCount = row.childCount + + return if (row.level > 1) { + // the value of a node is the sum of + // other nodes (contain no leafs) + var result = 0 + + for (i in 0 until childCount) { + val child = row.getChildAt(i) as VReportRow + val value = child.getValueAt(column) as Int? + + if (value != null) { + result += value + } + } + result + } else { + // the value is the number of the children + // if the children are leafs + childCount + } + } + } +} + +/** + * Compute the decimal sum in a report column + */ +fun ReportField.sumDecimal(): VCalculateColumn { + return object : VCCDepthFirstCircuitN() { + override fun evalNode(row: VReportRow, column: Int): Any { + val childCount = row.childCount + var result = BigDecimal.valueOf(0, 2) + + for (i in 0 until childCount) { + val child = row.getChildAt(i) as VReportRow + val value = child.getValueAt(column) as? BigDecimal + + if (value != null) { + result += value + } + } + return result + } + } +} + +/** + * Compute the integer sum in a report column + */ +fun ReportField.sumNullInteger(): VCalculateColumn where T: Comparable, T: Number { + return object : VCCDepthFirstCircuitN() { + override fun evalNode(row: VReportRow, column: Int): Any? { + val childCount = row.childCount + var result = 0 + var valueFound = false + + for (i in 0 until childCount) { + val child = row.getChildAt(i) as VReportRow + val value = child.getValueAt(column) as Int? + + if (value != null) { + valueFound = true + result += value + } + } + return if (valueFound) result else null + } + } +} + +/** + * Compute the decimal sum in a report column + */ +fun ReportField.sumNullDecimal(): VCalculateColumn { + return object : VCCDepthFirstCircuitN() { + override fun evalNode(row: VReportRow, column: Int): Any? { + val childCount = row.childCount + var valueFound = false + var result = BigDecimal.valueOf(0, 2) + + for (i in 0 until childCount) { + val child = row.getChildAt(i) as VReportRow + val value = child.getValueAt(column) as? BigDecimal + + if (value != null) { + valueFound = true + result += value + } + } + return if (valueFound) result else null + } + } +} + +/** + * Report a value when all child are identical + */ +fun ReportField<*>.reportIdenticalValue(): VCalculateColumn { + return object : VCCDepthFirstCircuitN() { + override fun evalNode(row: VReportRow, column: Int): Any? { + val childCount = row.childCount + val value = (row.getChildAt(0) as VReportRow).getValueAt(column) + + return if (value == null) { + null + } else { + for (i in 1 until childCount) { + val child = row.getChildAt(i) as VReportRow + + if (value != child.getValueAt(column)) { + return null + } + } + value + } + } + } +} + +/** + * Compute the integer average in a report column + */ +fun ReportField.avgInteger(): VCalculateColumn where T: Comparable, T: Number { + return object : VCCDepthFirstCircuitN() { + override fun evalNode(row: VReportRow, column: Int): Any { + val childCount = row.childCount + var result = 0 + + for (i in 0 until childCount) { + val child = row.getChildAt(i) as VReportRow + val value = child.getValueAt(column) as Int? + + if (value != null) { + result += value + } + } + return result / childCount + } + } +} + +/** + * Compute the integer sum in a report column and the the value + * in the leaves with a serial number + */ +fun ReportField.serialInteger(): VCalculateColumn where T: Comparable, T: Number { + return object : VCCDepthFirstCircuitN() { + override fun evalNode(row: VReportRow, column: Int): Any { + val childCount = row.childCount + + return if (row.level > 1) { + // the value of a node is the sum of + // other nodes (contain no leafs) + var result = 0 + + for (i in 0 until childCount) { + val child = row.getChildAt(i) as VReportRow + val value = child.getValueAt(column) as Int? + + if (value != null) { + result += value + } + } + result + } else { + // the value is the number of the children + // if the children are leafs + childCount + } + } + + /** + * Add calculated data into the report row + */ + override fun calculate(tree: VGroupRow, column: Int) { + if (tree.level > 1) { + val childCount = tree.childCount + + for (i in 0 until childCount) { + calculate(tree.getChildAt(i) as VGroupRow, column) + } + } else { + val childCount = tree.childCount + + for (i in 0 until childCount) { + // set leave to serial number + (tree.getChildAt(i) as VBaseRow).setValueAt(column, i + 1) + } + } + tree.setValueAt(column, evalNode(tree, column)) + } + } +} + +/** + * Compute the decimal average in a report column + */ +fun ReportField.avgDecimal(): VCalculateColumn { + return object : VCCDepthFirstCircuitN() { + override fun evalNode(row: VReportRow, column: Int): Any { + val leafCount = row.leafCount + var notNullLeafCount = 0.0 + var result = BigDecimal.valueOf(0, 2) + var leaf = row.firstLeaf as? VReportRow + + for (i in 0 until leafCount) { + val value = leaf!!.getValueAt(column) as? BigDecimal + + if (value != null) { + result += value + notNullLeafCount++ + } + leaf = leaf.nextLeaf as? VReportRow + } + return if (notNullLeafCount != 0.0) { + (result / BigDecimal(notNullLeafCount)).setScale(2) + } else { + BigDecimal.valueOf(0, 2) + } + } + } +} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/ColumnStyleGenerator.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/ColumnStyleGenerator.kt new file mode 100644 index 000000000..4a09eb509 --- /dev/null +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/ColumnStyleGenerator.kt @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +package org.kopi.galite.visual.ui.vaadin.pivotTable + +import org.kopi.galite.visual.pivotTable.MPivotTable +import org.kopi.galite.visual.pivotTable.VReportColumn +import org.kopi.galite.visual.pivotTable.VSeparatorColumn + +import com.vaadin.flow.function.SerializableFunction + +/** + * The `ColumnStyleGenerator` is the dynamic report + * implementation for generating CSS class names for + * cells in the column [column]. + * + * @param model The report model. + */ +class ColumnStyleGenerator(private val model: MPivotTable, val column: VReportColumn) : SerializableFunction { + + //--------------------------------------------------- + // IMPLEMENTATIONS + //--------------------------------------------------- + override fun apply(item: DPivotTable.ReportModelItem): String = + buildString { + if (item.rowIndex == model.getRowCount() - 1) { + append("last-row") + } + + if (column is VSeparatorColumn) { + append(" separator") + } else { + append(" level-" + model.getRow(item.rowIndex)!!.level) + } + } +} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/ColumnsSelector.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/ColumnsSelector.kt new file mode 100644 index 000000000..8c81984cc --- /dev/null +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/ColumnsSelector.kt @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +package org.kopi.galite.visual.ui.vaadin.pivotTable + +import com.vaadin.flow.component.checkbox.Checkbox +import com.vaadin.flow.component.contextmenu.ContextMenu +import com.vaadin.flow.component.dependency.CssImport +import com.vaadin.flow.component.html.Div +import com.vaadin.flow.component.icon.Icon +import com.vaadin.flow.component.icon.VaadinIcon + +@CssImport(value = "./styles/galite/columnselector.css") +class ColumnsSelector : Div() { + private val contextMenu = ContextMenu() + private val icon: Icon = Icon(VaadinIcon.ANGLE_DOUBLE_RIGHT) + + init { + contextMenu.target = icon + contextMenu.isOpenOnClick = true + className = "columns-selector" + icon.className = "columns-selector-button" + icon.setSize("1em") + + add(icon, contextMenu) + } + + fun build(table: DTable) { + contextMenu.removeAll() + + table.viewColumns.forEach { + val checkbox = Checkbox(table.model.model.columns[it]?.label) + val column = table.getColumnByKey(it.toString()) + + checkbox.className = "checkbox-selector" + checkbox.value = column.isVisible + checkbox.addValueChangeListener { e -> + column.isVisible = e.value + table.model.model.columns[it]?.isVisible = e.value + } + val item = contextMenu.addItem(checkbox) + + item.element.setAttribute("onClick", "event.stopPropagation()") + item.element.classList.add("column-item-selector") + } + } +} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/DPivotTable.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/DPivotTable.kt new file mode 100644 index 000000000..da5ad550e --- /dev/null +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/DPivotTable.kt @@ -0,0 +1,455 @@ +/* + * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +package org.kopi.galite.visual.ui.vaadin.pivotTable + +import java.awt.Color + +import org.kopi.galite.visual.pivotTable.MPivotTable +import org.kopi.galite.visual.pivotTable.Parameters +import org.kopi.galite.visual.pivotTable.Point +import org.kopi.galite.visual.pivotTable.UPivotTable +import org.kopi.galite.visual.pivotTable.VPivotTable +import org.kopi.galite.visual.pivotTable.VReportRow +import org.kopi.galite.visual.pivotTable.VSeparatorColumn +import org.kopi.galite.visual.ui.vaadin.base.BackgroundThreadHandler.access +import org.kopi.galite.visual.ui.vaadin.base.BackgroundThreadHandler.accessAndPush +import org.kopi.galite.visual.ui.vaadin.visual.DWindow +import org.kopi.galite.visual.Action +import org.kopi.galite.visual.VException +import org.kopi.galite.visual.VlibProperties + +import com.vaadin.flow.component.Unit +import com.vaadin.flow.component.contextmenu.ContextMenu +import com.vaadin.flow.component.grid.Grid +import com.vaadin.flow.component.html.Span +import com.vaadin.flow.component.orderedlayout.VerticalLayout +import org.vaadin.addons.componentfactory.PivotTable + +import org.kopi.galite.visual.ui.vaadin.report.VTable + +/** + * The `DReport` is the visual part of the [VReport] model. + * + * The `DReport` ensure the implementation of the [UReport] + * specifications. + * + * @param report The report model. + */ +class DPivotTable(private val report: VPivotTable) : DWindow(report), UPivotTable { + + //--------------------------------------------------- + // DATA MEMBERS + //--------------------------------------------------- + private val model: MPivotTable = report.model // report model + private lateinit var table: DTable + private var parameters: Parameters? = null + private var columnsSelector: ColumnsSelector = ColumnsSelector() + private var pivotData = PivotTable.PivotData() + private var pivotOptions = PivotTable.PivotOptions() + private var listeRows = mutableListOf() + + init { + model.addReportListener(this) + getModel()!!.setDisplay(this) + setSizeFull() + + add(columnsSelector) + } + + //--------------------------------------------------- + // IMPLEMENTATIONS + //--------------------------------------------------- + override fun run() { + report.initReport() + report.setMenu() + table.focus() + setInfoTable() + } + + override fun build() { + // load personal configuration + table = DTable(VTable(model, buildRows())) + + + model.columns.forEach { + if(it?.label != "" ) { + pivotData.addColumn(it?.label, it?.javaClass) + } + } + + model.baseRows.forEach { + it?.data?.forEach { row -> + if(row != null) { + listeRows.add(row) + } + } + pivotData.addRow(*listeRows.toTypedArray()) + listeRows.clear() + } + + var pivot = PivotTable(pivotData, pivotOptions, PivotTable.PivotMode.INTERACTIVE) + add(pivot) + } + + override fun redisplay() { + contentChanged() + } + + /** + * Reorders the report columns. + * @param newOrder The new columns order. + */ + fun reorder(newOrder: IntArray) { + model.columnMoved(newOrder) + accessAndPush(currentUI) { + table.setColumnOrder( + newOrder.map { table.getColumnByKey(it.toString()) } + ) + for (col in 0 until model.getAccessibleColumnCount()) { + table.getColumnByKey(col.toString()).isVisible = + !model.getAccessibleColumn(col)!!.isFolded + || model.getAccessibleColumn(col) is VSeparatorColumn + } + } + } + + override fun removeColumn(position: Int) { + val indexInView = table.convertColumnIndexToView(position) + + model.removeColumn(position) + table.removeColumnByKey(position.toString()) + model.initializeAfterRemovingColumn(indexInView) + + // set new order. + val pos = IntArray(model.getAccessibleColumnCount()) + for (i in 0 until model.getAccessibleColumnCount()) { + pos[i] = if (model.getDisplayOrder(i) > position) model.getDisplayOrder(i) - 1 else model.getDisplayOrder(i) + } + report.columnMoved(pos) + } + + override fun addColumn(position: Int) { + accessAndPush(currentUI) { + var position = position + position = table.convertColumnIndexToView(position) + position += 1 + val headerLabel = "col" + model.getColumnCount() + val span = VerticalLayout(Span(headerLabel)) + model.addColumn(headerLabel, position) + val column = table.addColumn(model.getColumnCount() - 1) + column.setHeader(span) + column.flexGrow = 0 + addHeaderListeners(column, span) + // move last column to position. + val pos = IntArray(model.getAccessibleColumnCount()) + for (i in 0 until position) { + pos[i] = model.getDisplayOrder(i) + } + for (i in position + 1 until model.getAccessibleColumnCount()) { + pos[i] = model.getDisplayOrder(i - 1) + } + pos[position] = model.getDisplayOrder(model.getAccessibleColumnCount() - 1) + report.columnMoved(pos) + } + } + + override fun addColumn() { + addColumn(table.getColumnCount() - 1) + } + + override fun getTable(): UPivotTable.UTable { + return table + } + + override fun contentChanged() { + if (this::table.isInitialized) { + accessAndPush(currentUI) { + table.setItems(buildRows()) + table.model.fireContentChanged() + columnsSelector.build(table) + } + } + } + + override fun columnMoved(pos: IntArray) { + reorder(pos) + model.columnMoved(pos) + redisplay() + } + + override fun resetWidth() { + access(currentUI) { + table.resetWidth() + } + } + + override fun getSelectedColumn(): Int { + return table.selectedColumn + } + + override fun getSelectedCell(): Point = Point(table.selectedColumn, table.selectedRow) + + override fun setColumnLabel(column: Int, label: String) { + access(currentUI) { + table.getColumnByKey(column.toString()).setHeader(label) + } + } + + /** + * Return the columns display order. + * @return The columns display order. + */ + val displayOrder: IntArray + get() { + val displayOrder = IntArray(model.getColumnCount()) + for (i in 0 until model.getColumnCount()) { + displayOrder[i] = table.convertColumnIndexToModel(i) + } + return displayOrder + } + + /** + * Returns the number of columns displayed in the table + * @return tThe number of columns displayed + */ + val columnCount: Int + get() = table.getColumnCount() + + /** + * Add listeners to the report table. + */ + private fun addTableListeners() { + val currentModel: MPivotTable = model + + table.columnToHeaderMap.forEach { (gridColumn, header) -> + addHeaderListeners(gridColumn, header) + } + + // Listeners for item click to fold and unfold the row + table.addItemClickListener { event -> + val row = event.item.rowIndex + val col = event.column.key.toInt() + if (event.button == 0) { + if (event.clickCount == 2) { + if (currentModel.isRowLine(row)) { + getModel()!!.performAsyncAction(object : Action("edit_line") { + override fun execute() { + try { + report.editLine() + } catch (ve: VException) { + // exception thrown by trigger. + throw ve + } + } + }) + } else { + if (row >= 0) { + if (currentModel.isRowFold(row, col)) { + currentModel.unfoldingRow(row, col) + } else { + currentModel.foldingRow(row, col) + } + } + } + } else if (event.isShiftKey && event.isCtrlKey) { + currentModel.sortColumn(col) + } else if (event.isCtrlKey) { + if (row >= 0) { + if (currentModel.isRowFold(row, col)) { + currentModel.unfoldingRow(row, col) + } else { + currentModel.foldingRow(row, col) + } + } + } else if (event.isShiftKey) { + if (currentModel.isColumnFold(col)) { + currentModel.unfoldingColumn(col) + } else { + currentModel.foldingColumn(col) + } + } + } else if (event.button == 2) { + if (row >= 0) { + if (currentModel.isRowFold(row, col)) { + currentModel.unfoldingRow(row, col) + } else { + currentModel.foldingRow(row, col) + } + } + } else if (event.button == 1) { + if (currentModel.isColumnFold(col)) { + currentModel.unfoldingColumn(col) + } else { + currentModel.foldingColumn(col) + } + } + } + + // Listener for column reorder + table.addColumnReorderListener { event -> + table.viewColumns = event.columns.map { it.key.toInt() }.toMutableList() + val newColumnOrder = IntArray(model.getColumnCount()) + val visibleColumns = table.viewColumns + var hiddenColumnsCount = 0 + for (i in newColumnOrder.indices) { + if (!model.getAccessibleColumn(i)!!.isVisible) { + hiddenColumnsCount += 1 + newColumnOrder[i] = model.getDisplayOrder(i) + } else { + newColumnOrder[i] = visibleColumns[i - hiddenColumnsCount] + } + } + model.columnMoved(newColumnOrder) + } + + /*table.addListener(object : ColumnCollapseListener() { TODO + fun columnCollapsed(event: ColumnCollapseEvent) { + for (i in 0 until model.getAccessibleColumnCount()) { + model.getAccessibleColumn(i)!!.isFolded = false + } + for (propertyId: Any in event.getPropertyIds()) { + val col: Int = propertyId as String?. toInt () - 1 + model.getAccessibleColumn(col)!!.isFolded = true + } + table.dataCommunicator.reset() // TODO + } + })*/ + + table.addSelectionListener { + report.setMenu() + } + + table.dataProvider.addDataProviderListener { + setInfoTable() + table.resetCachedInfos() + } + } + + // Issue: https://github.com/vaadin/flow-components/issues/1520 + val contextMenuList = mutableListOf() + + private fun addHeaderListeners(gridColumn: Grid.Column<*>, header: VerticalLayout) { + val currentModel: MPivotTable = model + val labelPopupMenu = ContextMenu() + + contextMenuList.add(labelPopupMenu) + + labelPopupMenu.target = header + + labelPopupMenu.addItem(VlibProperties.getString("set_column_info")) { + table.selectedColumn = getSelectedColumnIndex(gridColumn) + getModel()!!.performAsyncAction(object : Action("set_column_info") { + override fun execute() { + try { + report.setColumnInfo() + } catch (ve: VException) { + // exception thrown by trigger. + throw ve + } + } + }) + } + labelPopupMenu.addItem(VlibProperties.getString("sort_ASC")) { + currentModel.sortColumn(getSelectedColumnIndex(gridColumn), 1) + } + labelPopupMenu.addItem(VlibProperties.getString("sort_DSC")) { + currentModel.sortColumn(getSelectedColumnIndex(gridColumn), -1) + } + labelPopupMenu.addItem(VlibProperties.getString("add_column")) { + addColumn(getSelectedColumnIndex(gridColumn)) + } + if (currentModel.getAccessibleColumn(getSelectedColumnIndex(gridColumn))!!.isAddedAtRuntime) { + labelPopupMenu.addItem(VlibProperties.getString("remove_column")) { + removeColumn(getSelectedColumnIndex(gridColumn)) + } + labelPopupMenu.addItem(VlibProperties.getString("set_column_data")) { + table.selectedColumn = getSelectedColumnIndex(gridColumn) + getModel()!!.performAsyncAction(object : Action("set_column_data") { + override fun execute() { + try { + report.setColumnData() + } catch (ve: VException) { + // exception thrown by the trigger. + throw ve + } + } + }) + } + } + + header.addClickListener { event -> + if (event.button == 0) { // TODO do we need this check? + if (event.isCtrlKey) { + if (currentModel.isColumnFold(getSelectedColumnIndex(gridColumn))) { + currentModel.unfoldingColumn(getSelectedColumnIndex(gridColumn)) + } else { + currentModel.foldingColumn(getSelectedColumnIndex(gridColumn)) + } + } else if (event.isShiftKey) { + currentModel.sortColumn(getSelectedColumnIndex(gridColumn)) + } + } + } + } + + fun getSelectedColumnIndex(gridColumn: Grid.Column<*>): Int = gridColumn.key.toInt() + + /** + * Display table information in the footer of the table + */ + private fun setInfoTable() { + setStatisticsText( + table.model.model.getRowCount() + .toString() + "/" + + model.getBaseRowCount() + + "/" + + model.getVisibleRowCount() + ) + } + + /** + * Builds the grid rows. + */ + private fun buildRows(): List { + val rows = mutableListOf() + for (i in 0 until model.getRowCount()) { + rows.add(ReportModelItem(i)) + } + return rows + } + + //--------------------------------------------------- + // TABLE MODEL ITEM + //--------------------------------------------------- + /** + * The `TableModelItem` is the report table + * data model. + * + * @param rowIndex The row index. + */ + inner class ReportModelItem(val rowIndex: Int) { + //--------------------------------------- + // IMPLEMENTATIONS + //--------------------------------------- + fun getValueAt(columnIndex: Int): String { + return model.accessibleColumns[columnIndex]!!.format(model.getValueAt(rowIndex, columnIndex)) + } + + val reportRow: VReportRow? get() = model.getRow(rowIndex) + } +} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/DTable.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/DTable.kt new file mode 100644 index 000000000..ba05c3fda --- /dev/null +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/DTable.kt @@ -0,0 +1,255 @@ +/* + * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +package org.kopi.galite.visual.ui.vaadin.pivotTable + +import org.kopi.galite.visual.pivotTable.Constants +import org.kopi.galite.visual.pivotTable.UPivotTable.UTable +import org.kopi.galite.visual.pivotTable.VDecimalColumn +import org.kopi.galite.visual.pivotTable.VIntegerColumn +import org.kopi.galite.visual.pivotTable.VReportColumn +import org.kopi.galite.visual.pivotTable.VSeparatorColumn + +import com.vaadin.flow.component.AttachEvent +import com.vaadin.flow.component.Component +import com.vaadin.flow.component.DetachEvent +import com.vaadin.flow.component.dependency.CssImport +import com.vaadin.flow.component.grid.ColumnTextAlign +import com.vaadin.flow.component.grid.Grid +import com.vaadin.flow.component.grid.GridVariant +import com.vaadin.flow.component.html.Span +import com.vaadin.flow.component.orderedlayout.VerticalLayout +import com.vaadin.flow.component.page.Page +import com.vaadin.flow.function.ValueProvider +import com.vaadin.flow.shared.Registration + +import elemental.json.JsonObject +import elemental.json.JsonValue + +/** + * The `DTable` is a table implementing the [UTable] + * specifications. + * + * @param model The table model. + */ + +@CssImport.Container(value = [ + CssImport("./styles/galite/report.css"), + CssImport(value = "./styles/galite/report.css", themeFor = "vaadin-grid") +]) +class DTable(val model: VTable) : Grid(), UTable { + + //--------------------------------------------------- + // DATA MEMBERS + //--------------------------------------------------- + + /** + * The table selected row. + */ + val selectedRow: Int get() = asSingleSelect().value?.rowIndex ?: -1 + + /** + * The selected column. + */ + var selectedColumn = -1 + + /** + * The indexes of the columns in the grid view + */ + var viewColumns = mutableListOf() + + val columnToHeaderMap = mutableMapOf, VerticalLayout>() + + lateinit var cellStyler: ReportCellStyler + lateinit var browserWindowResizeListener: Registration + + init { + buildColumns() + addThemeVariants(GridVariant.LUMO_COMPACT, GridVariant.LUMO_COLUMN_BORDERS) + themeNames.add("report") + classNames.add("small") + classNames.add("borderless") + classNames.add("report") + setWidthFull() + } + + //--------------------------------------------------- + // IMPLEMENTATIONS + //--------------------------------------------------- + + override fun onAttach(attachEvent: AttachEvent) { + val page = attachEvent.ui.page + + page.setWindowHeight() + + browserWindowResizeListener = page.addBrowserWindowResizeListener { event -> + height = (event.height - 200).toString() + "px" + } + } + + private fun Page.setWindowHeight() { + val js = "return Vaadin.Flow.getBrowserDetailsParameters();" + executeJs(js).then { + height = ((it as JsonObject).get("v-wh").asNumber() - 200).toString() + "px" + } + } + + override fun onDetach(detachEvent: DetachEvent) { + browserWindowResizeListener.remove() + } + + /** + * Builds the grid columns. + */ + private fun buildColumns() { + model.accessibleColumns.forEachIndexed { index, column -> + val gridColumn = addColumn(index, column!!) + + gridColumn + .setHeader(getColumnNameComponent(column, gridColumn)) + + gridColumn.flexGrow = 0 + } + } + + /** + * Returns a component containing the column name of a given column. + * + * @param column The report column. + * @return The column name container. + */ + fun getColumnNameComponent(column: VReportColumn, gridColumn: Column): Component = + VerticalLayout(Span(column.label)) + .also { + it.element.setProperty("title", column.help) + columnToHeaderMap[gridColumn] = it + } + + /** + * Maps the index of the column in the grid at [viewColumnIndex] to the index of the column in the table model. + */ + override fun convertColumnIndexToModel(viewColumnIndex: Int): Int = viewColumns[viewColumnIndex] + + /** + * Maps the index of the column in the table model at [modelColumnIndex] to the index of the column in the grid. + */ + override fun convertColumnIndexToView(modelColumnIndex: Int): Int = viewColumns.indexOf(modelColumnIndex) + + /** + * Adds a new text column to this table with a column value provider and a key for the column. + * + * @param key the key of the column provider + * @param column the report column model + * @return the created column + */ + fun addColumn(key: Int, column: VReportColumn = model.accessibleColumns[key]!!): Column { + val provider = ColumnValueProvider(key, column) + + viewColumns.add(key) + + return addColumn(provider).also { + provider.column = it + it.setKey(key.toString()) + .setResizable(true) + .setClassNameGenerator(ColumnStyleGenerator(model.model, column)) + .setSortable(false) + } + } + + override fun removeColumnByKey(columnKey: String) { + viewColumns.remove(columnKey.toInt()) + super.removeColumnByKey(columnKey) + } + + override fun removeColumn(column: Column) { + viewColumns.remove(column.key.toInt()) + super.removeColumn(column) + } + + /** + * Returns the column count. + * @return the column count. + */ + fun getColumnCount(): Int = model.getColumnCount() + + /** + * Reset all columns widths. + */ + fun resetWidth() { + for (i in 0 until model.getColumnCount()) { + resetColumnSize(i) + } + } + + /** + * Resets the column size at a given position. + * @param pos The column position. + */ + private fun resetColumnSize(pos: Int) { + val column = model.model.getAccessibleColumn(convertColumnIndexToModel(pos)) + var width: Int + + if (column!!.isFolded && column !is VSeparatorColumn) { + width = 1 + } else if (column is VDecimalColumn || column is VIntegerColumn) { + width = column.label.length.coerceAtLeast(column.width) + // Integer and Fixed column can contain , data generated by operations like sum, multiplication + // --> compute column width occording to data. + width = width.coerceAtLeast(model.model.computeColumnWidth(convertColumnIndexToModel(pos))) + } else { + width = column.label.length.coerceAtLeast(column.width) + } + + if (width != 0) { + width = width * 9 + 2 + } + + columns[pos].width = "${width + 12}px" + } + + /** + * Resets the table cached information. + */ + fun resetCachedInfos() { + selectedColumn = -1 + select(null) + } + + /** + * Provides the value for the column with index [columnIndex] + * + * @param columnIndex the index of the column + */ + inner class ColumnValueProvider( + private val columnIndex: Int, + private val columnModel: VReportColumn + ) : ValueProvider { + var column: Column? = null + + override fun apply(source: DPivotTable.ReportModelItem): String { + column?.textAlign = if (columnModel.align == Constants.ALG_RIGHT) { + ColumnTextAlign.END + } else { + ColumnTextAlign.START + } + + cellStyler.updateStyles(source.rowIndex, columnIndex) + + return source.getValueAt(columnIndex) + } + } +} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/ReportCellStyler.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/ReportCellStyler.kt new file mode 100644 index 000000000..c8f3acc4c --- /dev/null +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/ReportCellStyler.kt @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +package org.kopi.galite.visual.ui.vaadin.pivotTable + +import java.awt.Color + +import org.kopi.galite.visual.pivotTable.ColumnStyle +import org.kopi.galite.visual.pivotTable.MPivotTable +import org.kopi.galite.visual.pivotTable.Parameters +import org.kopi.galite.visual.pivotTable.VSeparatorColumn + +/** + * The `ReportCellStyler` is the dynamic report styler + * + * @param model The report model. + * @param parameters The style parameters. + */ +class ReportCellStyler(private val model: MPivotTable, private val parameters: Parameters, val table: DTable) { + + //--------------------------------------------------- + // IMPLEMENTATIONS + //--------------------------------------------------- + /** + * Updates the cell styles. + * + * @param i The row index of the cell. + * @param j The column index of the cell. + */ + fun updateStyles(i: Int, j: Int) { + val column = model.getAccessibleColumn(j) + + if (column is VSeparatorColumn) { + return + } + val style = column!!.getStyles()[0] + + updateStyle(style, model.getRow(i)!!.level) + } + + /** + * Updates the CSS style of a given [ColumnStyle]. + * + * @param columnStyle The [ColumnStyle]. + * @param level The column level. + * + */ + private fun updateStyle(columnStyle: ColumnStyle, level: Int) { + val background = if (columnStyle.getBackground() != columnStyle.getBackground()) { + columnStyle.getBackground() + } else { + parameters.getBackground(level) + } + val foreground = if (columnStyle.getForeground() != columnStyle.getForeground()) { + columnStyle.getForeground() + } else { + parameters.getForeground(level) + } + val fontSize = if (columnStyle.getFont().size != columnStyle.getFont().size) { + columnStyle.getFont().size + } else { + parameters.font.size + } + val fontFamily = if (columnStyle.getFont().name != columnStyle.getFont().name) { + columnStyle.getFont().name + } else { + parameters.font.name + } + val isBold = if (columnStyle.getFont().isBold != columnStyle.getFont().isBold) { + columnStyle.getFont().isBold + } else { + parameters.font.isBold + } + val isItalic = if (columnStyle.getFont().isItalic != columnStyle.getFont().isItalic) { + columnStyle.getFont().isItalic + } else { + parameters.font.isItalic + } + + setStyle(level, background, foreground,fontSize, fontFamily, fontWeight(isBold), fontStyle(isItalic)) + } + + /** + * Returns the encapsulated CSS style. + */ + private fun setStyle( + level: Int, + background: Color, + foreground: Color, + fontSize: Int, + fontFamily: String, + fontWeight: String, + fontStyle: String, + ) { + table.style["--level-$level-background"] = getCSSColor(background) + table.style["--level-$level-color"] = getCSSColor(foreground) + table.style["--level-$level-font-size"] = fontSize.toString() + table.style["--level-$level-font-family"] = fontFamily + table.style["--level-$level-font-weight"] = fontWeight + table.style["--level-$level-font-style"] = fontStyle + } + + /** + * Returns the corresponding CSS color of a given [Color]. + * @param color The AWT color. + * @return The CSS color. + */ + private fun getCSSColor(color: Color): String { + return "rgb(" + color.red + "," + color.green + "," + color.blue + ")" + } + + /** + * Returns the bold style. + * @param isBold The bold style. + */ + private fun fontWeight(isBold: Boolean): String = if(isBold) "bold" else "normal" + + /** + * Returns the italic style. + * @param isItalic The italic style. + */ + private fun fontStyle(isItalic: Boolean) : String = if (isItalic) "italic" else "normal" +} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/VTable.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/VTable.kt new file mode 100644 index 000000000..d9f6209a4 --- /dev/null +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/VTable.kt @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +package org.kopi.galite.visual.ui.vaadin.pivotTable + +import org.kopi.galite.visual.pivotTable.VReportColumn +import org.kopi.galite.visual.ui.vaadin.pivotTable.DPivotTable.ReportModelItem + +import com.vaadin.flow.component.grid.Grid +import com.vaadin.flow.data.provider.ListDataProvider +import com.vaadin.flow.data.provider.Query +import com.vaadin.flow.function.SerializablePredicate +import org.kopi.galite.visual.pivotTable.MPivotTable + +/** + * The VTable is a vaadin [Grid] data provider adapted + * to dynamic reports needs. + * + * @param model The table model. + */ +class VTable( + internal val model: MPivotTable, + reportItems: List +): ListDataProvider(reportItems) { + + init { + addFilter { + it != null + } + } + + override fun size(query: Query>?): Int { + return model.getRowCount() + } + + /** + * Notify the report table that the report content has been + * change in order to update the table content. + */ + fun fireContentChanged() { + refreshAll() + } + + /** + * Returns the column align. + * @param column The column index. + * @return The column align. + */ + fun getColumnAlign(column: Int): Int = model.getAccessibleColumn(column)!!.align + + /** + * Returns the column count. + * @return the column count. + */ + fun getColumnCount(): Int = model.getColumnCount() + + /** + * Returns the accessible columns to display in the grid. + */ + val accessibleColumns: Array get() = model.accessibleColumns +} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/visual/VUIFactory.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/visual/VUIFactory.kt index bdab2ecb8..9357c8eba 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/visual/VUIFactory.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/visual/VUIFactory.kt @@ -33,6 +33,7 @@ import org.kopi.galite.visual.VHelpViewer import org.kopi.galite.visual.VItemTree import org.kopi.galite.visual.VMenuTree import org.kopi.galite.visual.VModel +import org.kopi.galite.visual.pivotTable.VPivotTable /** * The `VUIFactory` is a vaadin implementation of the [UIFactory]. @@ -68,6 +69,9 @@ class VUIFactory : UIFactory() { is VListDialog -> { createListDialog(model) } + is VPivotTable -> { + createPivotTable(model) + } else -> { throw IllegalArgumentException("NO UI IMPLEMENTATION FOR " + model.javaClass) } @@ -149,4 +153,13 @@ class VUIFactory : UIFactory() { internal fun createListDialog(model: VListDialog): DListDialog { return DListDialog(model) } + /** + * Creates the [DPivotTable] from a given model. + * @param model The pivot table model + * @return The [DPivotTable] view. + */ + + internal fun createPivotTable(model: VPivotTable): org.kopi.galite.visual.ui.vaadin.pivotTable.DPivotTable { + return org.kopi.galite.visual.ui.vaadin.pivotTable.DPivotTable(model) + } } diff --git a/galite-core/src/main/resources/org/kopi/galite/visual/dsl/form/Form-ar_TN.xml b/galite-core/src/main/resources/org/kopi/galite/visual/dsl/form/Form-ar_TN.xml index d668e1d42..1e7da6227 100644 --- a/galite-core/src/main/resources/org/kopi/galite/visual/dsl/form/Form-ar_TN.xml +++ b/galite-core/src/main/resources/org/kopi/galite/visual/dsl/form/Form-ar_TN.xml @@ -29,6 +29,7 @@ + diff --git a/galite-core/src/main/resources/org/kopi/galite/visual/dsl/form/Form-de_AT.xml b/galite-core/src/main/resources/org/kopi/galite/visual/dsl/form/Form-de_AT.xml index 327e22d0c..29540267b 100644 --- a/galite-core/src/main/resources/org/kopi/galite/visual/dsl/form/Form-de_AT.xml +++ b/galite-core/src/main/resources/org/kopi/galite/visual/dsl/form/Form-de_AT.xml @@ -29,6 +29,7 @@ + diff --git a/galite-core/src/main/resources/org/kopi/galite/visual/dsl/form/Form-en_GB.xml b/galite-core/src/main/resources/org/kopi/galite/visual/dsl/form/Form-en_GB.xml index f59f7503c..993a290c5 100644 --- a/galite-core/src/main/resources/org/kopi/galite/visual/dsl/form/Form-en_GB.xml +++ b/galite-core/src/main/resources/org/kopi/galite/visual/dsl/form/Form-en_GB.xml @@ -29,6 +29,7 @@ + diff --git a/galite-core/src/main/resources/org/kopi/galite/visual/dsl/form/Form-fr_FR.xml b/galite-core/src/main/resources/org/kopi/galite/visual/dsl/form/Form-fr_FR.xml index a1e85411e..c2b990f2f 100644 --- a/galite-core/src/main/resources/org/kopi/galite/visual/dsl/form/Form-fr_FR.xml +++ b/galite-core/src/main/resources/org/kopi/galite/visual/dsl/form/Form-fr_FR.xml @@ -29,6 +29,7 @@ + diff --git a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/bill/BillForm.kt b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/bill/BillForm.kt index f80cfa6dc..504259b34 100644 --- a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/bill/BillForm.kt +++ b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/bill/BillForm.kt @@ -16,6 +16,7 @@ */ package org.kopi.galite.demo.bill +import org.kopi.galite.demo.command.CommandR import java.util.Locale import org.kopi.galite.demo.database.Bill @@ -42,6 +43,11 @@ class BillForm : DictionaryForm(title = "Bills", locale = Locale.UK) { BillR() } } + command(item = pivotTable) { + createPivotTable { + BillP() + } + } } class BlockBill : Block("Bills", 1, 1) { diff --git a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/bill/BillP.kt b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/bill/BillP.kt new file mode 100644 index 000000000..3f41b880f --- /dev/null +++ b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/bill/BillP.kt @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +package org.kopi.galite.demo.bill + +import java.util.Locale + +import org.jetbrains.exposed.sql.selectAll +import org.jetbrains.exposed.sql.transactions.transaction +import org.kopi.galite.demo.database.Bill +import org.kopi.galite.visual.domain.DATE +import org.kopi.galite.visual.domain.DECIMAL +import org.kopi.galite.visual.domain.INT +import org.kopi.galite.visual.domain.STRING +import org.kopi.galite.visual.dsl.common.Icon +import org.kopi.galite.visual.dsl.form.Key +import org.kopi.galite.visual.dsl.pivotTable.PivotTable +import org.kopi.galite.visual.dsl.pivotTable.FieldAlignment + +/** + * Bill Report + */ +class BillP : PivotTable("Bills_Report", locale = Locale.UK) { + + val action = menu("Action") + val file = menu("File") + + val quit = actor(menu = file, label = "Quit", help = "Close Report.", ident = "quit") { + key = Key.ESCAPE + icon = Icon.QUIT + } + val csv = actor(menu = action, label = "CSV", help = "CSV Format", ident = "csv") { + key = Key.F8 // key is optional here + icon = Icon.EXPORT_CSV // icon is optional here + } + + val xls = actor(menu = action, label = "XLS", help = "Excel (XLS) Format", ident = "xls") { + key = Key.SHIFT_F8 // key is optional here + icon = Icon.EXPORT_XLSX // icon is optional here + } + + val xlsx = actor(menu = action, label = "XLSX", help = "Excel (XLSX) Format", ident = "xlsx") { + key = Key.SHIFT_F8 // key is optional here + icon = Icon.EXPORT // icon is optional here + } + + val pdf = actor(menu = action, label = "PDF", help = "PDF Format", ident = "pdf") { + key = Key.F9 // key is optional here + icon = Icon.EXPORT_PDF // icon is optional here + } + + val cmdQuit = command(item = quit) { + model.close() + } + + val numBill = field(INT(25)) { + label = "Number" + help = "The bill number" + align = FieldAlignment.LEFT + } + + val addressBill = field(STRING(25)) { + label = "Address" + help = "The bill address" + align = FieldAlignment.LEFT + } + val dateBill = field(DATE) { + label = "Date" + help = "The bill date" + align = FieldAlignment.LEFT + } + + val amountWithTaxes = field(DECIMAL(20, 10)) { + label = "Amount to pay" + help = "The amount including all taxes to pay" + align = FieldAlignment.LEFT + } + + val refCmd = field(INT(50)) { + label = "Command reference" + help = "The command reference" + align = FieldAlignment.LEFT + } + + val bills = Bill.selectAll() + + init { + transaction { + bills.forEach { result -> + add { + this[numBill] = result[Bill.numBill] + this[addressBill] = result[Bill.addressBill] + this[dateBill] = result[Bill.dateBill] + this[amountWithTaxes] = result[Bill.amountWithTaxes] + this[refCmd] = result[Bill.refCmd] + } + } + } + } +} diff --git a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/billproduct/BillProductForm.kt b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/billproduct/BillProductForm.kt index 64ec0d33e..220031430 100644 --- a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/billproduct/BillProductForm.kt +++ b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/billproduct/BillProductForm.kt @@ -16,6 +16,7 @@ */ package org.kopi.galite.demo.billproduct +import org.kopi.galite.demo.command.CommandR import java.util.Locale import org.kopi.galite.demo.database.Bill @@ -41,6 +42,11 @@ class BillProductForm : DictionaryForm("Bill products", Locale.UK) { BillProductR() } } + command(item = pivotTable) { + createPivotTable { + BillProductP() + } + } } class BlockBillProduct : Block("bill product", 1, 1) { diff --git a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/billproduct/BillProductP.kt b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/billproduct/BillProductP.kt new file mode 100644 index 000000000..fb798c23e --- /dev/null +++ b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/billproduct/BillProductP.kt @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +package org.kopi.galite.demo.billproduct + +import java.util.Locale + +import org.jetbrains.exposed.sql.selectAll +import org.jetbrains.exposed.sql.transactions.transaction +import org.kopi.galite.demo.common.ReportDefault +import org.kopi.galite.demo.database.BillProduct +import org.kopi.galite.visual.domain.DECIMAL +import org.kopi.galite.visual.domain.INT +import org.kopi.galite.visual.dsl.common.Icon +import org.kopi.galite.visual.dsl.form.Key +import org.kopi.galite.visual.dsl.pivotTable.PivotTable +import org.kopi.galite.visual.dsl.pivotTable.FieldAlignment + +/** + * Products Bill Report + */ +class BillProductP : PivotTable("Bill Product Report", Locale.UK) { + + val quantity = field(INT(25)) { + label = "Quantity" + help = "The quantity" + align = FieldAlignment.LEFT + } + + val amount = field(DECIMAL(25, 10)) { + label = "Amount before tax" + help = "The amount before tax to pay" + + } + val amountWithTaxes = field(DECIMAL(50, 10)) { + label = "Amount all taxes included" + help = "The amount all taxes included to pay" + align = FieldAlignment.LEFT + } + + val billProducts = BillProduct.selectAll() + + init { + transaction { + billProducts.forEach { result -> + add { + this[quantity] = result[BillProduct.quantity] + this[amount] = result[BillProduct.amount] + this[amountWithTaxes] = result[BillProduct.amountWithTaxes] + } + } + } + } +} diff --git a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/client/ClientForm.kt b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/client/ClientForm.kt index 9f87cda8d..1fcf2012d 100644 --- a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/client/ClientForm.kt +++ b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/client/ClientForm.kt @@ -21,6 +21,7 @@ import java.util.Locale import org.jetbrains.exposed.sql.SqlExpressionBuilder import org.jetbrains.exposed.sql.stringLiteral import org.jetbrains.exposed.sql.transactions.transaction +import org.kopi.galite.demo.command.CommandR import org.kopi.galite.demo.database.Client import org.kopi.galite.demo.database.Product diff --git a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/command/CommandForm.kt b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/command/CommandForm.kt index 9e62bf082..0e97e948d 100644 --- a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/command/CommandForm.kt +++ b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/command/CommandForm.kt @@ -50,6 +50,7 @@ class CommandForm : DictionaryForm(title = "Commands", locale = Locale.UK) { } } + command(item = list) { recursiveQuery() } diff --git a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/product/ProductForm.kt b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/product/ProductForm.kt index be5ec81e0..fbedc6617 100644 --- a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/product/ProductForm.kt +++ b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/product/ProductForm.kt @@ -16,6 +16,7 @@ */ package org.kopi.galite.demo.product +import org.kopi.galite.demo.command.CommandR import java.util.Locale import org.kopi.galite.demo.database.Product diff --git a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/provider/ProviderForm.kt b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/provider/ProviderForm.kt index 15a45af12..9653c107d 100644 --- a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/provider/ProviderForm.kt +++ b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/provider/ProviderForm.kt @@ -16,6 +16,7 @@ */ package org.kopi.galite.demo.provider +import org.kopi.galite.demo.command.CommandR import java.util.Locale import org.kopi.galite.demo.database.Provider @@ -40,6 +41,11 @@ class ProviderForm : DictionaryForm(title = "Providers", locale = Locale.UK) { ProviderR() } } + command(item = pivotTable) { + createPivotTable { + ProviderP() + } + } } class BlockProvider : Block("Providers", 1, 1) { diff --git a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/provider/ProviderP.kt b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/provider/ProviderP.kt new file mode 100644 index 000000000..e8c1cd318 --- /dev/null +++ b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/provider/ProviderP.kt @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +package org.kopi.galite.demo.provider + +import java.util.Locale + +import org.jetbrains.exposed.sql.selectAll +import org.jetbrains.exposed.sql.transactions.transaction +import org.kopi.galite.demo.database.Provider +import org.kopi.galite.visual.domain.INT +import org.kopi.galite.visual.domain.STRING +import org.kopi.galite.visual.dsl.common.Icon +import org.kopi.galite.visual.dsl.form.Key +import org.kopi.galite.visual.dsl.pivotTable.PivotTable +import org.kopi.galite.visual.dsl.pivotTable.FieldAlignment + +/** + * Provider Report + */ +class ProviderP : PivotTable(title = "Providers_Report", locale = Locale.UK) { + + val action = menu("Action") + + val csv = actor(menu = action, label = "CSV", help = "CSV Format", ident = "csv") { + key = Key.F8 + icon = Icon.EXPORT_CSV + } + + val xls = actor(menu = action, label = "XLS", help = "Excel (XLS) Format", ident = "xls") { + key = Key.SHIFT_F8 + icon = Icon.EXPORT_XLSX + } + + val xlsx = actor(menu = action, label = "XLSX", help = "Excel (XLSX) Format", ident = "xlsx") { + key = Key.SHIFT_F8 + icon = Icon.EXPORT + } + + val pdf = actor(menu = action, label = "PDF", help = "PDF Format", ident = "pdf") { + key = Key.F9 + icon = Icon.EXPORT_PDF + } + + + val nameProvider = field(STRING(50)) { + label = "Name" + help = "The provider name" + align = FieldAlignment.LEFT + format { value -> + value.toUpperCase() + } + } + + val tel = field(INT(25)) { + label = "Phone number" + help = "The provider phone number" + align = FieldAlignment.LEFT + } + + val description = field(STRING(255)) { + label = "Description" + help = "The provider description" + align = FieldAlignment.LEFT + format { value -> + value.toUpperCase() + } + } + + val address = field(STRING(70)) { + label = "Address" + help = "The provider address" + align = FieldAlignment.LEFT + } + + val zipCode = field(INT(50)) { + label = "Zip code" + help = "The provider zip code" + align = FieldAlignment.LEFT + } + + val providers = Provider.selectAll() + + init { + transaction { + providers.forEach { result -> + add { + this[nameProvider] = result[Provider.nameProvider] + this[description] = result[Provider.description] + this[tel] = result[Provider.tel] + this[zipCode] = result[Provider.zipCode] + this[address] = result[Provider.address] + } + } + } + } +} diff --git a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/stock/StockForm.kt b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/stock/StockForm.kt index 712d57937..0a3e6a9b6 100644 --- a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/stock/StockForm.kt +++ b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/stock/StockForm.kt @@ -16,6 +16,7 @@ */ package org.kopi.galite.demo.stock +import org.kopi.galite.demo.command.CommandR import java.util.Locale import org.kopi.galite.demo.database.Product @@ -41,6 +42,11 @@ class StockForm : DictionaryForm(title = "Stocks", locale = Locale.UK) { StockR() } } + command(item = pivotTable) { + createPivotTable { + StockP() + } + } } class StockBlock : Block("Stock", 1, 1) { diff --git a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/stock/StockP.kt b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/stock/StockP.kt new file mode 100644 index 000000000..b30304f09 --- /dev/null +++ b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/stock/StockP.kt @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +package org.kopi.galite.demo.stock + +import java.util.Locale + +import org.jetbrains.exposed.sql.JoinType +import org.jetbrains.exposed.sql.selectAll +import org.jetbrains.exposed.sql.transactions.transaction +import org.kopi.galite.demo.database.Product +import org.kopi.galite.demo.database.Provider +import org.kopi.galite.demo.database.Stock +import org.kopi.galite.visual.domain.INT +import org.kopi.galite.visual.domain.STRING +import org.kopi.galite.visual.dsl.common.Icon +import org.kopi.galite.visual.dsl.form.Key +import org.kopi.galite.visual.dsl.pivotTable.PivotTable +import org.kopi.galite.visual.dsl.pivotTable.FieldAlignment + +/** + * Stock Report + */ +class StockP : PivotTable(title = "Stocks", locale = Locale.UK) { + + val action = menu("Action") + + val csv = actor(menu = action, label = "CSV", help = "CSV Format", ident = "csv") { + key = Key.F8 + icon = Icon.EXPORT_CSV + } + + val xls = actor(menu = action, label = "XLS", help = "Excel (XLS) Format", ident = "xls") { + key = Key.SHIFT_F8 + icon = Icon.EXPORT_XLSX + } + + val xlsx = actor(menu = action, label = "XLSX", help = "Excel (XLSX) Format", ident = "xlsx") { + key = Key.SHIFT_F8 + icon = Icon.EXPORT + } + + val pdf = actor(menu = action, label = "PDF", help = "PDF Format", ident = "pdf") { + key = Key.F9 + icon = Icon.EXPORT_PDF + } + + val description = field(STRING(25)) { + label = "Description" + help = "The product description" + align = FieldAlignment.LEFT + } + val nameProvider = field(STRING(25)) { + label = "Provider name" + help = "The provider name" + align = FieldAlignment.LEFT + } + val minAlert = field(INT(25)) { + label = "Min Alert" + help = "The stock's min alert" + align = FieldAlignment.LEFT + } + + val stocks = Stock.join(Provider, JoinType.INNER, Stock.idStckProv, Provider.idProvider) + .join(Product, JoinType.INNER, Stock.idStckProv, Product.idPdt) + .slice(Stock.minAlert, Product.description, Provider.nameProvider) + .selectAll() + + init { + transaction { + stocks.forEach { result -> + add { + this[minAlert] = result[Stock.minAlert] + this[description] = result[Product.description] + this[nameProvider] = result[Provider.nameProvider] + } + } + } + } +} diff --git a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/taxRule/TaxRuleForm.kt b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/taxRule/TaxRuleForm.kt index c3538d295..831e9263c 100644 --- a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/taxRule/TaxRuleForm.kt +++ b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/taxRule/TaxRuleForm.kt @@ -16,6 +16,7 @@ */ package org.kopi.galite.demo.taxRule +import org.kopi.galite.demo.command.CommandR import java.util.Locale import org.kopi.galite.demo.database.TaxRule @@ -93,6 +94,11 @@ class TaxRuleForm : DictionaryForm(title = "TaxRules", locale = Locale.UK) { TaxRuleR() } } + command(item = pivotTable) { + createPivotTable { + TaxRuleP() + } + } command(item = save) { saveBlock() diff --git a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/taxRule/TaxRuleP.kt b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/taxRule/TaxRuleP.kt new file mode 100644 index 000000000..bcbf14668 --- /dev/null +++ b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/taxRule/TaxRuleP.kt @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +package org.kopi.galite.demo.taxRule + +import java.util.Locale + +import org.jetbrains.exposed.sql.selectAll +import org.jetbrains.exposed.sql.transactions.transaction +import org.kopi.galite.demo.database.TaxRule +import org.kopi.galite.visual.domain.INT +import org.kopi.galite.visual.domain.STRING +import org.kopi.galite.visual.dsl.common.Icon +import org.kopi.galite.visual.dsl.form.Key +import org.kopi.galite.visual.dsl.pivotTable.PivotTable +import org.kopi.galite.visual.dsl.pivotTable.FieldAlignment + +/** + * Tax Rules Report + */ +class TaxRuleP : PivotTable(title = "TaxRules_Report", locale = Locale.UK) { + + val action = menu("Action") + + val csv = actor(menu = action, label = "CSV", help = "CSV Format", ident = "csv") { + key = Key.F8 + icon = Icon.EXPORT_CSV + } + + val xls = actor(menu = action, label = "XLS", help = "Excel (XLS) Format", ident = "xls") { + key = Key.SHIFT_F8 + icon = Icon.EXPORT_XLSX + } + + val xlsx = actor(menu = action, label = "XLSX", help = "Excel (XLSX) Format", ident = "xlsx") { + key = Key.SHIFT_F8 + icon = Icon.EXPORT + } + + val pdf = actor(menu = action, label = "PDF", help = "PDF Format", ident = "pdf") { + key = Key.F9 + icon = Icon.EXPORT_PDF + } + + val taxName = field(STRING(50)) { + label = "Name" + help = "The tax name" + align = FieldAlignment.LEFT + } + + val rate = field(INT(25)) { + label = "Rate in %" + help = "The tax rate in %" + align = FieldAlignment.LEFT + } + + val taxRules = TaxRule.selectAll() + + init { + transaction { + taxRules.forEach { result -> + add { + this[taxName] = result[TaxRule.taxName] + this[rate] = result[TaxRule.rate] + } + } + } + } +} From 785779af457aec697ff92427440c1d82ef661aba Mon Sep 17 00:00:00 2001 From: Super User Date: Wed, 18 Oct 2023 18:10:24 +0100 Subject: [PATCH 04/20] Clean Cosmetic --- .../org/kopi/galite/visual/domain/Domain.kt | 29 +- .../visual/dsl/pivotTable/FieldAlignment.kt | 26 - .../visual/dsl/pivotTable/PivotTable.kt | 210 +--- .../visual/dsl/pivotTable/ReportField.kt | 131 +-- .../pivotTable/ReportLocalizationWriter.kt | 1 - .../pivotTable/CellStyleCacheManager.kt | 109 -- .../galite/visual/pivotTable/ColumnStyle.kt | 93 -- .../galite/visual/pivotTable/Constants.kt | 82 -- .../galite/visual/pivotTable/MPivotTable.kt | 938 +----------------- .../kopi/galite/visual/pivotTable/PConfig.kt | 63 -- .../galite/visual/pivotTable/Parameters.kt | 60 -- .../kopi/galite/visual/pivotTable/Point.kt | 39 - .../visual/pivotTable/ReportListener.kt | 37 - .../galite/visual/pivotTable/UPivotTable.kt | 78 +- .../visual/pivotTable/VBooleanCodeColumn.kt | 70 -- .../visual/pivotTable/VBooleanColumn.kt | 72 -- .../pivotTable/VCCDepthFirstCircuitN.kt | 60 -- .../visual/pivotTable/VCalculateColumn.kt | 36 - .../galite/visual/pivotTable/VCellFormat.kt | 44 - .../galite/visual/pivotTable/VCodeColumn.kt | 104 -- .../galite/visual/pivotTable/VDateColumn.kt | 81 -- .../visual/pivotTable/VDecimalCodeColumn.kt | 75 -- .../visual/pivotTable/VDecimalColumn.kt | 108 -- .../galite/visual/pivotTable/VGroupRow.kt | 54 - .../visual/pivotTable/VHelpGenerator.kt | 22 - .../visual/pivotTable/VIntegerCodeColumn.kt | 103 -- .../visual/pivotTable/VIntegerColumn.kt | 73 -- .../galite/visual/pivotTable/VMonthColumn.kt | 62 -- .../galite/visual/pivotTable/VPivotTable.kt | 340 +------ .../galite/visual/pivotTable/VReportColumn.kt | 85 +- .../visual/pivotTable/VReportCommand.kt | 112 --- .../galite/visual/pivotTable/VReportRow.kt | 21 - .../visual/pivotTable/VSeparatorColumn.kt | 56 -- .../visual/pivotTable/VStringCodeColumn.kt | 83 -- .../galite/visual/pivotTable/VStringColumn.kt | 57 -- .../galite/visual/pivotTable/VTimeColumn.kt | 81 -- .../visual/pivotTable/VTimestampColumn.kt | 81 -- .../galite/visual/pivotTable/VWeekColumn.kt | 61 -- .../visual/pivotTable/triggers/Triggers.kt | 286 ------ .../vaadin/pivotTable/ColumnStyleGenerator.kt | 50 - .../ui/vaadin/pivotTable/ColumnsSelector.kt | 61 -- .../ui/vaadin/pivotTable/DPivotTable.kt | 386 +------ .../visual/ui/vaadin/pivotTable/DTable.kt | 255 ----- .../ui/vaadin/pivotTable/ReportCellStyler.kt | 137 --- .../visual/ui/vaadin/pivotTable/VTable.kt | 75 -- .../org/kopi/galite/demo/bill/BillForm.kt | 4 +- .../kotlin/org/kopi/galite/demo/bill/BillP.kt | 26 - .../galite/demo/billproduct/BillProductP.kt | 6 - .../kopi/galite/demo/provider/ProviderP.kt | 12 - .../org/kopi/galite/demo/stock/StockP.kt | 4 - .../org/kopi/galite/demo/taxRule/TaxRuleP.kt | 23 - 51 files changed, 31 insertions(+), 5131 deletions(-) delete mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/FieldAlignment.kt delete mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/CellStyleCacheManager.kt delete mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/ColumnStyle.kt delete mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/PConfig.kt delete mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/Parameters.kt delete mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/Point.kt delete mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/ReportListener.kt delete mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VBooleanCodeColumn.kt delete mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VBooleanColumn.kt delete mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VCCDepthFirstCircuitN.kt delete mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VCalculateColumn.kt delete mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VCellFormat.kt delete mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VCodeColumn.kt delete mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VDateColumn.kt delete mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VDecimalCodeColumn.kt delete mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VDecimalColumn.kt delete mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VIntegerCodeColumn.kt delete mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VIntegerColumn.kt delete mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VMonthColumn.kt delete mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VReportCommand.kt delete mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VSeparatorColumn.kt delete mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VStringCodeColumn.kt delete mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VStringColumn.kt delete mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VTimeColumn.kt delete mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VTimestampColumn.kt delete mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VWeekColumn.kt delete mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/triggers/Triggers.kt delete mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/ColumnStyleGenerator.kt delete mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/ColumnsSelector.kt delete mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/DTable.kt delete mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/ReportCellStyler.kt delete mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/VTable.kt diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/domain/Domain.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/domain/Domain.kt index 044ed1488..43d3579e6 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/domain/Domain.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/domain/Domain.kt @@ -277,33 +277,12 @@ open class Domain(val width: Int? = null, /** * Builds the pivot table column model */ - open fun buildReportFieldModel(field: org.kopi.galite.visual.dsl.pivotTable.ReportField<*>, function: org.kopi.galite.visual.pivotTable.VCalculateColumn?, format: org.kopi.galite.visual.pivotTable.VCellFormat?): org.kopi.galite.visual.pivotTable.VReportColumn { + open fun buildReportFieldModel(field: org.kopi.galite.visual.dsl.pivotTable.ReportField<*>): org.kopi.galite.visual.pivotTable.VReportColumn { return with(field) { when (kClass) { - Int::class, Long::class -> - org.kopi.galite.visual.pivotTable.VIntegerColumn(ident, options, align.value, groupID, function, width ?: 0, format) - String::class -> - org.kopi.galite.visual.pivotTable.VStringColumn( - ident, options, align.value, groupID, function, width ?: 0, - height ?: 0, format - ) - BigDecimal::class -> - org.kopi.galite.visual.pivotTable.VDecimalColumn( - ident, options, align.value, groupID, function, width ?: 0, - height ?: 0, format - ) - Boolean::class -> - org.kopi.galite.visual.pivotTable.VBooleanColumn(ident, options, align.value, groupID, function, format) - org.joda.time.LocalDate::class, LocalDate::class, java.sql.Date::class, java.util.Date::class -> - org.kopi.galite.visual.pivotTable.VDateColumn(ident, options, align.value, groupID, function, width ?: 0, format) - Month::class -> - org.kopi.galite.visual.pivotTable.VMonthColumn(ident, options, align.value, groupID, function, format) - Week::class -> - org.kopi.galite.visual.pivotTable.VWeekColumn(ident, options, align.value, groupID, function, format) - org.joda.time.LocalTime::class, LocalTime::class -> - org.kopi.galite.visual.pivotTable.VTimeColumn(ident, options, align.value, groupID, function, format) - Instant::class, LocalDateTime::class, DateTime::class -> - org.kopi.galite.visual.pivotTable.VTimestampColumn(ident, options, align.value, groupID, function, format) + Int::class, Long::class, String::class, BigDecimal::class, Boolean::class, org.joda.time.LocalDate::class, LocalDate::class, java.sql.Date::class, java.util.Date::class, Month::class, Week::class, org.joda.time.LocalTime::class, LocalTime::class, Instant::class, LocalDateTime::class, DateTime::class -> + org.kopi.galite.visual.pivotTable.VReportColumn(ident) + else -> throw java.lang.RuntimeException("Type ${kClass!!.qualifiedName} is not supported") } } diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/FieldAlignment.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/FieldAlignment.kt deleted file mode 100644 index 372972cb6..000000000 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/FieldAlignment.kt +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.kopi.galite.visual.dsl.pivotTable - -import org.kopi.galite.visual.report.Constants - -enum class FieldAlignment(val value: Int) { - DEFAULT(Constants.ALG_DEFAULT), - CENTER(Constants.ALG_CENTER), - LEFT(Constants.ALG_LEFT), - RIGHT(Constants.ALG_RIGHT), -} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTable.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTable.kt index fa4d62972..3243086a8 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTable.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTable.kt @@ -19,29 +19,13 @@ package org.kopi.galite.visual.dsl.pivotTable import java.io.IOException import java.util.Locale -import org.jetbrains.exposed.sql.ExpressionWithColumnType -import org.jetbrains.exposed.sql.Op import org.kopi.galite.visual.domain.Domain -import org.kopi.galite.visual.dsl.common.Action import org.kopi.galite.visual.dsl.common.LocalizationWriter -import org.kopi.galite.visual.dsl.common.ReportTrigger -import org.kopi.galite.visual.dsl.common.Trigger import org.kopi.galite.visual.dsl.common.Window -import org.kopi.galite.visual.form.VConstants -import org.kopi.galite.visual.form.VField -import org.kopi.galite.visual.pivotTable.Constants import org.kopi.galite.visual.pivotTable.VPivotTable -import org.kopi.galite.visual.pivotTable.VSeparatorColumn import org.kopi.galite.visual.ApplicationContext -/** - * Represents a report that contains fields [fields] and displays a table of [reportRows]. - - * @param title The title of this form. - * @param help The help text. - * @param locale the window locale. - */ abstract class PivotTable(title: String, val help: String?, locale: Locale? = null) : Window(title, locale) { constructor(title: String, locale: Locale? = null) : this(title, null, locale) @@ -67,27 +51,13 @@ abstract class PivotTable(title: String, val help: String?, locale: Locale? = nu field.initialize() - val pos = if(model.model.columns.size == 0) 0 else model.model.columns.size - 1 // TODO!! + val pos = if(model.model.columns.size == 0) 0 else model.model.columns.size - 1 model.model.columns.add(pos, field.buildReportColumn()) fields.add(field) - field.addFieldTriggers() return field } - fun ReportField<*>.addFieldTriggers() { - // FIELD TRIGGERS - val fieldTriggerArray = arrayOfNulls(Constants.TRG_TYPES.size) - if (computeTrigger != null) { - fieldTriggerArray[Constants.TRG_COMPUTE] = computeTrigger!! - } - if (formatTrigger != null) { - fieldTriggerArray[Constants.TRG_FORMAT] = formatTrigger!! - } - // TODO : Add field triggers here - this@PivotTable.model.VKT_Fields_Triggers.add(fieldTriggerArray) - } - /** * creates and returns a field that accept nulls. It uses [init] method to initialize the field. * @@ -118,24 +88,6 @@ abstract class PivotTable(title: String, val help: String?, locale: Locale? = nu } } - /** - * creates and returns fields that accept nulls. It uses [init] method to initialize the fields. - * - * @param fieldsNumber the number of fields to create. - * @param domain the domain of the field. - * @param init initialization method. - * @return a field. - */ - inline fun ?> nullableField(fieldsNumber: Int, - domain: Domain, - noinline init: ReportField.() -> Unit): List> { - return (0 until fieldsNumber).map { - field(domain, init).also { field -> - field.model.label = "${field.label}_${it + 1}" - } - } - } - /** * Adds a row to the report. * @@ -158,38 +110,6 @@ abstract class PivotTable(title: String, val help: String?, locale: Locale? = nu } } - /** - * Adds report trigger to this block. - * - * @param reportTriggerEvents the trigger events to add - * @param method the method to execute when trigger is called - */ - fun trigger(vararg reportTriggerEvents: ReportTriggerEvent, method: () -> T): Trigger { - val event = reportEventList(reportTriggerEvents) - val reportAction = Action(null, method) - val trigger = ReportTrigger(event, reportAction) - - triggers.add(trigger) - // REPORT TRIGGERS - for (i in VConstants.TRG_TYPES.indices) { - if (trigger.events shr i and 1 > 0) { - model.VKT_Report_Triggers[0][i] = trigger - } - } - - return trigger - } - - private fun reportEventList(reportTriggerEvents: Array>): Long { - var self = 0L - - reportTriggerEvents.forEach { trigger -> - self = self or (1L shl trigger.event) - } - - return self - } - /** * Returns the row's data. * @@ -197,59 +117,11 @@ abstract class PivotTable(title: String, val help: String?, locale: Locale? = nu */ fun getRow(rowNumber: Int): MutableMap, Any?> = reportRows[rowNumber].data - /** - * Returns rows of data for a specific [field]. - * - * @param field the field. - */ - fun getRowsForField(field: ReportField<*>) = reportRows.map { it.data[field] } - /** * Adds default report commands */ open val reportCommands = false - /////////////////////////////////////////////////////////////////////////// - // REPORT TRIGGERS - /////////////////////////////////////////////////////////////////////////// - /** - * Block Triggers - * - * @param event the event of the trigger - */ - open class ReportTriggerEvent(val event: Int) - - /** - * Executed before the report is displayed. - */ - val PREREPORT = ReportTriggerEvent(Constants.TRG_PREREPORT) - - /** - * Executed after the report is closed. - */ - val POSTREPORT = ReportTriggerEvent(Constants.TRG_POSTREPORT) - - // ---------------------------------------------------------------------- - // METHODS FOR SQL - // ---------------------------------------------------------------------- - /** - * creates an SQL condition, so that the column have to fit the - * requirements (value and search operator) of the field. - */ - protected fun buildSQLCondition(column: ExpressionWithColumnType, field: VField): Op { - return field.getSearchCondition(column) ?: Op.TRUE - } - - /** - * Returns true if there is trigger associated with given event. - */ - protected fun hasTrigger(event: Int): Boolean = model.hasTrigger(event) - - /** - * Returns true if there is trigger associated with given event. - */ - protected fun hasCommandTrigger(event: Int, index: Int): Boolean = model.hasCommandTrigger(event, index) - fun setMenu() { model.setMenu() } @@ -258,8 +130,6 @@ abstract class PivotTable(title: String, val help: String?, locale: Locale? = nu // HELP // ---------------------------------------------------------------------- - fun genHelp(): String? = model.genHelp() - fun showHelp() { model.showHelp() } @@ -268,70 +138,7 @@ abstract class PivotTable(title: String, val help: String?, locale: Locale? = nu model.addDefaultReportCommands() } - - /** - * Sets the title - */ - fun setPageTitle(title: String) { - model.setPageTitle(title) - } - - fun setPageTitleParams(param: Any) { - model.setPageTitleParams(param) - } - - fun setPageTitleParams(param1: Any, param2: Any) { - model.setPageTitleParams(param1, param2) - } - - fun setPageTitleParams(params: Array) { - model.setPageTitleParams(params) - } - - fun setFirstPageHeader(firstPageHeader: String) { - model.setFirstPageHeader(firstPageHeader) - } - - fun foldSelection() { - model.foldSelection() - } - - fun unfoldSelection() { - model.unfoldSelection() - } - - fun foldSelectedColumn() { - model.foldSelectedColumn() - } - - fun unfoldSelectedColumn() { - model.unfoldSelectedColumn() - } - - /** - * Sort the displayed tree wrt to a column - */ - fun sortSelectedColumn() { - model.sortSelectedColumn() - } - - /** - * Sort the displayed tree wrt to a column - */ - fun editLine() { - model.editLine() - } - - fun setColumnData() { - model.setColumnData() - } - - fun setColumnInfo() { - model.setColumnInfo() - } - override fun addCommandTrigger() { - model.VKT_Commands_Triggers.add(arrayOfNulls(Constants.TRG_TYPES.size)) } // ---------------------------------------------------------------------- @@ -364,23 +171,10 @@ abstract class PivotTable(title: String, val help: String?, locale: Locale? = nu // REPORT MODEL // ---------------------------------------------------------------------- override val model: VPivotTable = object : VPivotTable() { - init { - // TODO: for separator column - if(VKT_Fields_Triggers.size == 0) { - VKT_Fields_Triggers.add(arrayOfNulls(Constants.TRG_TYPES.size)) - } else { - VKT_Fields_Triggers.add(VKT_Fields_Triggers.size - 1, arrayOfNulls(Constants.TRG_TYPES.size)) - } - } override fun init() { fields.forEach { it.initField() - - if (it.group != null) { - it.groupID = fields.indexOf(it.group) - it.model.groups = it.groupID - } } } @@ -396,8 +190,6 @@ abstract class PivotTable(title: String, val help: String?, locale: Locale? = nu if (reportCommands) { addDefaultReportCommands() } - - model.model.columns.add(VSeparatorColumn()) // TODO!!! } @PublishedApi diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/ReportField.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/ReportField.kt index 9bdb08982..9dc4acd81 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/ReportField.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/ReportField.kt @@ -17,27 +17,12 @@ */ package org.kopi.galite.visual.dsl.pivotTable -import java.math.BigDecimal - import org.kopi.galite.visual.domain.Domain -import org.kopi.galite.visual.dsl.common.Action import org.kopi.galite.visual.dsl.common.LocalizationWriter -import org.kopi.galite.visual.dsl.common.ReportTrigger -import org.kopi.galite.visual.dsl.common.Trigger import org.kopi.galite.visual.dsl.field.Field -import org.kopi.galite.visual.pivotTable.Constants -import org.kopi.galite.visual.pivotTable.VCalculateColumn -import org.kopi.galite.visual.pivotTable.VCellFormat -import org.kopi.galite.visual.pivotTable.VDecimalColumn import org.kopi.galite.visual.pivotTable.VReportColumn import org.kopi.galite.visual.VCommand -/** - * This class represents the definition of a report field. - * - * @param domain The domain of this field. - * @param ident The identifier of this field, used to identify the field the localization file. - */ class ReportField(override val domain: Domain, val init: ReportField.() -> Unit, ident: String? = null, @@ -45,110 +30,21 @@ class ReportField(override val domain: Domain, /** the options of the field */ internal var options: Int = 0 - /** - * The fields you want to be grouped by the actual field. This creates clickable groups in your report. - * - * Example : - * - * val invoice = field() - * - * val customer = field() { - * group = invoice - * } - * - * In this report, you can click on the customer field to group invoices. - * - */ - var group: ReportField<*>? = null - - /** the alignment of the text */ - var align: FieldAlignment = FieldAlignment.DEFAULT - /** the commands accessible in this field */ lateinit var commands: Array - /** the triggers executed by this field */ - internal val triggers = mutableListOf() - - /** compute trigger */ - internal var computeTrigger: Trigger? = null - - /** format trigger */ - internal var formatTrigger: Trigger? = null - - internal var groupID = -1 - - /** - * true if the field is hidden, false otherwise - */ - private val isHidden: Boolean get() = options and Constants.CLO_HIDDEN > 0 - - /** - * true if the field is hidden, false otherwise - */ - override var hidden: Boolean? = false - set(value) { - options = if (value == true) Constants.CLO_HIDDEN else Constants.CLO_VISIBLE - field = value - } - fun initialize() { initField() - if(domain.kClass == BigDecimal::class) { - align = FieldAlignment.RIGHT - } } fun initField() { init() } - /** - * executed when the report is displayed and can be used to compute expressions on the report columns and show - * the result. - * - * @param method The method to execute when compute trigger is executed. - */ - fun compute(method: () -> VCalculateColumn): ReportTrigger { - val fieldAction = Action(null, method) - return ReportTrigger(0L or (1L shl Constants.TRG_COMPUTE), fieldAction).also { - computeTrigger = it - } - } - - /** - * Changes the values of this field in a specific format. - * - * @param method The method to execute when compute trigger is executed. - */ - fun format(method: (value: T) -> String?): ReportTrigger { - val formatMethod = { - object : VCellFormat() { - override fun format(value: Any?): String = method(value as T).orEmpty() - } - } - val fieldAction = Action(null, formatMethod) - return ReportTrigger(0L or (1L shl Constants.TRG_FORMAT), fieldAction).also { - formatTrigger = it - } - } - lateinit var model: VReportColumn fun buildReportColumn(): VReportColumn { - val function: VCalculateColumn? = if (computeTrigger != null) { - computeTrigger!!.action.method() as VCalculateColumn - } else { - null - } - - val format: VCellFormat? = if (formatTrigger != null) { - formatTrigger!!.action.method() as VCellFormat - } else { - null - } - - model = domain.buildReportFieldModel(this, function, format).also { column -> + model = domain.buildReportFieldModel(this).also { column -> column.label = label ?: "" column.help = help } @@ -163,29 +59,6 @@ class ReportField(override val domain: Domain, * Generates localization for the field in the xml file */ override fun genLocalization(writer: LocalizationWriter) { - if (!isHidden) { - (writer as ReportLocalizationWriter).genField(ident, label, help) - } + (writer as ReportLocalizationWriter).genField(ident, label, help) } } - -// ---------------------------------------------------------------------- -// DECIMAL FIELD FUNCTIONS -// ---------------------------------------------------------------------- - -/** - * Sets display scale to maxScale - * all values will be set to the same scale - */ -fun ReportField.setDisplayScale(scale: Int) { - (model as VDecimalColumn).setDisplayScale(scale) -} - -/** - * Sets maxScale - * all values with scale superior to maxScale will have - * maxScale as scale, and the other values will keep their scale. - */ -fun ReportField.setMaxScale(scale: Int) { - (model as VDecimalColumn).setMaxScale(scale) -} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/ReportLocalizationWriter.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/ReportLocalizationWriter.kt index 9b3a65199..ad1b178c7 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/ReportLocalizationWriter.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/ReportLocalizationWriter.kt @@ -38,7 +38,6 @@ class ReportLocalizationWriter : LocalizationWriter() { self.setAttribute("help", help) } pushNode(self) - // coll.genLocalization(this) TODO // Menus menus.forEach { menu -> diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/CellStyleCacheManager.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/CellStyleCacheManager.kt deleted file mode 100644 index 4f14a2e34..000000000 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/CellStyleCacheManager.kt +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN - * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -package org.kopi.galite.visual.pivotTable - -import java.awt.Color -import java.io.Serializable - -import org.apache.poi.hssf.util.HSSFColor -import org.apache.poi.ss.usermodel.BorderStyle -import org.apache.poi.ss.usermodel.CellStyle -import org.apache.poi.ss.usermodel.FillPatternType -import org.apache.poi.ss.usermodel.HorizontalAlignment -import org.apache.poi.ss.usermodel.IndexedColors -import org.apache.poi.ss.usermodel.VerticalAlignment -import org.apache.poi.ss.usermodel.Workbook -import org.apache.poi.xssf.usermodel.XSSFCellStyle -import org.apache.poi.xssf.usermodel.XSSFColor - -/** - * Manage the CellStyle cache. - * In order to not have the 4000 style limit, cell styles are cached base on their - * hash codes within a [Set] and reused when it two or more cells have the same - * style. - * Use [.setCellStyle] for caching functions. - */ -class CellStyleCacheManager : Serializable { - - //--------------------------------------------------- - // DATA MEMBERS - //--------------------------------------------------- - private val stylesCache: MutableMap = HashMap() - - //--------------------------------------------------- - // IMPLEMENTATIONS - //--------------------------------------------------- - /** - * Returns the cell style corresponding to the given alignment, data format and color. - * If the style is not cached yet, it will be created and added to the cache. - * @param exporter The excel exporter instance. - * @param wb The workbook instance. - * @param alignment The style alignment. - * @param dataFormat The style data format. - * @param color The style background color. - * @return The style instance. - */ - fun getStyle( - wb: Workbook, - alignment: Short, - dataFormat: Short, - color: Color, - ): CellStyle { - val key = StyleKey(alignment, dataFormat, color) - if (!stylesCache.containsKey(key)) { - val style: CellStyle = wb.createCellStyle() - - style.verticalAlignment = VerticalAlignment.TOP - style.borderBottom = BorderStyle.THIN - style.bottomBorderColor = IndexedColors.BLACK.getIndex() - style.borderLeft = BorderStyle.THIN - style.leftBorderColor = IndexedColors.BLACK.getIndex() - style.borderRight = BorderStyle.THIN - style.rightBorderColor = IndexedColors.BLACK.getIndex() - style.borderTop = BorderStyle.THIN - style.topBorderColor = IndexedColors.BLACK.getIndex() - style.fillPattern = FillPatternType.SOLID_FOREGROUND - style.wrapText = true - style.alignment = HorizontalAlignment.forInt(alignment.toInt()) - if (dataFormat.toInt() != -1) { - style.dataFormat = dataFormat - } - stylesCache[key] = style - } - return stylesCache[key]!! - } - - //--------------------------------------------------- - // INNER CLASSES - //--------------------------------------------------- - inner class StyleKey(private val alignment: Short, private val dataFormat: Short, private val color: Color) { - - //--------------------------------------- - // IMPLEMENTATIONS - //--------------------------------------- - override fun equals(other: Any?): Boolean = - if (other is StyleKey) { - alignment == other.alignment && dataFormat == other.dataFormat && color == other.color - } else { - super.equals(other) - } - - override fun hashCode(): Int = alignment + dataFormat + color.hashCode() - } -} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/ColumnStyle.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/ColumnStyle.kt deleted file mode 100644 index 126ea8208..000000000 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/ColumnStyle.kt +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN - * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -package org.kopi.galite.visual.pivotTable - -import java.awt.Color -import java.awt.Font -import java.io.Serializable - -import org.kopi.galite.util.base.InconsistencyException - -class ColumnStyle : Serializable { - - var foregroundCode = 0 - var backgroundCode = 0 - var fontName = 0 - var fontStyle = 0 - var state = 0 - - /** - * Gets the background color of this component. - * - * @return color The color to become this component's background color. - */ - fun getBackground(): Color = when (backgroundCode) { - Constants.CLR_WHITE -> Color.white - Constants.CLR_BLACK -> Color.black - Constants.CLR_RED -> Color.red - Constants.CLR_GREEN -> Color.green - Constants.CLR_BLUE -> Color.blue - Constants.CLR_YELLOW -> Color.yellow - Constants.CLR_PINK -> Color.pink - Constants.CLR_CYAN -> Color.cyan - Constants.CLR_GRAY -> Color.gray - else -> - throw InconsistencyException( - message = "The background's color doesn't exist within the specified colors scope" - ) - } - - /** - * Gets the foreground color of this component. - * - * @return color The color to become this component's foreground color. - */ - fun getForeground(): Color = when (foregroundCode) { - Constants.CLR_WHITE -> Color.white - Constants.CLR_BLACK -> Color.black - Constants.CLR_RED -> Color.red - Constants.CLR_GREEN -> Color.green - Constants.CLR_BLUE -> Color.blue - Constants.CLR_YELLOW -> Color.yellow - Constants.CLR_PINK -> Color.pink - Constants.CLR_CYAN -> Color.cyan - Constants.CLR_GRAY -> Color.gray - else -> throw InconsistencyException( - message = "The foreground's color doesn't exist within the specified colors scope" - ) - } - - /** - * Gets the font of this component. - * - * @return font The font to become this component's font. - */ - fun getFont(): Font { - val font = when (fontName) { - 0 -> org.kopi.galite.visual.Constants.FNT_FIXED_WIDTH - 1 -> "Helvetica" - 2 -> "Geneva" - 3 -> "Courier" - else -> throw InconsistencyException( - message = "Font doesn't exist within the specified scope" - ) - } - return Font(font, fontStyle, 12) - } -} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/Constants.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/Constants.kt index 3c19b9664..fc8259472 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/Constants.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/Constants.kt @@ -23,91 +23,9 @@ import org.kopi.galite.visual.Constants interface Constants : Constants { companion object { - // -------------------------------------------------------------------- - // COLUMN OPTIONS - // -------------------------------------------------------------------- - const val CLO_VISIBLE = 0 - const val CLO_HIDDEN = 1 - - // --------------------------------------------------------------------- - // ALIGNMENT - // --------------------------------------------------------------------- - const val ALG_DEFAULT = 0 - const val ALG_LEFT = 1 - const val ALG_CENTER = 2 - const val ALG_RIGHT = 4 - - // --------------------------------------------------------------------- - // COLOR - // --------------------------------------------------------------------- - const val CLR_WHITE = 0 - const val CLR_BLACK = 1 - const val CLR_RED = 2 - const val CLR_GREEN = 3 - const val CLR_BLUE = 4 - const val CLR_YELLOW = 5 - const val CLR_PINK = 6 - const val CLR_CYAN = 7 - const val CLR_GRAY = 8 - - // --------------------------------------------------------------------- - // PRINT OPTIONS - // --------------------------------------------------------------------- - const val SUM_AT_HEAD = 1 - const val SUM_AT_TAIL = 2 - - // --------------------------------------------------------------------- - // TRIGGERED EVENTS (MAX 32) - // --------------------------------------------------------------------- - const val TRG_PREREPORT = 0 - const val TRG_POSTREPORT = 1 - const val TRG_INIT = 2 - const val TRG_FORMAT = 3 - const val TRG_COMPUTE = 4 - const val TRG_CMDACCESS = 5 - const val TRG_VOID: Int = VConstants.TRG_VOID - const val TRG_OBJECT: Int = VConstants.TRG_OBJECT - const val TRG_BOOLEAN: Int = VConstants.TRG_BOOLEAN - - // --------------------------------------------------------------------- - // CELL STATE - // --------------------------------------------------------------------- - const val STA_SEPARATOR = -2 - const val STA_FOLDED = -1 - const val STA_STANDARD = 0 - const val STA_EMPTY = 1 - const val STA_NEGATIVE = 2 - const val STA_NULL = 3 - const val STA_DEFAULT = 4 - // --------------------------------------------------------------------- // PREDEFINED COMMANDS // --------------------------------------------------------------------- const val CMD_QUIT = 0 - const val CMD_PRINT = 1 - const val CMD_PREVIEW = 2 - const val CMD_PRINT_OPTIONS = 3 - const val CMD_EXPORT_CSV = 4 - const val CMD_EXPORT_XLS = 5 - const val CMD_EXPORT_XLSX = 6 - const val CMD_EXPORT_PDF = 7 - const val CMD_FOLD = 8 - const val CMD_UNFOLD = 9 - const val CMD_SORT = 10 - const val CMD_FOLD_COLUMN = 11 - const val CMD_UNFOLD_COLUMN = 12 - const val CMD_COLUMN_INFO = 13 - const val CMD_OPEN_LINE = 14 - const val CMD_REMOVE_CONFIGURATION = 15 - const val CMD_LOAD_CONFIGURATION = 16 - const val CMD_HELP = 17 - - // --------------------------------------------------------------------- - // TRIGGER INFO - // --------------------------------------------------------------------- - val TRG_NAMES = arrayOf( - "TRG_PREREPORT", "TRG_POSTREPORT", "TRG_INIT", "TRG_FORMAT", "TRG_COMPUTE", "TRG_CMDACCESS") - val TRG_TYPES = intArrayOf( - TRG_VOID, TRG_VOID, TRG_VOID, TRG_OBJECT, TRG_OBJECT, TRG_BOOLEAN) } } diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/MPivotTable.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/MPivotTable.kt index 6cf488afb..4eb03c6e9 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/MPivotTable.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/MPivotTable.kt @@ -19,24 +19,8 @@ package org.kopi.galite.visual.pivotTable import java.io.Serializable -import java.math.BigDecimal -import java.time.Instant -import java.time.LocalDate -import java.time.LocalDateTime -import java.time.LocalTime - -import javax.swing.event.EventListenerList - -import kotlin.math.max -import org.kopi.galite.type.format import org.kopi.galite.visual.MessageCode -import org.kopi.galite.visual.VExecFailedException - -import com.graphbuilder.math.Expression -import com.graphbuilder.math.ExpressionTree -import com.graphbuilder.math.FuncMap -import com.graphbuilder.math.VarMap class MPivotTable : Constants, Serializable { @@ -49,21 +33,9 @@ class MPivotTable : Constants, Serializable { var accessibleColumns: Array = arrayOf() // array of visible or hide columns private set - // Root is the root of the tree (which is our model to manipulate data) - private var root: VGroupRow? = null // root of grouping tree - // Baserows contains data give by the request of the user - // visibleRows contains all data which will be displayed. It's like a buffer. visibleRows - // is changed when a column move or one or more row are folded internal var userRows: ArrayList? = ArrayList(500) lateinit var baseRows: Array // array of base data rows - private var visibleRows: Array? = null // array of visible rows - private var maxRowCount = 0 - - // Sortedcolumn contain the index of the sorted column - // sortingOrder store the type of sort of the sortedColumn : ascending or descending - private var sortedColumn = 0 // the table is sorted wrt. to this column - private var sortingOrder = 0 // 1: ascending, -1: descending // displayOrder contains index column model in display order // reverseOrder is calculate with displayOrder and contains index column display into model order @@ -72,296 +44,6 @@ class MPivotTable : Constants, Serializable { // The displayLevels variable is a table which contains the level of each column private lateinit var displayLevels: IntArray // column levels in display order - private val listenerList = EventListenerList() // List of listeners - - fun computeColumnWidth(column: Int): Int { - var max = 0 - - baseRows.forEach { row -> - if (row!!.getValueAt(column) != null) { - val value = row.getValueAt(column).let { value -> - when (value) { - is BigDecimal -> value.format() - is LocalDate -> value.format() - is LocalTime -> value.format() - is Instant -> value.format() - is LocalDateTime -> value.format() - else -> value.toString() - } - } - - max = max(max, value.length) - } - } - return max + 2 - } - - fun removeColumn(position: Int) { - var position = position - val cols = arrayOfNulls(columns.size - 1) - var hiddenColumns = 0 - - columns.forEach { - if (it!!.options and Constants.CLO_HIDDEN != 0) { - hiddenColumns += 1 - } - } - position += hiddenColumns - // copy columns before position. - for (i in 0 until position) { - cols[i] = columns[i] - } - // copy columns after position. - for (i in position until columns.size - 1) { - cols[i] = columns[i + 1] - } - position -= hiddenColumns - columns = cols.clone().toMutableList() - createAccessibleTab() - val rows = arrayOfNulls(baseRows.size) - - baseRows.forEachIndexed { index, element -> - val data = arrayOfNulls(getAccessibleColumnCount()) - - for (j in 0 until position) { - data[j] = element!!.getValueAt(j) - } - // skip position. - for (j in position until getAccessibleColumnCount()) { - data[j] = element!!.getValueAt(j + 1) - } - rows[index] = VBaseRow(data) - } - baseRows = rows.filterIsInstance().toTypedArray() - } - - fun initializeAfterRemovingColumn(position: Int) { - val columnCount: Int = getAccessibleColumnCount() - val newDisplayOrder = IntArray(columnCount) - - reverseOrder = IntArray(columnCount) - displayLevels = IntArray(columnCount) - for (i in 0 until position) { - newDisplayOrder[i] = displayOrder[i] - } - for (i in position until columnCount) { - newDisplayOrder[i] = displayOrder[i + 1] - } - for (i in 0 until columnCount) { - reverseOrder[i] = i - displayLevels[i] = -1 - } - displayOrder = newDisplayOrder - } - - /** - * Adds a column at runtime. - */ - fun addColumn(label: String, position: Int) { - val cols = arrayOfNulls(columns.size + 1) - - // add the new column; - cols[columns.size] = VDecimalColumn(null, 0, 4, -1, null, 15, 7, null) - cols[columns.size]!!.label = label - cols[columns.size]!!.isAddedAtRuntime = true - // copy the other columns. - columns.forEachIndexed { index, element -> - cols[index] = element - } - columns = cols.clone().toMutableList() - initializeAfterAddingColumn() - val rows = arrayOfNulls(baseRows.size) - - baseRows.forEachIndexed { index, element -> - val data = arrayOfNulls(getAccessibleColumnCount()) - - for (j in 0 until getAccessibleColumnCount() - 1) { - data[j] = element!!.getValueAt(j) - } - // fill the new column with null , column data will be set by user. - data[getAccessibleColumnCount() - 1] = null - rows[index] = VBaseRow(data) - } - baseRows = rows.filterIsInstance().toTypedArray() - } - - private fun initializeAfterAddingColumn() { - createAccessibleTab() - val columnCount: Int = getAccessibleColumnCount() - val newDisplayOrder = IntArray(columnCount) - - displayLevels = IntArray(columnCount) - reverseOrder = IntArray(columnCount) - for (i in 0 until columnCount - 1) { - newDisplayOrder[i] = displayOrder[i] - } - newDisplayOrder[columnCount - 1] = columnCount - 1 - displayOrder = newDisplayOrder - for (i in 0 until columnCount) { - reverseOrder[i] = i - displayLevels[i] = -1 - } - } - - fun computeDataForColumn(column: Int, columnIndexes: IntArray, formula: String) { - val x: Expression = try { - ExpressionTree.parse(formula) - } catch (e: Exception) { - throw VExecFailedException(MessageCode.getMessage("VIS-00064", formula, "\n$e")) - } - val params: Array = x.variableNames - val paramColumns = IntArray(params.size) - val functions = IntArray(params.size) - val NONE = -1 - val MAX = 0 - val MIN = 1 - val OVR = 2 - val SUM = 3 - - for (i in params.indices) { - try { - when { - params[i].startsWith("C") -> { - paramColumns[i] = params[i].substring(1).toInt() - functions[i] = NONE - } - params[i].startsWith("maxC") -> { - paramColumns[i] = params[i].substring(4).toInt() - functions[i] = MAX - } - params[i].startsWith("minC") -> { - paramColumns[i] = params[i].substring(4).toInt() - functions[i] = MIN - } - params[i].startsWith("ovrC") -> { - paramColumns[i] = params[i].substring(4).toInt() - functions[i] = OVR - } - params[i].startsWith("sumC") -> { - paramColumns[i] = params[i].substring(4).toInt() - functions[i] = SUM - } - else -> { - throw VExecFailedException( - MessageCode.getMessage("VIS-00061", - "${params[i]}\n", - "Cx, maxCx, minCx, ovrCx, sumCx")) - } - } - } catch (e: NumberFormatException) { - throw VExecFailedException(MessageCode.getMessage("VIS-00062", params[i].substring(1))) - } - // test column indexes. - var test = false - - for (j in columnIndexes.indices) { - if (paramColumns[i] == columnIndexes[j]) { - test = true - break - } - } - if (!test) { - throw VExecFailedException(MessageCode.getMessage("VIS-00063", params[i].substring(1))) - } - } - val vm = VarMap(false /* case sensitive */) - val fm: FuncMap? = null // no functions in expression - var tmp: Float - - for (i in baseRows.indices) { - for (j in paramColumns.indices) { - when (functions[j]) { - NONE -> { - val value = if (baseRows[i]!!.getValueAt(paramColumns[j]) == null) { - 0.0 - } else { - // !!! wael 20070622 : use 0 instead of null values. - (baseRows[i]!!.getValueAt(paramColumns[j]) as BigDecimal).toDouble() - } - vm.setValue(params[j], value) - } - MAX -> { - var max: Float - // init max - max = if (baseRows[0]!!.getValueAt(paramColumns[j]) == null) { - 0F - } else { - (baseRows[0]!!.getValueAt(paramColumns[j]) as BigDecimal).toFloat() - } - // calculate max value. - baseRows.forEach { - tmp = if (it!!.getValueAt(paramColumns[j]) == null) { - 0F - } else { - (it.getValueAt(paramColumns[j]) as BigDecimal).toFloat() - } - if (tmp > max) { - max = tmp - } - } - vm.setValue(params[j], max.toDouble()) - } - MIN -> { - var min: Float - - // init max - min = if (baseRows[0]!!.getValueAt(paramColumns[j]) == null) { - 0F - } else { - (baseRows[0]!!.getValueAt(paramColumns[j]) as BigDecimal).toFloat() - } - // calculate min value. - baseRows.forEach { - tmp = if (it!!.getValueAt(paramColumns[j]) == null) { - 0F - } else { - (it.getValueAt(paramColumns[j]) as BigDecimal).toFloat() - } - if (tmp < min) { - min = tmp - } - } - vm.setValue(params[j], min.toDouble()) - } - OVR -> { - var ovr = 0f - // calculate average. - baseRows.forEach { - tmp = if (it!!.getValueAt(paramColumns[j]) == null) { - 0F - } else { - (it.getValueAt(paramColumns[j]) as BigDecimal).toFloat() - } - ovr += tmp / baseRows.size - } - vm.setValue(params[j], ovr.toDouble()) - } - SUM -> { - var sum = 0f - // calculate sum. - baseRows.forEach { - tmp = if (it!!.getValueAt(paramColumns[j]) == null) { - 0F - } else { - (it.getValueAt(paramColumns[j]) as BigDecimal).toFloat() - } - sum += tmp - } - vm.setValue(params[j], sum.toDouble()) - } - } - } - try { - baseRows[i]!!.setValueAt(column, BigDecimal(x.eval(vm, fm))) - } catch (e: NumberFormatException) { - // this exception occurs with INFINITE double values. (ex : division by ZERO) - // return a null value (can not evaluate expression) - baseRows[i]!!.setValueAt(column, null) - } catch (e: Exception) { - throw VExecFailedException(MessageCode.getMessage("VIS-00066")) - } - } - } /** * Add a row to the list of rows defined by the user @@ -382,16 +64,16 @@ class MPivotTable : Constants, Serializable { baseRows = userRows!!.toTypedArray() userRows = null - // build working tables - val columnCount = getAccessibleColumnCount() - displayOrder = IntArray(columnCount) - reverseOrder = IntArray(columnCount) - displayLevels = IntArray(columnCount) - for (i in 0 until columnCount) { - displayOrder[i] = i - reverseOrder[i] = i - displayLevels[i] = -1 - } +// // build working tables +// val columnCount = getAccessibleColumnCount() +// displayOrder = IntArray(columnCount) +// reverseOrder = IntArray(columnCount) +// displayLevels = IntArray(columnCount) +// for (i in 0 until columnCount) { +// displayOrder[i] = i +// reverseOrder[i] = i +// displayLevels[i] = -1 +// } } // -------------------------------------------------------------------- // MEMBER ACCESS @@ -411,14 +93,6 @@ class MPivotTable : Constants, Serializable { */ fun getModelColumnCount(): Int = columns.size - /** - * Return a column definition - * - * @param column the index of the desired column - * @return the desired column - */ - fun getAccessibleColumn(column: Int): VReportColumn? = accessibleColumns[column] - /** * Returns the number of columns visible or hide * @@ -426,488 +100,6 @@ class MPivotTable : Constants, Serializable { */ fun getAccessibleColumnCount(): Int = accessibleColumns.size - /** - * Return a row definition - * - * @param row the index of the desired row - * @return the desired row - */ - fun getRow(row: Int): VReportRow? = visibleRows!![row] - - /** - * Return the tree used by the model - */ - fun getTree(): VGroupRow? = root - - // -------------------------------------------------------------------- - // GROUPING TREE - // -------------------------------------------------------------------- - internal fun createTree() { - // compute grouping columns in displayed column order - computeGroupings() - - // sort base rows wrt to each grouping column - sortBaseRows() - - // build the grouping tree recursively - buildGroupingTree() - - // compute all intermediate columns - calculateColumns() - - // create the array of displayed rows - updateTableModel() - } - - /** - * Returns an array of grouping columns in displayed column order - * For each column, the value is the column of the next (lower) level - * grouping or -1 if the column has no further sub-grouping. - * The columns are given in displayed column order - */ - private fun computeGroupings() { - val columnCount = accessibleColumns.size - val defaultGroups = IntArray(columnCount) - val displayGroups = IntArray(columnCount) - var separatorPos = Int.MAX_VALUE - - // retrieve the groups in original column order - for (i in 0 until columnCount) { - defaultGroups[i] = accessibleColumns[i]!!.groups - } - - // reorder the groups in displayed column order - for (i in 0 until columnCount) { - when { - defaultGroups[displayOrder[i]] == -1 -> { - displayGroups[i] = -1 - } - defaultGroups[displayOrder[i]] >= reverseOrder.size -> { - displayGroups[i] = reverseOrder.size - } // not shown - else -> { - displayGroups[i] = reverseOrder[defaultGroups[displayOrder[i]]] - } - } - } - - // retrieve separator - for (i in 0 until columnCount) { - if (accessibleColumns[displayOrder[i]] is VSeparatorColumn) { - separatorPos = i - } - } - var level = 0 - - //top is reached - run { - var i = 0 - while (i < displayGroups.size) { - displayLevels[i] = level - if (accessibleColumns[displayOrder[i]]!!.isVisible) { - if (displayGroups[i] == -1 || i == separatorPos) { - while (i < displayGroups.size) { - displayLevels[i] = level - i++ - } - break - } else if (displayGroups[i] > i) { - while (i + 1 < displayGroups.size && displayGroups[i + 1] <= i + 1 && displayGroups[i + 1] != -1) { - displayLevels[i + 1] = level - i++ - } - level++ - } - } - i++ - } - } - - // renumber levels from highest to lowest (0) - for (i in 0 until columnCount) { - displayLevels[i] = level - displayLevels[i] - } - } - - /** - * Sort base rows wrt to each grouping column - * Note: we assume that the sorting algorithm ist stable: we thus - * can sort the complete table for each column, starting with the - * last grouping column. - */ - private fun sortBaseRows() { - visibleRows = arrayOfNulls(baseRows.size) - sortBaseRows(0) - } - - private fun sortBaseRows(column: Int) { - if (displayLevels[column] > 0) { - var next = column + 1 - - while (displayLevels[next] == displayLevels[next - 1]) { - next += 1 - } - sortBaseRows(next) - } - // sort in ascending order - var i = column - while (!accessibleColumns[i]!!.isVisible) { - i += 1 - } - if (i >= 0) { - sortArray(baseRows, displayOrder[i], 1) - // this value is overwritten in each pass: at the end - // of the recursion it will hold the first column - sortedColumn = displayOrder[i] - sortingOrder = 1 - } - } - - /** - * Build the grouping tree - */ - private fun buildGroupingTree() { - maxRowCount = baseRows.size + 1 - root = VGroupRow(arrayOfNulls(getModelColumnCount()), displayLevels[0] + 1) - // even if column 0 is hidden, it has the highest level - buildGroupingTree(root!!, 0, baseRows.size - 1, 0) - visibleRows = arrayOfNulls(maxRowCount) - root!!.visible = true - for (i in 0 until root!!.childCount) { - (root!!.getChildAt(i) as VReportRow).visible = true - } - } - - private fun buildGroupingTree(tree: VReportRow, loRow: Int, hiRow: Int, start: Int) { - var loRow = loRow - var start = start - - if (displayLevels[start] == 0) { // even if the 0-index column is hidden, its displayLevels == 0 - for (i in loRow..hiRow) { - tree.add(baseRows[i]) - } - } else { - // get the interval of columns at this level - var next: Int = start + 1 - - while (displayLevels[next] == displayLevels[start]) { - next++ - } - while (!accessibleColumns[start]!!.isVisible) { - // to get the first visible column of this level - start++ - } - - do { - val value = baseRows[loRow]!!.getValueAt(displayOrder[start]) - var split = loRow - - while (split <= hiRow && (value == null && baseRows[split]!!.getValueAt(displayOrder[start]) == null - || value != null && value == baseRows[split]!!.getValueAt(displayOrder[start]))) { - split += 1 - } - val newRow = VGroupRow(arrayOfNulls(getModelColumnCount()), displayLevels[start]) - - maxRowCount++ - for (i in 0 until next) { - newRow.setValueAt(displayOrder[i], baseRows[loRow]!!.getValueAt(displayOrder[i])) - } - buildGroupingTree(newRow, loRow, split - 1, next) - tree.add(newRow) - loRow = split - } while (loRow <= hiRow) - } - } - - /** - * Sorts an array of rows wrt to given column using straight two-way merge sorting. - * - * @param array The array to sort - * @param column The index of the column on which to sort - * @param order The sorting order (1: ascending, -1: descending) - */ - private fun sortArray(array: Array, column: Int, order: Int) { - mergeSort(array, column, order, 0, array.size - 1, visibleRows) - } - - private fun mergeSort(array: Array, - column: Int, - order: Int, - lo: Int, - hi: Int, - scratch: Array?) { - // a one-element array is always sorted - if (lo < hi) { - val mid = (lo + hi) / 2 - - // split into 2 sublists and sort them - mergeSort(array, column, order, lo, mid, scratch) - mergeSort(array, column, order, mid + 1, hi, scratch) - - // Merge sorted sublists - var t_lo = lo - var t_hi = mid + 1 - - for (k in lo..hi) { - if (t_lo > mid || - t_hi <= hi && - order * array[t_hi]!!.compareTo(array[t_lo]!!, column, getModelColumn(column)) < 0) { - scratch!![k] = array[t_hi++] - } else { - scratch!![k] = array[t_lo++] - } - } - - // Copy back to array - for (k in lo..hi) { - array[k] = scratch!![k] - } - } - } - - /** - * Calculate all columns which need to be calculated - */ - fun calculateColumns() { - for (i in columns.indices) { - val function: VCalculateColumn? = columns[i]!!.function - - if (function != null) { - function.init() - function.calculate(root!!, i) - } - } - } - - /** - * fill table of visible rows - */ - private fun updateTableModel() { - maxRowCount = addRowsInArray(root, 0) - fireContentChanged() - } - - /** - * add visible rows in a vector - * - * @param node node to test. - * @param pos position of the node. - */ - private fun addRowsInArray(node: VReportRow?, pos: Int): Int { - var position = pos - - if (node!!.visible) { - visibleRows!![position++] = node - for (i in 0 until node.childCount) { - val row = node.getChildAt(i) as VReportRow - - if (row.level == 0) { - if (row.visible) { - visibleRows!![position++] = row - } - } else { - position = addRowsInArray(node.getChildAt(i) as VReportRow, position) - } - } - } - return position - } - // -------------------------------------------------------------------- - // EVENTS FROM DISPLAY - // -------------------------------------------------------------------- - /** - * Sort the displayed tree wrt to a column - * - * @param column the model column index used for sorting in display order. - */ - fun sortColumn(column: Int) { - sortTree(column) - calculateColumns() - updateTableModel() - } - - /** - * Sort the displayed tree wrt to a column - * - * @param column the model column index used for sorting in display order. - * @param order sort order. - */ - fun sortColumn(column: Int, order: Int) { - sortTree(root, column, order) - calculateColumns() - updateTableModel() - } - - /** - * Sort the display tree wrt to a column; if it is already sorted - * wrt to this column, invert the sorting order. - * - * @param column The model column index given in display order - */ - private fun sortTree(column: Int) { - val order: Int = if (column != sortedColumn) 1 else -sortingOrder - - sortTree(root, column, order) - sortedColumn = column - sortingOrder = order - } - - private fun sortTree(tree: VReportRow?, column: Int, order: Int) { - - // place the children of the root in an array - val rowTab: Array = arrayOfNulls(tree!!.childCount) - - for (i in 0 until tree.childCount) { - rowTab[i] = tree.getChildAt(i) as VReportRow - } - - // sort the array wrt to column: if already sorted, invert order - sortArray(rowTab, column, order) - - // re-add the rows as children - tree.removeAllChildren() - for (i in rowTab.indices) { - tree.add(rowTab[i]) - } - - // sort sub-trees recursively - if (tree.level > 1) { - for (i in 0 until tree.childCount) { - sortTree(tree.getChildAt(i) as VReportRow, column, order) - } - } - } - - /** - * Returns true is the specified column is fold - */ - fun isColumnFold(column: Int): Boolean { - return if (root!!.level > 1) { - val level = displayLevels[reverseOrder[column]] - - !root!!.isUnfolded(level) - } else { - false - } - } - - /** - * Returns true if the specified row is fold at the specified column - */ - fun isRowFold(row: Int, column: Int): Boolean { - return if (root!!.level > 1) { - val level = displayLevels[reverseOrder[column]] - var currentRow = visibleRows!![row] - - while (currentRow!!.level < level) { - currentRow = currentRow.parent as? VReportRow - } - if (currentRow is VGroupRow?) !currentRow.isUnfolded(level) else true - } else { - false - } - } - - /** - * Folds the specified column - */ - fun foldingColumn(column: Int) { - if (root!!.level > 1) { - val level = displayLevels[reverseOrder[column]] - - root!!.setChildNodesInvisible(level) - updateTableModel() - } - } - - /** - * Unfolds the specified column - */ - fun unfoldingColumn(column: Int) { - if (root!!.level > 1) { - val level = displayLevels[reverseOrder[column]] - - root!!.setChildNodesVisible(level) - updateTableModel() - } - } - - /** - * Folds the specified column - */ - fun setColumnFolded(column: Int, fold: Boolean) { - accessibleColumns[column]!!.isFolded = fold - fireContentChanged() - } - - /** - * Folds the specified column - */ - fun switchColumnFolding(column: Int) { - accessibleColumns[column]!!.isFolded = (!accessibleColumns[column]!!.isFolded) - fireContentChanged() - } - - /** - * Folds the specified row to specified column - * - * @param column the model index of the column - */ - fun foldingRow(row: Int, column: Int) { - if (root!!.level > 1) { - val level = displayLevels[reverseOrder[column]] - var currentRow = visibleRows!![row] - - while (currentRow!!.level < level) { - currentRow = currentRow.parent as? VReportRow - } - if (currentRow is VGroupRow?) { - currentRow.setChildNodesInvisible(level) - } - updateTableModel() - } - } - - /** - * Unfolds the specified row to specified column - * - * @param column the model index of the column - */ - fun unfoldingRow(row: Int, column: Int) { - if (root!!.level > 1) { - val level = displayLevels[reverseOrder[column]] - val currentRow = visibleRows!![row] - - if (currentRow is VGroupRow) { - currentRow.setChildNodesVisible(level) - } - updateTableModel() - } - } - - /** - * Returns true if the specified row is fold at the specified column - */ - fun isRowLine(row: Int): Boolean { - return if (visibleRows != null) { - row in 0 until maxRowCount && visibleRows!![row]!!.level == 0 - } else { - false - } - } - - /** - * @param newOrder the table of the display order columns - */ - fun columnMoved(newOrder: IntArray) { - displayOrder = newOrder - - // rebuild column mapping from model to display - displayOrder.forEachIndexed { index, element -> - reverseOrder[element] = index - } - createTree() - } // -------------------------------------------------------------------- // REDEFINITION OF METHODS IN AbstractTableModel // -------------------------------------------------------------------- @@ -918,56 +110,6 @@ class MPivotTable : Constants, Serializable { */ fun getColumnCount(): Int = accessibleColumns.size - /** - * Returns the number of records managed by the data source object. - * - * @return the number or rows in the model - */ - fun getRowCount(): Int = maxRowCount - - /** - * Returns always false since report cells are never editable. - * - * @param row the index of the row whose value is to be looked up - * @param column the index of the column whose value is to be looked up - * @return true if the cell is editable. - */ - fun isCellEditable(row: Int, column: Int): Boolean = false - - /** - * Returns an attribute value for a cell. - * - * @param row the index of the row whose value is to be looked up - * @param column the index of the column whose value is to be looked up (column of the model) - * @return the value Object at the specified cell - */ - fun getValueAt(row: Int, column: Int): Any? { - var x: Any? = null - - try { - x = visibleRows!![row]!!.getValueAt(column) - } catch (e: Exception) { - e.printStackTrace() - } - return if (visibleRows!![row]!!.level < displayLevels[reverseOrder[column]]) null else x - } - - /** - * Returns the name of a column. - * Note, this name does not need to be unique. - * - * @param column the index of the column - * @return the name of the column - */ - fun getColumnName(column: Int): String { - val label = accessibleColumns[column]!!.label - - if (label.isEmpty()) { - return "" - } - return if (accessibleColumns[column]!!.isFolded) label.substring(0, 1) else label - } - /** * Makes the table of accessible columns from the columns variable */ @@ -976,74 +118,16 @@ class MPivotTable : Constants, Serializable { var accessiblecolumnCount = 0 for (i in 0 until columnCount) { - if (columns[i]!!.options and Constants.CLO_HIDDEN == 0) { accessiblecolumnCount += 1 - } } accessibleColumns = arrayOfNulls(accessiblecolumnCount) accessiblecolumnCount = 0 for (i in 0 until columnCount) { - if (columns[i]!!.options and Constants.CLO_HIDDEN == 0) { accessibleColumns[accessiblecolumnCount++] = columns[i] - } - } - } - - fun getDisplayLevels(column: Int): Int = displayLevels[column] - - fun getReverseOrder(column: Int): Int = reverseOrder[column] - - fun getDisplayOrder(column: Int): Int = displayOrder[column] - - /** - * Returns the number of base rows. - */ - fun getBaseRowCount(): Int = baseRows.size - - /** - * Returns the number of visible rows. - */ - fun getVisibleRowCount(): Int = visibleRows!!.size - - // -------------------------------------------------------------------- - // LISTENERS HANDLING - // -------------------------------------------------------------------- - /** - * Adds a listener to the list that's notified each time a change - * to the data model occurs. - * - * @param l The ReportListener - */ - fun addReportListener(l: ReportListener) { - listenerList.add(ReportListener::class.java, l) - } - - /** - * Removes a listener from the list that's notified each time a - * change to the data model occurs. - * - * @param l The ReportListener - */ - fun removeReportListener(l: ReportListener) { - listenerList.remove(ReportListener::class.java, l) - } - - /** - * Notifies all listeners that the report model has changed. - */ - protected fun fireContentChanged() { - val listeners = listenerList.listenerList - var i = listeners.size - 2 - - while (i >= 0) { - if (listeners[i] == ReportListener::class.java) { - (listeners[i + 1] as ReportListener).contentChanged() - } - i -= 2 } } companion object { private const val serialVersionUID = 0L } -} +} \ No newline at end of file diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/PConfig.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/PConfig.kt deleted file mode 100644 index 770dd5d66..000000000 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/PConfig.kt +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN - * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -package org.kopi.galite.visual.pivotTable - -import java.io.Serializable - -import org.kopi.galite.visual.util.PPaperType - -/** - * PConfig Class that allows to set the configuration parameters - * @param papertype different formats of paper - * @param paperlayout the layout of the paper (Portrait or Landscape) - * @param topmargin top sheet margin in points - * @param bottommargin bottom sheet margin in points - * @param leftmargin left sheet margin in points - * @param rightmargin right sheet margin in points - * @param headermargin header sheet margin in points - * @param footermargin footer sheet margin in points - * @param visibleRows true if only visible rows must be displayed - * @param order order to used for printing - * @param groupFormfeed cut the form at each big nivel - * @param grid_H horizontal grid - * @param grid_V vertical grid - * @param border border size - * @param reportScale report scale - */ -data class PConfig(val papertype: Int = PPaperType.PPT_A4.code, - val paperlayout: String = "Landscape", - val topmargin: Int = 30, - val bottommargin: Int = 30, - val leftmargin: Int = 30, - val rightmargin: Int = 30, - val headermargin: Int = 5, - val footermargin: Int = 10, - val visibleRows: Boolean = true, - val order: Int = Constants.SUM_AT_TAIL, - val groupFormfeed: Boolean = false, - val grid_H: Double = 0.1, - val grid_V: Double = 0.1, - val border: Double = 1.0, - val reportScale: Double = MIN_REPORT_SCALE) : Serializable { - - companion object { - const val MIN_REPORT_SCALE = 3.0 - const val MAX_REPORT_SCALE = 12.0 - } -} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/Parameters.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/Parameters.kt deleted file mode 100644 index 4db217948..000000000 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/Parameters.kt +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN - * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -package org.kopi.galite.visual.pivotTable - -import java.awt.Color -import java.awt.Font -import java.io.Serializable - -import org.kopi.galite.visual.Constants - -/** - * Parameters class . - * - * @param color a color defined in Constants - */ -class Parameters(color: Color) : Serializable { - /**Returns the size of the font*/ - val font = Font(Constants.FNT_FIXED_WIDTH, Font.PLAIN, 12) - private val bgcolors: Array = arrayOfNulls(10) - private val fgcolors = Array(10) { Color(0, 0, 0) } - - init { - val reverseColor = Color(255 - color.red, 255 - color.green, 255 - color.blue) - for (i in bgcolors.indices) { - bgcolors[i] = Color(255 - i * reverseColor.red / 17, - 255 - i * reverseColor.green / 17, - 255 - i * reverseColor.blue / 17) - } - } - - /** - * Returns the background color which corresponds to the level - */ - fun getBackground(level: Int): Color { - return if (level >= bgcolors.size) Color.white else bgcolors[level]!! - } - - /** - * Returns the foreground color which corresponds to the level - */ - fun getForeground(level: Int): Color { - return if (level >= fgcolors.size) Color.black else fgcolors[level] - } -} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/Point.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/Point.kt deleted file mode 100644 index b4e8fdd43..000000000 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/Point.kt +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN - * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -package org.kopi.galite.visual.pivotTable - -import java.io.Serializable - -/** - * A point representing a location in `(x,y)` coordinate space, - * specified in integer precision. - */ -data class Point(val x: Int = 0, val y: Int = 0) : Serializable { - - /** - * Returns a string representation of this point and its location - * in the `(x,y)` coordinate space. This method is - * intended to be used only for debugging purposes, and the content - * and format of the returned string may vary between implementations. - * The returned string may be empty but may not be `null`. - * - * @return a string representation of this point - */ - override fun toString() = javaClass.name + "[x=" + x + ",y=" + y + "]" -} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/ReportListener.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/ReportListener.kt deleted file mode 100644 index 489954724..000000000 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/ReportListener.kt +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN - * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -package org.kopi.galite.visual.pivotTable - -import java.io.Serializable -import java.util.EventListener - -/** - * `TableModelListener` defines the interface for an object that listens - * to changes in [MPivotTable] content. - * - * @see javax.swing.table.TableModel - */ -interface ReportListener : EventListener, Serializable { - /** - * This fine grain notification tells listeners that - * the report model has changed and the display should - * update it self - */ - fun contentChanged() -} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/UPivotTable.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/UPivotTable.kt index 4b1cb23ae..08a4a3065 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/UPivotTable.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/UPivotTable.kt @@ -20,85 +20,9 @@ package org.kopi.galite.visual.pivotTable import org.kopi.galite.visual.UWindow -/** - * `UReport` is the top-level interface that must be implemented - * by all dynamic reports. It is the visual component of the [VPivotTable] model. - */ -interface UPivotTable : UWindow, ReportListener { +interface UPivotTable : UWindow { /** * Builds the report; */ fun build() - - /** - * Redisplays the report - */ - fun redisplay() - - /** - * Fired when report columns has moved. - * @param pos The new columns positions - */ - fun columnMoved(pos: IntArray) - - /** - * Removes a column having the position `position` - * @param position The column position - */ - fun removeColumn(position: Int) - - /** - * Adds a column at the position `position` - * @param position The column position - */ - fun addColumn(position: Int) - - /** - * Adds a column at the end of the report - */ - fun addColumn() - - /** - * Returns the report table. - */ - fun getTable(): UTable - - /** - * Reset columns width - */ - fun resetWidth() - - /** - * Returns the selected column - */ - fun getSelectedColumn(): Int - - /** - * Returns the coordinate of the selected cell - * The index of the column is relative to the model - */ - fun getSelectedCell(): Point - - /** - * Sets the column label. - * @param column The column number. - * @param label The column label - */ - fun setColumnLabel(column: Int, label: String) - - /** - * [UTable] is a report table ensuring conversion between - * visible indexes and model indexes - */ - interface UTable { - /** - * Maps the index of the column in the view at [viewColumnIndex] to the index of the column in the table model. - */ - fun convertColumnIndexToModel(viewColumnIndex: Int): Int - - /** - * Maps the index of the column in the table model at [modelColumnIndex] to the index of the column in the view. - */ - fun convertColumnIndexToView(modelColumnIndex: Int): Int - } } diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VBooleanCodeColumn.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VBooleanCodeColumn.kt deleted file mode 100644 index 2c797e81c..000000000 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VBooleanCodeColumn.kt +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN - * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -package org.kopi.galite.visual.pivotTable - -import org.kopi.galite.util.base.InconsistencyException - -/** - * Represents a report column description - * - * @param ident The column identifier - * @param options The column options as bitmap - * @param align The column alignment - * @param groups The index of the column grouped by this one or -1 - * @param function An (optional) summation function - */ -class VBooleanCodeColumn(ident: String?, - type: String?, - source: String?, - options: Int, - align: Int, - groups: Int, - function: VCalculateColumn?, - width: Int, - format: VCellFormat?, - names: Array, - private val codes: BooleanArray) - : VCodeColumn(ident, - type, - source, - options, - align, - groups, - function, - width, - format, - names) { - - init { - if (codes.size > 2) { - throw InconsistencyException("Can't define more than two codes for a boolean column") - } - } - - override fun compareTo(object1: Any, object2: Any): Int { - return if (object1 == object2) 0 else if (true == object1) 1 else -1 - } - - /** - * Get the index of the value. - */ - override fun getIndex(value: Any): Int { - return if ((value as Boolean) == codes[0]) 0 else 1 - } -} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VBooleanColumn.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VBooleanColumn.kt deleted file mode 100644 index 4634a7fbc..000000000 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VBooleanColumn.kt +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN - * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -package org.kopi.galite.visual.pivotTable - -import org.kopi.galite.visual.VlibProperties - -/** - * Represents a report column description - * - * @param ident The column identifier - * @param options The column options as bitmap - * @param align The column alignment - * @param groups The index of the column grouped by this one or -1 - * @param function An (optional) summation function - */ -class VBooleanColumn(ident: String?, - options: Int, - align: Int, - groups: Int, - function: VCalculateColumn?, - format: VCellFormat?) - : VReportColumn(ident, - options, - align, - groups, - function, - VlibProperties.getString("true").length.coerceAtLeast(VlibProperties.getString("false").length), - 1, - format ?: VBooleanFormat()) { - /** - * Compare two objects. - * - * @param object1 the first operand of the comparison - * @param object2 the second operand of the comparison - * @return -1 if the first operand is smaller than the second - * 1 if the second operand if smaller than the first - * 0 if the two operands are equal - */ - override fun compareTo(object1: Any, object2: Any): Int { - return if (object1 == object2) 0 else if (true == object1) 1 else -1 - } - - private class VBooleanFormat : VCellFormat() { - override fun format(value: Any?): String { - return if (value == null) "" else if (true == value) trueRep else falseRep - } - } - - companion object { - // -------------------------------------------------------------------- - // DATA MEMBERS - // -------------------------------------------------------------------- - private val trueRep = VlibProperties.getString("true") - private val falseRep = VlibProperties.getString("false") - } -} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VCCDepthFirstCircuitN.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VCCDepthFirstCircuitN.kt deleted file mode 100644 index c6f45cc50..000000000 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VCCDepthFirstCircuitN.kt +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN - * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -package org.kopi.galite.visual.pivotTable - -abstract class VCCDepthFirstCircuitN : VCalculateColumn() { - /** - * Initialisation of the calculation - */ - override fun init() {} - - /** - * Evaluates nodes - */ - override fun evalNode(row: VReportRow, column: Int): Any? = null - - /** - * Evaluates leafs - */ - open fun evalLeaf(row: VReportRow, column: Int): Any? = null - - /** - * Add calculated data into the report row - */ - override fun calculate(tree: VGroupRow, column: Int) { - if (tree.level > 1) { - val childCount: Int = tree.childCount - - for (i in 0 until childCount) { - calculate(tree.getChildAt(i) as VGroupRow, column) - } - } else { - val childCount: Int = tree.childCount - - for (i in 0 until childCount) { - val evaluatedObject = evalLeaf(tree.getChildAt(i) as VBaseRow, column) - - if (evaluatedObject != null) { - (tree.getChildAt(i) as VBaseRow).setValueAt(column, evaluatedObject) - } - } - } - tree.setValueAt(column, evalNode(tree, column)) - } -} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VCalculateColumn.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VCalculateColumn.kt deleted file mode 100644 index 6e2741ce3..000000000 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VCalculateColumn.kt +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN - * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -package org.kopi.galite.visual.pivotTable - -abstract class VCalculateColumn { - /** - * Initialisation of the calculation - */ - abstract fun init() - - /** - * Evaluates nodes - */ - open fun evalNode(row: VReportRow, column: Int): Any? = null - - /** - * Add calculated data into the report row - */ - abstract fun calculate(tree: VGroupRow, column: Int) -} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VCellFormat.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VCellFormat.kt deleted file mode 100644 index 8c204f74c..000000000 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VCellFormat.kt +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN - * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -package org.kopi.galite.visual.pivotTable - -import java.math.BigDecimal -import java.time.Instant -import java.time.LocalDate -import java.time.LocalDateTime -import java.time.LocalTime - -import org.kopi.galite.type.format - -open class VCellFormat { - /** - * Return a formatted string of the Object - * @return the value formatted - */ - open fun format(value: Any?): String { - return when (value) { - is BigDecimal -> value.format() - is LocalDate -> value.format() - is LocalTime -> value.format() - is Instant -> value.format() - is LocalDateTime -> value.format() - else -> value?.toString() ?: "" - } - } -} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VCodeColumn.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VCodeColumn.kt deleted file mode 100644 index c20fa1c8d..000000000 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VCodeColumn.kt +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN - * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -package org.kopi.galite.visual.pivotTable - -import kotlin.math.max - -import org.kopi.galite.visual.l10n.FieldLocalizer -import org.kopi.galite.visual.l10n.TypeLocalizer - -/** - * Represents a report column description - * - * @param ident The column identifier - * @param options The column options as bitmap - * @param align The column alignment - * @param groups The index of the column grouped by this one or -1 - * @param function An (optional) summation function - */ -abstract class VCodeColumn(ident: String?, - private val type: String?, - private val source: String?, - options: Int, align: Int, - groups: Int, function: VCalculateColumn?, - width: Int, - format: VCellFormat?, - private val idents: Array) - : VReportColumn(ident, - options, - align, - groups, - function, - width, - 1, - format) { - - protected var names: Array? = null // array of external representations - - /** - * Compares two objects. - * - * @param object1 the first operand of the comparison - * @param object2 the second operand of the comparison - * @return -1 if the first operand is smaller than the second - * 1 if the second operand if smaller than the first - * 0 if the two operands are equal - */ - abstract override fun compareTo(object1: Any, object2: Any): Int - - /** - * Return a string representation. - */ - override fun format(o: Any?): String { - return if (isFolded || o == null) { - "" - } else { - format?.format(o) ?: if (names != null) names!![getIndex(o)]!! else idents[getIndex(o)] - } - } - - /** - * Get the index of the value. - */ - abstract fun getIndex(value: Any): Int - - // ---------------------------------------------------------------------- - // LOCALIZATION - // ---------------------------------------------------------------------- - /** - * Localizes this field - * - * @param parentLocalizer the caller localizer - */ - override fun localize(parentLocalizer: FieldLocalizer) { - val loc: TypeLocalizer = parentLocalizer.manager.getTypeLocalizer(source, type) - names = Array(idents.size) { i -> - val label = loc.getCodeLabel(idents[i]) - this.width = max(this.width, label.length) - label - } - } - - fun initLabels(labels: Array) { - names = labels.map { - this.width = max(this.width, it.length) - it - }.toTypedArray() - } -} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VDateColumn.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VDateColumn.kt deleted file mode 100644 index 0efbf674d..000000000 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VDateColumn.kt +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN - * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -package org.kopi.galite.visual.pivotTable - -import java.time.LocalDate - -import org.kopi.galite.type.format -import org.kopi.galite.util.base.InconsistencyException - -/** - * Represents a report column description - * - * @param ident The column identifier - * @param options The column options as bitmap - * @param align The column alignment - * @param groups The index of the column grouped by this one or -1 - * @param function An (optional) summation function - * @param width The width of the cells - * @param format The format of the cells - */ -class VDateColumn(ident: String?, - options: Int, - align: Int, - groups: Int, - function: VCalculateColumn?, - width: Int, - format: VCellFormat?) - : VReportColumn(ident, - options, - align, - groups, - function, - 10, // width, default date format - 1, - format ?: VDateFormat()) { - /** - * Compare two objects. - * - * @param object1 the first operand of the comparison - * @param object2 the second operand of the comparison - * @return -1 if the first operand is smaller than the second - * 1 if the second operand if smaller than the first - * 0 if the two operands are equal - */ - override fun compareTo(object1: Any, object2: Any): Int = (object1 as LocalDate).compareTo(object2 as LocalDate) - - /** - * Returns the width of cells in this column in characters - */ - override fun getPrintedWidth(): Double = width * 0.7 - - /** - * Default date formatter. - */ - private class VDateFormat : VCellFormat() { - - override fun format(value: Any?): String = - when(value) { - null -> "" - is LocalDate -> value.format() - is java.sql.Date -> value.toLocalDate().format() - else -> throw InconsistencyException("bad type for $value") - } - } -} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VDecimalCodeColumn.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VDecimalCodeColumn.kt deleted file mode 100644 index 6ba645915..000000000 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VDecimalCodeColumn.kt +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN - * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -package org.kopi.galite.visual.pivotTable - -import java.math.BigDecimal - -import org.kopi.galite.util.base.InconsistencyException - -class VDecimalCodeColumn(ident: String?, - type: String?, - source: String?, - options: Int, - align: Int, - groups: Int, - function: VCalculateColumn?, - width: Int, - format: VCellFormat?, - names: Array, - // array of internal representations - private val codes: Array) - : VCodeColumn(ident, - type, - source, - options, - align, - groups, - function, - width, - format, - names) { - /** - * Get the index of the value. - */ - override fun getIndex(value: Any): Int { - for (i in codes.indices) { - if (value == codes[i]) { - return i - } - } - throw InconsistencyException(">>>>$value") - } - - /** - * Returns the width of cells in this column in characters - */ - override fun getPrintedWidth(): Double = width * 0.7 - - /** - * Compares two objects. - * - * @param object1 the first operand of the comparison - * @param object2 the second operand of the comparison - * @return -1 if the first operand is smaller than the second - * 1 if the second operand if smaller than the first - * 0 if the two operands are equal - */ - override fun compareTo(object1: Any, object2: Any): Int = (object1 as BigDecimal) - .compareTo(object2 as BigDecimal) -} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VDecimalColumn.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VDecimalColumn.kt deleted file mode 100644 index f0622e103..000000000 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VDecimalColumn.kt +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN - * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -package org.kopi.galite.visual.pivotTable - -import java.math.BigDecimal - -import org.kopi.galite.visual.form.VDecimalField -import org.kopi.galite.type.format -import org.kopi.galite.util.base.InconsistencyException - -/** - * Represents a report column description - * - * @param ident The column identifier - * @param options The column options as bitmap - * @param align The column alignment - * @param groups The index of the column grouped by this one or -1 - * @param function An (optional) summation function - * @param maxScale The maximum of scale - * @param format The format of the cells - */ -class VDecimalColumn(ident: String?, - options: Int, - align: Int, - groups: Int, - function: VCalculateColumn?, - digits: Int, - maxScale: Int, - format: VCellFormat?) - : VReportColumn(ident, - options, - align, - groups, - function, - VDecimalField.computeWidth(digits, maxScale, null, null), - 1, - format ?: VFixedFormat(maxScale, true)) { - - var formula: String? = null - var maxScale = maxScale - private set - - /** - * Compare two objects. - * - * @param object1 the first operand of the comparison - * @param object2 the second operand of the comparison - * @return -1 if the first operand is smaller than the second - * 1 if the second operand if smaller than the first - * 0 if the two operands are equal - */ - override fun compareTo(object1: Any, object2: Any): Int = - (object1 as BigDecimal).compareTo(object2 as BigDecimal) - - /** - * Returns the width of cells in this column in characters - */ - override fun getPrintedWidth(): Double = width * 0.7 - - /** - * sets all column values to the same scale - */ - private class VFixedFormat(private val maxScale: Int, private val exactScale: Boolean) : VCellFormat() { - - override fun format(value: Any?): String = - when(value) { - null -> "" - is Int -> value.toString() - is BigDecimal -> if ((value).scale() > maxScale || exactScale) (value).setScale(maxScale, java.math.RoundingMode.HALF_UP).format() else value.format() - else -> throw InconsistencyException("bad type for $value") - } - } - - /** - * Sets display scale to maxScale - * all values will be set to the same scale - */ - fun setDisplayScale(scale: Int) { - format = VFixedFormat(scale, true) - maxScale = scale - } - - /** - * Sets maxScale - * all values with scale superior than maxScale will have - * maxScale as scale, and the other values will keep their scale. - */ - fun setMaxScale(scale: Int) { - format = VFixedFormat(scale, false) - maxScale = scale - } -} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VGroupRow.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VGroupRow.kt index cfd49ee5e..23a5b6af1 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VGroupRow.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VGroupRow.kt @@ -43,60 +43,6 @@ class VGroupRow(data: Array, private val level: Int) : VReportRow(data) { return level } - /** - * Returns true if all the child nodes of the level generation are visible. - * - * @param level level to test - */ - fun isUnfolded(level: Int): Boolean { - for (i in 0 until childCount) { - val child = getChildAt(i) as VReportRow - if (child.level > level) { - if ((child as VGroupRow).isUnfolded(level)) { - return true - } - } else { - if (child.visible) { - return true - } - } - } - return false - } - - /** - * Sets child node of the level generation to visible - * - * @param level level to be set visible - */ - fun setChildNodesVisible(level: Int) { - for (i in 0 until childCount) { - val child = getChildAt(i) as VReportRow - child.visible = true - if (getLevel() > level + 1) { - (child as VGroupRow).setChildNodesVisible(level) - } - } - } - - /** - * Sets child node of the level generation to invisible - * - * @param level level to be set visible - */ - fun setChildNodesInvisible(level: Int) { - for (i in 0 until childCount) { - val child = getChildAt(i) as VReportRow - when { - child.level > level -> - (child as VGroupRow).setChildNodesInvisible(level) - child is VGroupRow -> - child.setChildNodesInvisible() - else -> child.visible = false - } - } - } - private fun setChildNodesInvisible() { visible = false if (getLevel() > 0) { diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VHelpGenerator.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VHelpGenerator.kt index 0a446449c..87400c692 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VHelpGenerator.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VHelpGenerator.kt @@ -69,12 +69,6 @@ class VHelpGenerator : VHelpGenerator() { printer.println("") printer.println("") printer.println("
") - for (i in 0 until columnCount) { - val column: VReportColumn = model.getModelColumn(i) - if (column.options and Constants.CLO_HIDDEN == 0) { - column.helpOnColumn(this) - } - } printer.println("
") printer.println("") printer.println("") @@ -98,20 +92,4 @@ class VHelpGenerator : VHelpGenerator() { null } } - - /** - * prints a compilation unit - */ - fun helpOnColumn(label: String?, - help: String?) { - if (label == null) { - return - } - printer.println("
") - printer.println("

$label

") - printer.println("
") - if (help != null) { - printer.println("

$help

") - } - } } diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VIntegerCodeColumn.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VIntegerCodeColumn.kt deleted file mode 100644 index c6da43658..000000000 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VIntegerCodeColumn.kt +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN - * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -package org.kopi.galite.visual.pivotTable - -/** - * Represents a report column description - * - * @param ident The column identifier - * @param options The column options as bitmap - * @param align The column alignment - * @param groups The index of the column grouped by this one or -1 - * @param function An (optional) summation function - * @param width The width of the cells - * @param format The format of the cells - * @param names The names of the cells - * @param codes The codes of the cells, represents an array of internal representations - */ -class VIntegerCodeColumn(ident: String?, - type: String?, - source: String?, - options: Int, - align: Int, - groups: Int, - function: VCalculateColumn?, - width: Int, - format: VCellFormat?, - names: Array, - private var codes: IntArray) - : VCodeColumn(ident, - type, - source, - options, - align, - groups, - function, - width, - format, - names) { - - private var fastIndex = -1 // if array = {fastIndex, fastIndex + 1, ...} - - init { - fastIndex = codes[0] - for (i in 1 until codes.size) { - if (codes[i] != fastIndex + i) { - fastIndex = -1 - break - } - } - } - - /** - * Get the index of the value. - */ - override fun getIndex(value: Any): Int { - if (fastIndex != -1) { - return (value as Int) - fastIndex - } - for (i in codes.indices) { - if ((value as Int) == codes[i]) { - return i - } - } - return -1 - } - - /** - * Returns the width of cells in this column in characters - */ - override fun getPrintedWidth(): Double = width * 0.7 - - /** - * Compares two objects. - * - * @param object1 the first operand of the comparison - * @param object2 the second operand of the comparison - * @return -1 if the first operand is smaller than the second - * 1 if the second operand if smaller than the first - * 0 if the two operands are equal - */ - override fun compareTo(object1: Any, object2: Any): Int { - val v1 = (object1 as Int) - val v2 = (object2 as Int) - - return if (v1 < v2) -1 else if (v1 > v2) 1 else 0 - } -} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VIntegerColumn.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VIntegerColumn.kt deleted file mode 100644 index fd57c20ab..000000000 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VIntegerColumn.kt +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN - * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -package org.kopi.galite.visual.pivotTable - -/** - * Represents a report column description - * - * @param ident The column ident - * @param options The column options as bitmap - * @param align The column alignment - * @param groups The index of the column grouped by this one or -1 - * @param function An (optional) summation function - */ -class VIntegerColumn(ident: String?, - options: Int, - align: Int, - groups: Int, - function: VCalculateColumn?, - width: Int, - format: VCellFormat?) - : VReportColumn(ident, - options, - align, - groups, - function, - width, - 1, - format ?: VIntegerFormat()) { - - /** - * Compare two objects. - * - * @param object1 the first operand of the comparison - * @param object2 the second operand of the comparison - * @return -1 if the first operand is smaller than the second - * 1 if the second operand if smaller than the first - * 0 if the two operands are equal - */ - override fun compareTo(object1: Any, object2: Any): Int { - val v1 = (object1 as Int) - val v2 = (object2 as Int) - - return if (v1 < v2) -1 else if (v1 > v2) 1 else 0 - } - - /** - * Returns the width of cells in this column in characters - */ - override fun getPrintedWidth(): Double = width * 0.7 - - private class VIntegerFormat : VCellFormat() { - override fun format(value: Any?): String { - // don't do substring when value.length() > columnWidth - return value?.toString() ?: "" - } - } -} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VMonthColumn.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VMonthColumn.kt deleted file mode 100644 index aa88dd2fb..000000000 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VMonthColumn.kt +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN - * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.kopi.galite.visual.pivotTable - -import org.kopi.galite.type.Month - -/** - * Represents a report column description - * - * @param ident The column ident - * @param options The column options as bitmap - * @param align The column alignment - * @param groups The index of the column grouped by this one or -1 - * @param function An (optional) summation function - */ -class VMonthColumn(ident: String?, - options: Int, - align: Int, - groups: Int, - function: VCalculateColumn?, - format: VCellFormat?) - : VReportColumn(ident, - options, - align, - groups, - function, - 7, - 1, - format) { - /** - * Compare two objects. - * - * @param object1 the first operand of the comparison - * @param object2 the second operand of the comparison - * @return -1 if the first operand is smaller than the second - * 1 if the second operand if smaller than the first - * 0 if the two operands are equal - */ - override fun compareTo(object1: Any, object2: Any): Int { - return (object1 as Month).compareTo(object2 as Month) - } - - /** - * Returns the width of cells in this column in characters - */ - override fun getPrintedWidth(): Double = width * 0.7 -} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VPivotTable.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VPivotTable.kt index 77da59c70..090f63e41 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VPivotTable.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VPivotTable.kt @@ -21,25 +21,17 @@ package org.kopi.galite.visual.pivotTable import java.awt.event.KeyEvent import java.io.File import java.net.MalformedURLException -import java.text.MessageFormat -import kotlin.jvm.Throws - -import org.jetbrains.annotations.TestOnly import org.kopi.galite.visual.cross.VDynamicReport import org.kopi.galite.visual.dsl.common.Trigger import org.kopi.galite.visual.form.VConstants import org.kopi.galite.visual.l10n.LocalizationManager -import org.kopi.galite.visual.print.Printable -import org.kopi.galite.visual.print.Printable.Companion.DOC_UNKNOWN import org.kopi.galite.util.base.InconsistencyException import org.kopi.galite.visual.ApplicationContext import org.kopi.galite.visual.UIFactory import org.kopi.galite.visual.UWindow import org.kopi.galite.visual.VCommand -import org.kopi.galite.visual.VException import org.kopi.galite.visual.VHelpViewer -import org.kopi.galite.visual.VRuntimeException import org.kopi.galite.visual.VWindow import org.kopi.galite.visual.WindowBuilder import org.kopi.galite.visual.WindowController @@ -52,7 +44,7 @@ abstract class VPivotTable internal constructor() : VWindow(), Constants, VConst init { WindowController.windowController.registerWindowBuilder( - org.kopi.galite.visual.Constants.MDL_REPORT, + org.kopi.galite.visual.Constants.MDL_PIVOT_TABLE, object : WindowBuilder { override fun createWindow(model: VWindow): UWindow { return UIFactory.uiFactory.createView( @@ -66,35 +58,13 @@ abstract class VPivotTable internal constructor() : VWindow(), Constants, VConst // ---------------------------------------------------------------------- // DATA MEMBERS // ---------------------------------------------------------------------- - private var cmdFold: VCommand? = null - private var cmdUnfold: VCommand? = null - private var cmdSort: VCommand? = null - private var cmdOpenLine: VCommand? = null - private var cmdFoldColumn: VCommand? = null - private var cmdUnfoldColumn: VCommand? = null - private var cmdColumnInfo: VCommand? = null - private var cmdEditColumn: VCommand? = null val model: MPivotTable = MPivotTable() private var built = false private var pageTitle = "" - private var firstPageHeader = "" - var VKT_Report_Triggers = mutableListOf>(arrayOfNulls(Constants.TRG_TYPES.size)) - var VKT_Fields_Triggers = mutableListOf>() - var VKT_Commands_Triggers = mutableListOf>() private val activeCommands = ArrayList() - var printOptions: PConfig = PConfig() // The print options - var media: String? = null // The media for this document var help: String? = null - override fun getType() = org.kopi.galite.visual.Constants.MDL_REPORT - - /** - * Redisplay the report after change in formatting - */ - @Deprecated("call method in display; model must not be refreshed") - fun redisplay() { - (getDisplay() as UPivotTable).redisplay() - } + override fun getType() = org.kopi.galite.visual.Constants.MDL_PIVOT_TABLE /** * Close window @@ -105,11 +75,6 @@ abstract class VPivotTable internal constructor() : VWindow(), Constants, VConst } override fun destroyModel() { - try { - callTrigger(Constants.TRG_POSTREPORT) - } catch (v: VException) { - // ignore - } super.destroyModel() } @@ -126,32 +91,15 @@ abstract class VPivotTable internal constructor() : VWindow(), Constants, VConst // localize the report using the default locale localize() model.build() - model.createTree() (getDisplay() as UPivotTable?)?.build() built = true // all commands are by default enabled activeCommands.clear() commands.forEachIndexed { i, vCommand -> - when { - vCommand.getIdent() == "Fold" -> cmdFold = vCommand - vCommand.getIdent() == "Unfold" -> cmdUnfold = vCommand - vCommand.getIdent() == "Sort" -> cmdSort = vCommand - vCommand.getIdent() == "FoldColumn" -> cmdFoldColumn = vCommand - vCommand.getIdent() == "UnfoldColumn" -> cmdUnfoldColumn = vCommand - vCommand.getIdent() == "OpenLine" -> cmdOpenLine = vCommand - vCommand.getIdent() == "ColumnInfo" -> cmdColumnInfo = vCommand - vCommand.getIdent() == "EditColumnData" -> cmdEditColumn = vCommand - else -> { - setCommandEnabled(vCommand, i, true) - } - } + setCommandEnabled(vCommand, true) } } - - fun columnMoved(pos: IntArray) { - (getDisplay() as UPivotTable).columnMoved(pos) - } // ---------------------------------------------------------------------- // LOCALIZATION // ---------------------------------------------------------------------- @@ -187,38 +135,10 @@ abstract class VPivotTable internal constructor() : VWindow(), Constants, VConst // ---------------------------------------------------------------------- open fun initReport() { build() - callTrigger(Constants.TRG_PREREPORT) } // ---------------------------------------------------------------------- // INTERFACE (COMMANDS) // ---------------------------------------------------------------------- - /** - * Enables/disables the actor. - */ - fun setCommandEnabled(command: VCommand, index: Int, enable: Boolean) { - @Suppress("NAME_SHADOWING") - var enable = enable - - if (enable) { - // we need to check if VKT_Triggers is not empty - // ex : org.kopi.galite.visual.cross.VDynamicReport - if (VKT_Commands_Triggers.isNotEmpty() && hasCommandTrigger(Constants.TRG_CMDACCESS, index)) { - - val active: Boolean = try { - callCommandTrigger(Constants.TRG_CMDACCESS, index) as Boolean - } catch (e: VException) { - // trigger call error ==> command is considered as active - true - } - enable = active - } - command.setEnabled(enable) - activeCommands.add(command) - } else { - activeCommands.remove(command) - command.setEnabled(false) - } - } /** * Enables/disables the actor. @@ -241,148 +161,10 @@ abstract class VPivotTable internal constructor() : VWindow(), Constants, VConst setTitle(title) } - fun setPageTitleParams(param: Any) { - setPageTitleParams(arrayOf(param)) - } - - fun setPageTitleParams(param1: Any, param2: Any) { - setPageTitleParams(arrayOf(param1, param2)) - } - - fun setPageTitleParams(params: Array) { - setPageTitle(MessageFormat.format(pageTitle, *params)) - } - - fun setFirstPageHeader(firstPageHeader: String) { - this.firstPageHeader = firstPageHeader - } - fun getColumn(i: Int): VReportColumn { return model.getModelColumn(i) } - fun foldSelection() { - val column = getSelectedColumn() - - if (column != -1) { - model.foldingColumn(column) - } else { - val (x, y) = getSelectedCell() - if (y != -1 && x != -1) { - model.foldingRow(y, x) - } - } - setMenu() - } - - fun unfoldSelection() { - val column = getSelectedColumn() - - if (column != -1) { - model.unfoldingColumn(column) - } else { - val (x, y) = getSelectedCell() - if (y != -1 && x != -1) { - model.unfoldingRow(y, x) - } - } - setMenu() - } - - fun foldSelectedColumn() { - val column = getSelectedColumn() - - if (column != -1) { - model.setColumnFolded(column, true) - } - (getDisplay() as UPivotTable).resetWidth() - setMenu() - } - - fun unfoldSelectedColumn() { - val column = getSelectedColumn() - - if (column != -1) { - model.setColumnFolded(column, false) - } - (getDisplay() as UPivotTable).resetWidth() - setMenu() - } - - /** - * Sort the displayed tree wrt to a column - */ - fun sortSelectedColumn() { - model.sortColumn(getSelectedColumn()) - } - - /** - * Sort the displayed tree wrt to a column - */ - @Throws(VException::class) - fun editLine() { - if (cmdOpenLine != null) { - cmdOpenLine!!.action.invoke() - } - } - - @Throws(VException::class) - fun setColumnData() { - if (cmdEditColumn != null) { - cmdEditColumn!!.action.invoke() - } - } - - @Throws(VException::class) - fun setColumnInfo() { - if (cmdColumnInfo != null) { - cmdColumnInfo!!.action.invoke() - } - } - - /** - * Returns the ID - */ - fun getValueOfFieldId(): Int { - var idCol = -1 - var id = -1 - var i = 0 - - while (i < model.getModelColumnCount() && idCol == -1) { - if (model.getModelColumn(i).ident == "ID") { - idCol = i - } - i++ - } - if (idCol != -1 && getSelectedCell().y != -1) { - id = (model.getRow(getSelectedCell().y)?.getValueAt(idCol) as Int) - } - return if (id == -1) { - throw VRuntimeException() - } else { - id - } - } - - /** - * Return the value of a field in the selected row - * by passing its name(key) - */ - fun getValueOfField(key: Any): Any? { - var col = -1 - var i = 0 - - while (i < model.getModelColumnCount() && col == -1) { - if (model.getModelColumn(i).ident == key) { - col = i - } - i++ - } - return if (col != -1 && getSelectedCell().y != -1) { - model.getRow(getSelectedCell().y)?.getValueAt(col) - } else null - } - // ---------------------------------------------------------------------- // PRIVATE METHODS // ---------------------------------------------------------------------- @@ -390,116 +172,12 @@ abstract class VPivotTable internal constructor() : VWindow(), Constants, VConst trigger?.action?.method?.invoke() } - open fun executeObjectTrigger(trigger: Trigger?): Any = throw InconsistencyException("SHOULD BE REDEFINED") - - fun executeBooleanTrigger(trigger: Trigger?): Boolean = throw InconsistencyException("SHOULD BE REDEFINED") - - fun executeIntegerTrigger(trigger: Trigger?): Int = throw InconsistencyException("SHOULD BE REDEFINED") - - fun getDocumentType(): Int = DOC_UNKNOWN - - /** - * overridden by forms to implement triggers - * default triggers - */ - protected fun execTrigger(block: Any, trigger: Trigger?): Any? { - executeVoidTrigger(trigger) - return null - } - - /** - * Calls trigger for given event, returns last trigger called 's value. - */ - internal fun callCommandTrigger(event: Int, index: Int): Any? { - return callTrigger(event, index, VKT_Commands_Triggers) - } - - /** - * Calls trigger for given event, returns last trigger called 's value. - */ - internal fun callTrigger(event: Int): Any? { - return callTrigger(event, 0, VKT_Report_Triggers) - } - - /** - * Calls trigger for given event, returns last trigger called 's value. - */ - internal fun callFieldTrigger(event: Int, index: Int): Any? { - return callTrigger(event, index, VKT_Fields_Triggers) - } - - /** - * Calls trigger for given event, returns last trigger called 's value. - */ - private fun callTrigger(event: Int, index: Int, triggers: List>): Any? { - return when (Constants.TRG_TYPES[event]) { - Constants.TRG_VOID -> { - executeVoidTrigger(triggers[index][event]) - null - } - Constants.TRG_OBJECT -> executeObjectTrigger(triggers[index][event]) - Constants.TRG_BOOLEAN -> executeBooleanTrigger(triggers[index][event]) - else -> throw InconsistencyException("BAD TYPE" + Constants.TRG_TYPES[event]) - } - } - - /** - * Returns true if there is trigger associated with given event. - */ - internal fun hasTrigger(event: Int): Boolean = VKT_Report_Triggers[0][event] != null - - /** - * Returns true if there is trigger associated with given event. - */ - internal fun hasCommandTrigger(event: Int, index: Int): Boolean = VKT_Commands_Triggers[index][event] != null - fun setMenu() { if (!built) { // only when commands are displayed return } - val column = getSelectedColumn() - val (x, y) = getSelectedCell() - val foldEnabled = column != -1 && !model.isColumnFold(column) || x != -1 && y != -1 && !model.isRowFold(y, x) - val unfoldEnabled = column != -1 || x != -1 && y != -1 - - if (cmdFold != null) { - setCommandEnabled(cmdFold!!, foldEnabled) - } - if (cmdUnfold != null) { - setCommandEnabled(cmdUnfold!!, unfoldEnabled) - } - if (cmdSort != null) { - setCommandEnabled(cmdSort!!, column != -1) - } - if (cmdOpenLine != null) { - setCommandEnabled(cmdOpenLine!!, model.isRowLine(y)) - } - if (cmdFoldColumn != null) { - setCommandEnabled(cmdFoldColumn!!, column != -1) - } - if (cmdUnfoldColumn != null) { - setCommandEnabled(cmdUnfoldColumn!!, column != -1) - } - if (cmdColumnInfo != null) { - setCommandEnabled(cmdColumnInfo!!, column != -1) - } - if (cmdEditColumn != null) { - setCommandEnabled(cmdEditColumn!!, column != -1 && model.getAccessibleColumn(column)!!.isAddedAtRuntime) - } } - // ---------------------------------------------------------------------- - // IMPLEMENTATION - // ---------------------------------------------------------------------- - /** - * Returns the selected column or -1 if no column is selected. - */ - private fun getSelectedColumn(): Int = (getDisplay() as UPivotTable).getSelectedColumn() - - /** - * Returns the selected cell or !!! ??? if no cell is selected. - */ - private fun getSelectedCell(): Point = (getDisplay() as UPivotTable).getSelectedCell() // ---------------------------------------------------------------------- // HELP @@ -536,15 +214,6 @@ abstract class VPivotTable internal constructor() : VWindow(), Constants, VConst private fun initDefaultActors() { addActors(arrayOf( VDefaultReportActor("File", "Quit", VDynamicReport.QUIT_ICON, KeyEvent.VK_ESCAPE, 0), - VDefaultReportActor("File", "Print", VDynamicReport.PRINT_ICON, KeyEvent.VK_F6, 0), - VDefaultReportActor("File", "ExportCSV", VDynamicReport.EXPORT_ICON, KeyEvent.VK_F8, 0), - VDefaultReportActor("File", "ExportXLSX", VDynamicReport.EXPORT_ICON, KeyEvent.VK_F9, KeyEvent.SHIFT_MASK), - VDefaultReportActor("File", "ExportPDF", VDynamicReport.EXPORT_ICON, KeyEvent.VK_F9, 0), - VDefaultReportActor("Action", "Fold", VDynamicReport.FOLD_ICON, KeyEvent.VK_F2, 0), - VDefaultReportActor("Action", "Unfold", VDynamicReport.UNFOLD_ICON, KeyEvent.VK_F3, 0), - VDefaultReportActor("Action", "FoldColumn", VDynamicReport.FOLD_COLUMN_ICON, KeyEvent.VK_UNDEFINED, 0), - VDefaultReportActor("Action", "UnfoldColumn", VDynamicReport.UNFOLD_COLUMN_ICON, KeyEvent.VK_UNDEFINED, 0), - VDefaultReportActor("Action", "Sort", VDynamicReport.SERIALQUERY_ICON, KeyEvent.VK_F4, 0), VDefaultReportActor("Help", "Help", VDynamicReport.HELP_ICON, KeyEvent.VK_F1, 0), )) } @@ -554,7 +223,4 @@ abstract class VPivotTable internal constructor() : VWindow(), Constants, VConst commands.add(VCommand(VConstants.MOD_ANY, this, vActor, index, vActor.ident)) } } - - @TestOnly - fun _hasTrigger(event: Int): Boolean = hasTrigger(event) } diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VReportColumn.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VReportColumn.kt index 218bc01db..5abd23b25 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VReportColumn.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VReportColumn.kt @@ -26,23 +26,10 @@ import org.kopi.galite.visual.util.LineBreaker * Represents a report column description * * @param ident The identifier of the field - * @param options The column options as bitmap - * @param align The column alignment - * @param groups The index of the column grouped by this one or -1 - * @param function An (optional) function - * @param width The width of a cell in characters - * @param height The height of a cell in characters - * @param format format of the cells + * */ -abstract class VReportColumn( - val ident: String?, - val options: Int, - val align: Int, - var groups: Int, - val function: VCalculateColumn?, - var width: Int, - var height: Int, - protected var format: VCellFormat?) { +class VReportColumn( + val ident: String?) { // ---------------------------------------------------------------------- // DATA MEMBERS @@ -52,55 +39,7 @@ abstract class VReportColumn( var isVisible: Boolean = true open var isFolded: Boolean = false var isAddedAtRuntime: Boolean = false - var userDefinedLabel: Boolean = false - private var styles: Array? = null - - /** - * Returns true if this Column is hidden - */ - open fun isHidden(): Boolean { - return options and Constants.CLO_HIDDEN > 0 - } - - /** - * Returns the width of cells in this column in characters - */ - open fun getPrintedWidth(): Double { - return width.toDouble() - } - - open fun format(o: Any?): String { - return if (isFolded || o == null) { - "" - } else if (format != null) { - format!!.format(o) - } else if (height == 1) { - val str = o.toString() - val strLength = str.length - if (strLength <= width) str else str.substring(0, width) - } else { - o.toString() - } - } - fun formatWithLineBreaker(o: Any?): String { - return LineBreaker.modelToText(format(o), width) - } - - /** - * Compare two objects. - * - * @param object1 the first operand of the comparison - * @param object2 the second operand of the comparison - * @return -1 if the first operand is smaller than the second - * 1 if the second operand if smaller than the first - * 0 if the two operands are equal - */ - abstract fun compareTo(object1: Any, object2: Any): Int - - fun helpOnColumn(help: VHelpGenerator) { - help.helpOnColumn(label, this.help) - } // ---------------------------------------------------------------------- // LOCALIZATION // ---------------------------------------------------------------------- @@ -110,7 +49,7 @@ abstract class VReportColumn( * @param parent the caller localizer */ fun localize(parent: ReportLocalizer) { - if (!isHidden() && ident != "") { + if (ident != "") { val loc: FieldLocalizer = parent.getFieldLocalizer(ident!!) label = loc.getLabel() ?: "" @@ -127,20 +66,4 @@ abstract class VReportColumn( protected open fun localize(parentLocalizer: FieldLocalizer) { // by default nothing to do } - - fun getStyles(): Array { - return if (styles == null) { - val style = ColumnStyle() - style.fontName = 0 - style.backgroundCode = Constants.CLR_WHITE - style.foregroundCode = Constants.CLR_BLACK - arrayOf(style) - } else { - styles!! - } - } - - fun setStyles(styles: Array) { - this.styles = styles - } } diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VReportCommand.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VReportCommand.kt deleted file mode 100644 index 217da3460..000000000 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VReportCommand.kt +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN - * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -package org.kopi.galite.visual.pivotTable - -import org.kopi.galite.visual.dsl.common.Trigger -import org.kopi.galite.visual.print.DefaultPrintManager -import org.kopi.galite.visual.print.PrintManager -import org.kopi.galite.visual.Action -import org.kopi.galite.visual.ActionHandler -import org.kopi.galite.visual.PrinterManager -import org.kopi.galite.visual.VActor -import org.kopi.galite.visual.VCommand -import org.kopi.galite.visual.VHelpGenerator - -class VReportCommand( - val report: VPivotTable, - actor: VActor -) : VCommand(0xFFFF, null, actor, actor.number, actor.ident), ActionHandler { - - override fun setEnabled(enabled: Boolean) { - if (actor != null) { - actor!!.isEnabled = enabled - actor!!.number = trigger - actor!!.handler = this - } - } - - /** - * Performs the appropriate action asynchronously. - * You can use this method to perform any operation out of the UI event process - * - * @param action the action to perform. - * @param block This action should block the UI thread ? - */ - @Deprecated("use method performAsyncAction", ReplaceWith("performAsyncAction(action, block)")) - override fun performAction(action: Action, block: Boolean) { - report.performAsyncAction(action) - /*try { - executeVoidTrigger(getTrigger()); - } catch (Exception e) { - e.printStackTrace(); - }*/ - } - - /** - * Performs the appropriate action asynchronously. - * You can use this method to perform any operation out of the UI event process - * - * @param action the action to perform. - */ - override fun performAsyncAction(action: Action) { - report.performAsyncAction(action) - /*try { - executeVoidTrigger(getTrigger()); - } catch (Exception e) { - e.printStackTrace(); - }*/ - } - - /** - * Performs a void trigger - * - * @param VKT_Type the number of the trigger - */ - override fun executeVoidTrigger(VKT_Type: Int) { - when (VKT_Type) { - Constants.CMD_QUIT -> report.close() - Constants.CMD_FOLD -> report.foldSelection() - Constants.CMD_UNFOLD -> report.unfoldSelection() - Constants.CMD_SORT -> report.sortSelectedColumn() - Constants.CMD_FOLD_COLUMN -> report.foldSelectedColumn() - Constants.CMD_UNFOLD_COLUMN -> report.unfoldSelectedColumn() - Constants.CMD_HELP -> report.showHelp() - } - } - - /** - * Performs a void trigger - * - * @param trigger the trigger - */ - override fun executeVoidTrigger(trigger: Trigger?) { - // DO NOTHING ! - } - - // ---------------------------------------------------------------------- - // HELP HANDLING - // ---------------------------------------------------------------------- - override fun helpOnCommand(help: VHelpGenerator) { - if (actor == null) { - return - } - actor!!.helpOnCommand(help) - } - -} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VReportRow.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VReportRow.kt index e8af5c565..f038a3fb6 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VReportRow.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VReportRow.kt @@ -54,27 +54,6 @@ abstract class VReportRow(val data: Array) : DefaultMutableTreeNode() { */ fun cloneArray() = data.clone() - /** - * Compare two VReportRows within specified column - * - * @param other Report row to compare to - * @param position position in data - * @param column - * @return - */ - fun compareTo(other: VReportRow, position: Int, column: VReportColumn): Int { - val data = data[position] - val rowData = other.data[position] - - // check for nulls: define null less than everything - return when { - data == null && rowData == null -> 0 - data == null -> -1 - rowData == null -> 1 - else -> column.compareTo(data, rowData) - } - } - companion object { private const val serialVersionUID = 0L } diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VSeparatorColumn.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VSeparatorColumn.kt deleted file mode 100644 index 48cc374da..000000000 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VSeparatorColumn.kt +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN - * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -package org.kopi.galite.visual.pivotTable - -/** - * Represents a report column description - * - * @param ident The column identifier - * @param options The column options as bitmap - * @param align The column alignment - * @param groups The index of the column grouped by this one or -1 - * @param function An (optional) summation function - */ -class VSeparatorColumn: VReportColumn("", 0, 0, 0, null, 1, 1, null) { - /** - * No text here - */ - override fun format(o: Any?): String { - return "" - } - - /** - * Compare two objects. - * - * @param object1 the first operand of the comparison - * @param object2 the second operand of the comparison - * @return -1 if the first operand is smaller than the second - * 1 if the second operand if smaller than the first - * 0 if the two operands are equal - */ - override fun compareTo(object1: Any, object2: Any): Int { - return 0 - } - - /** - * Returns the visibility of the column - */ - override var isFolded: Boolean = false - get() = true -} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VStringCodeColumn.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VStringCodeColumn.kt deleted file mode 100644 index 050b9e874..000000000 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VStringCodeColumn.kt +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN - * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -package org.kopi.galite.visual.pivotTable - -import org.kopi.galite.util.base.InconsistencyException - -/** - * Represents a report column description - * - * @param ident The column ident - * @param options The column options as bitmap - * @param align The column alignment - * @param groups The index of the column grouped by this one or -1 - * @param function An (optional) summation function - */ -class VStringCodeColumn(ident: String?, - type: String?, - source: String?, - options: Int, - align: Int, - groups: Int, - function: VCalculateColumn?, - width: Int, - format: VCellFormat?, - names: Array, - private val codes: Array) - : VCodeColumn(ident, - type, - source, - options, - align, - groups, - function, - width, - format, - names) { - - /** - * Get the index of the value. - */ - override fun getIndex(value: Any): Int { - codes.forEachIndexed { index, code -> - if (value == code) { - return index - } - } - throw InconsistencyException(">>>>$value") - } - - /** - * Returns the width of cells in this column in characters - */ - override fun getPrintedWidth(): Double = width * 0.7 - - /** - * Compares two objects. - * - * @param object1 the first operand of the comparison - * @param object2 the second operand of the comparison - * @return -1 if the first operand is smaller than the second - * 1 if the second operand if smaller than the first - * 0 if the two operands are equal - */ - override fun compareTo(object1: Any, object2: Any): Int { - return (object1 as String).compareTo((object2 as String)) - } -} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VStringColumn.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VStringColumn.kt deleted file mode 100644 index f158104c6..000000000 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VStringColumn.kt +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN - * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -package org.kopi.galite.visual.pivotTable - -/** - * Represents a report column description - * - * @param ident The column ident - * @param options The column options as bitmap - * @param align The column alignment - * @param groups The index of the column grouped by this one or -1 - * @param function An (optional) summation function - */ -class VStringColumn(ident: String?, - options: Int, - align: Int, - groups: Int, - function: VCalculateColumn?, - width: Int, - height: Int, - format: VCellFormat?) - : VReportColumn(ident, - options, - align, - groups, - function, - width, - height, - format) { - - /** - * Compare two objects. - * - * @param object1 the first operand of the comparison - * @param object2 the second operand of the comparison - * @return -1 if the first operand is smaller than the second - * 1 if the second operand if smaller than the first - * 0 if the two operands are equal - */ - override fun compareTo(object1: Any, object2: Any): Int = (object1 as String).compareTo((object2 as String)) -} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VTimeColumn.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VTimeColumn.kt deleted file mode 100644 index 98db3c070..000000000 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VTimeColumn.kt +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN - * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -package org.kopi.galite.visual.pivotTable - -import java.sql.Time -import java.time.LocalTime - -import org.kopi.galite.type.format -import org.kopi.galite.util.base.InconsistencyException - -/** - * Represents a report column description - * - * @param ident The column ident - * @param options The column options as bitmap - * @param align The column alignment - * @param groups The index of the column grouped by this one or -1 - * @param function An (optional) summation function - */ -class VTimeColumn(ident: String?, - options: Int, - align: Int, - groups: Int, - function: VCalculateColumn?, - format: VCellFormat?) - : VReportColumn(ident, - options, - align, - groups, - function, - 5, // width, default time format - 1, - format ?: VTimeFormat()) { - /** - * Compares two objects. - * - * @param object1 the first operand of the comparison - * @param object2 the second operand of the comparison - * @return -1 if the first operand is smaller than the second - * 1 if the second operand if smaller than the first - * 0 if the two operands are equal - */ - override fun compareTo(object1: Any, object2: Any): Int { - return (object1 as LocalTime).compareTo(object2 as LocalTime) - } - - /** - * Returns the width of cells in this column in characters - */ - override fun getPrintedWidth(): Double = width * 0.7 - - /** - * Default time formatter. - */ - private class VTimeFormat : VCellFormat() { - - override fun format(value: Any?): String = - when(value) { - null -> "" - is LocalTime -> value.format() - is Time -> value.toLocalTime().format() - else -> throw InconsistencyException("bad type for $value") - } - } -} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VTimestampColumn.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VTimestampColumn.kt deleted file mode 100644 index 52b0b14d0..000000000 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VTimestampColumn.kt +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN - * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -package org.kopi.galite.visual.pivotTable - -import java.time.Instant -import java.time.LocalDateTime - -import org.kopi.galite.type.format -import org.kopi.galite.util.base.InconsistencyException - -/** - * Represents a report column description - * - * @param ident The column ident - * @param options The column options as bitmap - * @param align The column alignment - * @param groups The index of the column grouped by this one or -1 - * @param function An (optional) summation function - */ -class VTimestampColumn(ident: String?, - options: Int, - align: Int, - groups: Int, - function: VCalculateColumn?, - format: VCellFormat?) - : VReportColumn(ident, - options, - align, - groups, - function, - 10 + 1 + 8, // width, default timestamp format (date + space + time) - 1, - format ?: VTimestampFormat()) { - /** - * Compares two objects. - * - * @param object1 the first operand of the comparison - * @param object2 the second operand of the comparison - * @return -1 if the first operand is smaller than the second - * 1 if the second operand if smaller than the first - * 0 if the two operands are equal - */ - override fun compareTo(object1: Any, object2: Any): Int { - return (object1 as Instant).compareTo(object2 as Instant) - } - - /** - * Returns the width of cells in this column in characters - */ - override fun getPrintedWidth(): Double = width * 0.7 - - /** - * Default timestamp formatter. - */ - private class VTimestampFormat : VCellFormat() { - - override fun format(value: Any?): String = - when(value) { - null -> "" - is Instant -> value.format() - is LocalDateTime -> value.format() - else -> throw InconsistencyException("bad type for $value") - } - } -} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VWeekColumn.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VWeekColumn.kt deleted file mode 100644 index 99bf14bf4..000000000 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VWeekColumn.kt +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN - * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -package org.kopi.galite.visual.pivotTable - -import org.kopi.galite.type.Week - -/** - * Represents a report column description - * - * @param ident The column ident - * @param options The column options as bitmap - * @param align The column alignment - * @param groups The index of the column grouped by this one or -1 - * @param function An (optional) summation function - */ -class VWeekColumn(ident: String?, - options: Int, - align: Int, - groups: Int, - function: VCalculateColumn?, - format: VCellFormat?) - : VReportColumn(ident, - options, - align, - groups, - function, - 7, // width, default week format - 1, - format) { - /** - * Compare two objects. - * - * @param object1 the first operand of the comparison - * @param object2 the second operand of the comparison - * @return -1 if the first operand is smaller than the second - * 1 if the second operand if smaller than the first - * 0 if the two operands are equal - */ - override fun compareTo(object1: Any, object2: Any): Int = (object1 as Week).compareTo(object2 as Week) - - /** - * Returns the width of cells in this column in characters - */ - override fun getPrintedWidth(): Double = width * 0.7 -} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/triggers/Triggers.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/triggers/Triggers.kt deleted file mode 100644 index 890095228..000000000 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/triggers/Triggers.kt +++ /dev/null @@ -1,286 +0,0 @@ -/* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN - * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -package org.kopi.galite.visual.report.triggers - -import java.math.BigDecimal - -import org.kopi.galite.visual.dsl.report.ReportField -import org.kopi.galite.visual.report.VBaseRow -import org.kopi.galite.visual.report.VCCDepthFirstCircuitN -import org.kopi.galite.visual.report.VCalculateColumn -import org.kopi.galite.visual.report.VGroupRow -import org.kopi.galite.visual.report.VReportRow - -/////////////////////////////////////////////////////////////////////////// -// This file regroups predefined report triggers -/////////////////////////////////////////////////////////////////////////// - -/** - * Compute the integer sum in a report column - */ -fun ReportField.sumInteger(): VCalculateColumn { - - return object : VCCDepthFirstCircuitN() { - - override fun evalNode(row: VReportRow, column: Int): Any { - val childCount = row.childCount - var result = 0 - - for (i in 0 until childCount) { - val child = row.getChildAt(i) as VReportRow - val value = child.getValueAt(column) as Int? - - if (value != null) { - result += value - } - } - return result - } - } -} - -/** - * Compute the number of entries in a report column - */ -fun ReportField.countInteger(): VCalculateColumn { - return object : VCCDepthFirstCircuitN() { - override fun evalNode(row: VReportRow, column: Int): Any { - val childCount = row.childCount - - return if (row.level > 1) { - // the value of a node is the sum of - // other nodes (contain no leafs) - var result = 0 - - for (i in 0 until childCount) { - val child = row.getChildAt(i) as VReportRow - val value = child.getValueAt(column) as Int? - - if (value != null) { - result += value - } - } - result - } else { - // the value is the number of the children - // if the children are leafs - childCount - } - } - } -} - -/** - * Compute the decimal sum in a report column - */ -fun ReportField.sumDecimal(): VCalculateColumn { - return object : VCCDepthFirstCircuitN() { - override fun evalNode(row: VReportRow, column: Int): Any { - val childCount = row.childCount - var result = BigDecimal.valueOf(0, 2) - - for (i in 0 until childCount) { - val child = row.getChildAt(i) as VReportRow - val value = child.getValueAt(column) as? BigDecimal - - if (value != null) { - result += value - } - } - return result - } - } -} - -/** - * Compute the integer sum in a report column - */ -fun ReportField.sumNullInteger(): VCalculateColumn where T: Comparable, T: Number { - return object : VCCDepthFirstCircuitN() { - override fun evalNode(row: VReportRow, column: Int): Any? { - val childCount = row.childCount - var result = 0 - var valueFound = false - - for (i in 0 until childCount) { - val child = row.getChildAt(i) as VReportRow - val value = child.getValueAt(column) as Int? - - if (value != null) { - valueFound = true - result += value - } - } - return if (valueFound) result else null - } - } -} - -/** - * Compute the decimal sum in a report column - */ -fun ReportField.sumNullDecimal(): VCalculateColumn { - return object : VCCDepthFirstCircuitN() { - override fun evalNode(row: VReportRow, column: Int): Any? { - val childCount = row.childCount - var valueFound = false - var result = BigDecimal.valueOf(0, 2) - - for (i in 0 until childCount) { - val child = row.getChildAt(i) as VReportRow - val value = child.getValueAt(column) as? BigDecimal - - if (value != null) { - valueFound = true - result += value - } - } - return if (valueFound) result else null - } - } -} - -/** - * Report a value when all child are identical - */ -fun ReportField<*>.reportIdenticalValue(): VCalculateColumn { - return object : VCCDepthFirstCircuitN() { - override fun evalNode(row: VReportRow, column: Int): Any? { - val childCount = row.childCount - val value = (row.getChildAt(0) as VReportRow).getValueAt(column) - - return if (value == null) { - null - } else { - for (i in 1 until childCount) { - val child = row.getChildAt(i) as VReportRow - - if (value != child.getValueAt(column)) { - return null - } - } - value - } - } - } -} - -/** - * Compute the integer average in a report column - */ -fun ReportField.avgInteger(): VCalculateColumn where T: Comparable, T: Number { - return object : VCCDepthFirstCircuitN() { - override fun evalNode(row: VReportRow, column: Int): Any { - val childCount = row.childCount - var result = 0 - - for (i in 0 until childCount) { - val child = row.getChildAt(i) as VReportRow - val value = child.getValueAt(column) as Int? - - if (value != null) { - result += value - } - } - return result / childCount - } - } -} - -/** - * Compute the integer sum in a report column and the the value - * in the leaves with a serial number - */ -fun ReportField.serialInteger(): VCalculateColumn where T: Comparable, T: Number { - return object : VCCDepthFirstCircuitN() { - override fun evalNode(row: VReportRow, column: Int): Any { - val childCount = row.childCount - - return if (row.level > 1) { - // the value of a node is the sum of - // other nodes (contain no leafs) - var result = 0 - - for (i in 0 until childCount) { - val child = row.getChildAt(i) as VReportRow - val value = child.getValueAt(column) as Int? - - if (value != null) { - result += value - } - } - result - } else { - // the value is the number of the children - // if the children are leafs - childCount - } - } - - /** - * Add calculated data into the report row - */ - override fun calculate(tree: VGroupRow, column: Int) { - if (tree.level > 1) { - val childCount = tree.childCount - - for (i in 0 until childCount) { - calculate(tree.getChildAt(i) as VGroupRow, column) - } - } else { - val childCount = tree.childCount - - for (i in 0 until childCount) { - // set leave to serial number - (tree.getChildAt(i) as VBaseRow).setValueAt(column, i + 1) - } - } - tree.setValueAt(column, evalNode(tree, column)) - } - } -} - -/** - * Compute the decimal average in a report column - */ -fun ReportField.avgDecimal(): VCalculateColumn { - return object : VCCDepthFirstCircuitN() { - override fun evalNode(row: VReportRow, column: Int): Any { - val leafCount = row.leafCount - var notNullLeafCount = 0.0 - var result = BigDecimal.valueOf(0, 2) - var leaf = row.firstLeaf as? VReportRow - - for (i in 0 until leafCount) { - val value = leaf!!.getValueAt(column) as? BigDecimal - - if (value != null) { - result += value - notNullLeafCount++ - } - leaf = leaf.nextLeaf as? VReportRow - } - return if (notNullLeafCount != 0.0) { - (result / BigDecimal(notNullLeafCount)).setScale(2) - } else { - BigDecimal.valueOf(0, 2) - } - } - } -} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/ColumnStyleGenerator.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/ColumnStyleGenerator.kt deleted file mode 100644 index 4a09eb509..000000000 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/ColumnStyleGenerator.kt +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN - * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.kopi.galite.visual.ui.vaadin.pivotTable - -import org.kopi.galite.visual.pivotTable.MPivotTable -import org.kopi.galite.visual.pivotTable.VReportColumn -import org.kopi.galite.visual.pivotTable.VSeparatorColumn - -import com.vaadin.flow.function.SerializableFunction - -/** - * The `ColumnStyleGenerator` is the dynamic report - * implementation for generating CSS class names for - * cells in the column [column]. - * - * @param model The report model. - */ -class ColumnStyleGenerator(private val model: MPivotTable, val column: VReportColumn) : SerializableFunction { - - //--------------------------------------------------- - // IMPLEMENTATIONS - //--------------------------------------------------- - override fun apply(item: DPivotTable.ReportModelItem): String = - buildString { - if (item.rowIndex == model.getRowCount() - 1) { - append("last-row") - } - - if (column is VSeparatorColumn) { - append(" separator") - } else { - append(" level-" + model.getRow(item.rowIndex)!!.level) - } - } -} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/ColumnsSelector.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/ColumnsSelector.kt deleted file mode 100644 index 8c81984cc..000000000 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/ColumnsSelector.kt +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN - * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.kopi.galite.visual.ui.vaadin.pivotTable - -import com.vaadin.flow.component.checkbox.Checkbox -import com.vaadin.flow.component.contextmenu.ContextMenu -import com.vaadin.flow.component.dependency.CssImport -import com.vaadin.flow.component.html.Div -import com.vaadin.flow.component.icon.Icon -import com.vaadin.flow.component.icon.VaadinIcon - -@CssImport(value = "./styles/galite/columnselector.css") -class ColumnsSelector : Div() { - private val contextMenu = ContextMenu() - private val icon: Icon = Icon(VaadinIcon.ANGLE_DOUBLE_RIGHT) - - init { - contextMenu.target = icon - contextMenu.isOpenOnClick = true - className = "columns-selector" - icon.className = "columns-selector-button" - icon.setSize("1em") - - add(icon, contextMenu) - } - - fun build(table: DTable) { - contextMenu.removeAll() - - table.viewColumns.forEach { - val checkbox = Checkbox(table.model.model.columns[it]?.label) - val column = table.getColumnByKey(it.toString()) - - checkbox.className = "checkbox-selector" - checkbox.value = column.isVisible - checkbox.addValueChangeListener { e -> - column.isVisible = e.value - table.model.model.columns[it]?.isVisible = e.value - } - val item = contextMenu.addItem(checkbox) - - item.element.setAttribute("onClick", "event.stopPropagation()") - item.element.classList.add("column-item-selector") - } - } -} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/DPivotTable.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/DPivotTable.kt index da5ad550e..0e31d84a0 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/DPivotTable.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/DPivotTable.kt @@ -20,55 +20,25 @@ package org.kopi.galite.visual.ui.vaadin.pivotTable import java.awt.Color import org.kopi.galite.visual.pivotTable.MPivotTable -import org.kopi.galite.visual.pivotTable.Parameters -import org.kopi.galite.visual.pivotTable.Point import org.kopi.galite.visual.pivotTable.UPivotTable import org.kopi.galite.visual.pivotTable.VPivotTable -import org.kopi.galite.visual.pivotTable.VReportRow -import org.kopi.galite.visual.pivotTable.VSeparatorColumn -import org.kopi.galite.visual.ui.vaadin.base.BackgroundThreadHandler.access -import org.kopi.galite.visual.ui.vaadin.base.BackgroundThreadHandler.accessAndPush import org.kopi.galite.visual.ui.vaadin.visual.DWindow -import org.kopi.galite.visual.Action -import org.kopi.galite.visual.VException -import org.kopi.galite.visual.VlibProperties -import com.vaadin.flow.component.Unit -import com.vaadin.flow.component.contextmenu.ContextMenu -import com.vaadin.flow.component.grid.Grid -import com.vaadin.flow.component.html.Span -import com.vaadin.flow.component.orderedlayout.VerticalLayout import org.vaadin.addons.componentfactory.PivotTable -import org.kopi.galite.visual.ui.vaadin.report.VTable - -/** - * The `DReport` is the visual part of the [VReport] model. - * - * The `DReport` ensure the implementation of the [UReport] - * specifications. - * - * @param report The report model. - */ class DPivotTable(private val report: VPivotTable) : DWindow(report), UPivotTable { //--------------------------------------------------- // DATA MEMBERS //--------------------------------------------------- private val model: MPivotTable = report.model // report model - private lateinit var table: DTable - private var parameters: Parameters? = null - private var columnsSelector: ColumnsSelector = ColumnsSelector() private var pivotData = PivotTable.PivotData() private var pivotOptions = PivotTable.PivotOptions() private var listeRows = mutableListOf() init { - model.addReportListener(this) getModel()!!.setDisplay(this) setSizeFull() - - add(columnsSelector) } //--------------------------------------------------- @@ -77,17 +47,13 @@ class DPivotTable(private val report: VPivotTable) : DWindow(report), UPivotTabl override fun run() { report.initReport() report.setMenu() - table.focus() - setInfoTable() } override fun build() { - // load personal configuration - table = DTable(VTable(model, buildRows())) - model.columns.forEach { - if(it?.label != "" ) { + if(it?.label != "") { + println("column : " + it?.label) pivotData.addColumn(it?.label, it?.javaClass) } } @@ -98,6 +64,7 @@ class DPivotTable(private val report: VPivotTable) : DWindow(report), UPivotTabl listeRows.add(row) } } + println("rows : " + listeRows) pivotData.addRow(*listeRows.toTypedArray()) listeRows.clear() } @@ -105,351 +72,4 @@ class DPivotTable(private val report: VPivotTable) : DWindow(report), UPivotTabl var pivot = PivotTable(pivotData, pivotOptions, PivotTable.PivotMode.INTERACTIVE) add(pivot) } - - override fun redisplay() { - contentChanged() - } - - /** - * Reorders the report columns. - * @param newOrder The new columns order. - */ - fun reorder(newOrder: IntArray) { - model.columnMoved(newOrder) - accessAndPush(currentUI) { - table.setColumnOrder( - newOrder.map { table.getColumnByKey(it.toString()) } - ) - for (col in 0 until model.getAccessibleColumnCount()) { - table.getColumnByKey(col.toString()).isVisible = - !model.getAccessibleColumn(col)!!.isFolded - || model.getAccessibleColumn(col) is VSeparatorColumn - } - } - } - - override fun removeColumn(position: Int) { - val indexInView = table.convertColumnIndexToView(position) - - model.removeColumn(position) - table.removeColumnByKey(position.toString()) - model.initializeAfterRemovingColumn(indexInView) - - // set new order. - val pos = IntArray(model.getAccessibleColumnCount()) - for (i in 0 until model.getAccessibleColumnCount()) { - pos[i] = if (model.getDisplayOrder(i) > position) model.getDisplayOrder(i) - 1 else model.getDisplayOrder(i) - } - report.columnMoved(pos) - } - - override fun addColumn(position: Int) { - accessAndPush(currentUI) { - var position = position - position = table.convertColumnIndexToView(position) - position += 1 - val headerLabel = "col" + model.getColumnCount() - val span = VerticalLayout(Span(headerLabel)) - model.addColumn(headerLabel, position) - val column = table.addColumn(model.getColumnCount() - 1) - column.setHeader(span) - column.flexGrow = 0 - addHeaderListeners(column, span) - // move last column to position. - val pos = IntArray(model.getAccessibleColumnCount()) - for (i in 0 until position) { - pos[i] = model.getDisplayOrder(i) - } - for (i in position + 1 until model.getAccessibleColumnCount()) { - pos[i] = model.getDisplayOrder(i - 1) - } - pos[position] = model.getDisplayOrder(model.getAccessibleColumnCount() - 1) - report.columnMoved(pos) - } - } - - override fun addColumn() { - addColumn(table.getColumnCount() - 1) - } - - override fun getTable(): UPivotTable.UTable { - return table - } - - override fun contentChanged() { - if (this::table.isInitialized) { - accessAndPush(currentUI) { - table.setItems(buildRows()) - table.model.fireContentChanged() - columnsSelector.build(table) - } - } - } - - override fun columnMoved(pos: IntArray) { - reorder(pos) - model.columnMoved(pos) - redisplay() - } - - override fun resetWidth() { - access(currentUI) { - table.resetWidth() - } - } - - override fun getSelectedColumn(): Int { - return table.selectedColumn - } - - override fun getSelectedCell(): Point = Point(table.selectedColumn, table.selectedRow) - - override fun setColumnLabel(column: Int, label: String) { - access(currentUI) { - table.getColumnByKey(column.toString()).setHeader(label) - } - } - - /** - * Return the columns display order. - * @return The columns display order. - */ - val displayOrder: IntArray - get() { - val displayOrder = IntArray(model.getColumnCount()) - for (i in 0 until model.getColumnCount()) { - displayOrder[i] = table.convertColumnIndexToModel(i) - } - return displayOrder - } - - /** - * Returns the number of columns displayed in the table - * @return tThe number of columns displayed - */ - val columnCount: Int - get() = table.getColumnCount() - - /** - * Add listeners to the report table. - */ - private fun addTableListeners() { - val currentModel: MPivotTable = model - - table.columnToHeaderMap.forEach { (gridColumn, header) -> - addHeaderListeners(gridColumn, header) - } - - // Listeners for item click to fold and unfold the row - table.addItemClickListener { event -> - val row = event.item.rowIndex - val col = event.column.key.toInt() - if (event.button == 0) { - if (event.clickCount == 2) { - if (currentModel.isRowLine(row)) { - getModel()!!.performAsyncAction(object : Action("edit_line") { - override fun execute() { - try { - report.editLine() - } catch (ve: VException) { - // exception thrown by trigger. - throw ve - } - } - }) - } else { - if (row >= 0) { - if (currentModel.isRowFold(row, col)) { - currentModel.unfoldingRow(row, col) - } else { - currentModel.foldingRow(row, col) - } - } - } - } else if (event.isShiftKey && event.isCtrlKey) { - currentModel.sortColumn(col) - } else if (event.isCtrlKey) { - if (row >= 0) { - if (currentModel.isRowFold(row, col)) { - currentModel.unfoldingRow(row, col) - } else { - currentModel.foldingRow(row, col) - } - } - } else if (event.isShiftKey) { - if (currentModel.isColumnFold(col)) { - currentModel.unfoldingColumn(col) - } else { - currentModel.foldingColumn(col) - } - } - } else if (event.button == 2) { - if (row >= 0) { - if (currentModel.isRowFold(row, col)) { - currentModel.unfoldingRow(row, col) - } else { - currentModel.foldingRow(row, col) - } - } - } else if (event.button == 1) { - if (currentModel.isColumnFold(col)) { - currentModel.unfoldingColumn(col) - } else { - currentModel.foldingColumn(col) - } - } - } - - // Listener for column reorder - table.addColumnReorderListener { event -> - table.viewColumns = event.columns.map { it.key.toInt() }.toMutableList() - val newColumnOrder = IntArray(model.getColumnCount()) - val visibleColumns = table.viewColumns - var hiddenColumnsCount = 0 - for (i in newColumnOrder.indices) { - if (!model.getAccessibleColumn(i)!!.isVisible) { - hiddenColumnsCount += 1 - newColumnOrder[i] = model.getDisplayOrder(i) - } else { - newColumnOrder[i] = visibleColumns[i - hiddenColumnsCount] - } - } - model.columnMoved(newColumnOrder) - } - - /*table.addListener(object : ColumnCollapseListener() { TODO - fun columnCollapsed(event: ColumnCollapseEvent) { - for (i in 0 until model.getAccessibleColumnCount()) { - model.getAccessibleColumn(i)!!.isFolded = false - } - for (propertyId: Any in event.getPropertyIds()) { - val col: Int = propertyId as String?. toInt () - 1 - model.getAccessibleColumn(col)!!.isFolded = true - } - table.dataCommunicator.reset() // TODO - } - })*/ - - table.addSelectionListener { - report.setMenu() - } - - table.dataProvider.addDataProviderListener { - setInfoTable() - table.resetCachedInfos() - } - } - - // Issue: https://github.com/vaadin/flow-components/issues/1520 - val contextMenuList = mutableListOf() - - private fun addHeaderListeners(gridColumn: Grid.Column<*>, header: VerticalLayout) { - val currentModel: MPivotTable = model - val labelPopupMenu = ContextMenu() - - contextMenuList.add(labelPopupMenu) - - labelPopupMenu.target = header - - labelPopupMenu.addItem(VlibProperties.getString("set_column_info")) { - table.selectedColumn = getSelectedColumnIndex(gridColumn) - getModel()!!.performAsyncAction(object : Action("set_column_info") { - override fun execute() { - try { - report.setColumnInfo() - } catch (ve: VException) { - // exception thrown by trigger. - throw ve - } - } - }) - } - labelPopupMenu.addItem(VlibProperties.getString("sort_ASC")) { - currentModel.sortColumn(getSelectedColumnIndex(gridColumn), 1) - } - labelPopupMenu.addItem(VlibProperties.getString("sort_DSC")) { - currentModel.sortColumn(getSelectedColumnIndex(gridColumn), -1) - } - labelPopupMenu.addItem(VlibProperties.getString("add_column")) { - addColumn(getSelectedColumnIndex(gridColumn)) - } - if (currentModel.getAccessibleColumn(getSelectedColumnIndex(gridColumn))!!.isAddedAtRuntime) { - labelPopupMenu.addItem(VlibProperties.getString("remove_column")) { - removeColumn(getSelectedColumnIndex(gridColumn)) - } - labelPopupMenu.addItem(VlibProperties.getString("set_column_data")) { - table.selectedColumn = getSelectedColumnIndex(gridColumn) - getModel()!!.performAsyncAction(object : Action("set_column_data") { - override fun execute() { - try { - report.setColumnData() - } catch (ve: VException) { - // exception thrown by the trigger. - throw ve - } - } - }) - } - } - - header.addClickListener { event -> - if (event.button == 0) { // TODO do we need this check? - if (event.isCtrlKey) { - if (currentModel.isColumnFold(getSelectedColumnIndex(gridColumn))) { - currentModel.unfoldingColumn(getSelectedColumnIndex(gridColumn)) - } else { - currentModel.foldingColumn(getSelectedColumnIndex(gridColumn)) - } - } else if (event.isShiftKey) { - currentModel.sortColumn(getSelectedColumnIndex(gridColumn)) - } - } - } - } - - fun getSelectedColumnIndex(gridColumn: Grid.Column<*>): Int = gridColumn.key.toInt() - - /** - * Display table information in the footer of the table - */ - private fun setInfoTable() { - setStatisticsText( - table.model.model.getRowCount() - .toString() + "/" - + model.getBaseRowCount() - + "/" - + model.getVisibleRowCount() - ) - } - - /** - * Builds the grid rows. - */ - private fun buildRows(): List { - val rows = mutableListOf() - for (i in 0 until model.getRowCount()) { - rows.add(ReportModelItem(i)) - } - return rows - } - - //--------------------------------------------------- - // TABLE MODEL ITEM - //--------------------------------------------------- - /** - * The `TableModelItem` is the report table - * data model. - * - * @param rowIndex The row index. - */ - inner class ReportModelItem(val rowIndex: Int) { - //--------------------------------------- - // IMPLEMENTATIONS - //--------------------------------------- - fun getValueAt(columnIndex: Int): String { - return model.accessibleColumns[columnIndex]!!.format(model.getValueAt(rowIndex, columnIndex)) - } - - val reportRow: VReportRow? get() = model.getRow(rowIndex) - } } diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/DTable.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/DTable.kt deleted file mode 100644 index ba05c3fda..000000000 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/DTable.kt +++ /dev/null @@ -1,255 +0,0 @@ -/* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN - * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.kopi.galite.visual.ui.vaadin.pivotTable - -import org.kopi.galite.visual.pivotTable.Constants -import org.kopi.galite.visual.pivotTable.UPivotTable.UTable -import org.kopi.galite.visual.pivotTable.VDecimalColumn -import org.kopi.galite.visual.pivotTable.VIntegerColumn -import org.kopi.galite.visual.pivotTable.VReportColumn -import org.kopi.galite.visual.pivotTable.VSeparatorColumn - -import com.vaadin.flow.component.AttachEvent -import com.vaadin.flow.component.Component -import com.vaadin.flow.component.DetachEvent -import com.vaadin.flow.component.dependency.CssImport -import com.vaadin.flow.component.grid.ColumnTextAlign -import com.vaadin.flow.component.grid.Grid -import com.vaadin.flow.component.grid.GridVariant -import com.vaadin.flow.component.html.Span -import com.vaadin.flow.component.orderedlayout.VerticalLayout -import com.vaadin.flow.component.page.Page -import com.vaadin.flow.function.ValueProvider -import com.vaadin.flow.shared.Registration - -import elemental.json.JsonObject -import elemental.json.JsonValue - -/** - * The `DTable` is a table implementing the [UTable] - * specifications. - * - * @param model The table model. - */ - -@CssImport.Container(value = [ - CssImport("./styles/galite/report.css"), - CssImport(value = "./styles/galite/report.css", themeFor = "vaadin-grid") -]) -class DTable(val model: VTable) : Grid(), UTable { - - //--------------------------------------------------- - // DATA MEMBERS - //--------------------------------------------------- - - /** - * The table selected row. - */ - val selectedRow: Int get() = asSingleSelect().value?.rowIndex ?: -1 - - /** - * The selected column. - */ - var selectedColumn = -1 - - /** - * The indexes of the columns in the grid view - */ - var viewColumns = mutableListOf() - - val columnToHeaderMap = mutableMapOf, VerticalLayout>() - - lateinit var cellStyler: ReportCellStyler - lateinit var browserWindowResizeListener: Registration - - init { - buildColumns() - addThemeVariants(GridVariant.LUMO_COMPACT, GridVariant.LUMO_COLUMN_BORDERS) - themeNames.add("report") - classNames.add("small") - classNames.add("borderless") - classNames.add("report") - setWidthFull() - } - - //--------------------------------------------------- - // IMPLEMENTATIONS - //--------------------------------------------------- - - override fun onAttach(attachEvent: AttachEvent) { - val page = attachEvent.ui.page - - page.setWindowHeight() - - browserWindowResizeListener = page.addBrowserWindowResizeListener { event -> - height = (event.height - 200).toString() + "px" - } - } - - private fun Page.setWindowHeight() { - val js = "return Vaadin.Flow.getBrowserDetailsParameters();" - executeJs(js).then { - height = ((it as JsonObject).get("v-wh").asNumber() - 200).toString() + "px" - } - } - - override fun onDetach(detachEvent: DetachEvent) { - browserWindowResizeListener.remove() - } - - /** - * Builds the grid columns. - */ - private fun buildColumns() { - model.accessibleColumns.forEachIndexed { index, column -> - val gridColumn = addColumn(index, column!!) - - gridColumn - .setHeader(getColumnNameComponent(column, gridColumn)) - - gridColumn.flexGrow = 0 - } - } - - /** - * Returns a component containing the column name of a given column. - * - * @param column The report column. - * @return The column name container. - */ - fun getColumnNameComponent(column: VReportColumn, gridColumn: Column): Component = - VerticalLayout(Span(column.label)) - .also { - it.element.setProperty("title", column.help) - columnToHeaderMap[gridColumn] = it - } - - /** - * Maps the index of the column in the grid at [viewColumnIndex] to the index of the column in the table model. - */ - override fun convertColumnIndexToModel(viewColumnIndex: Int): Int = viewColumns[viewColumnIndex] - - /** - * Maps the index of the column in the table model at [modelColumnIndex] to the index of the column in the grid. - */ - override fun convertColumnIndexToView(modelColumnIndex: Int): Int = viewColumns.indexOf(modelColumnIndex) - - /** - * Adds a new text column to this table with a column value provider and a key for the column. - * - * @param key the key of the column provider - * @param column the report column model - * @return the created column - */ - fun addColumn(key: Int, column: VReportColumn = model.accessibleColumns[key]!!): Column { - val provider = ColumnValueProvider(key, column) - - viewColumns.add(key) - - return addColumn(provider).also { - provider.column = it - it.setKey(key.toString()) - .setResizable(true) - .setClassNameGenerator(ColumnStyleGenerator(model.model, column)) - .setSortable(false) - } - } - - override fun removeColumnByKey(columnKey: String) { - viewColumns.remove(columnKey.toInt()) - super.removeColumnByKey(columnKey) - } - - override fun removeColumn(column: Column) { - viewColumns.remove(column.key.toInt()) - super.removeColumn(column) - } - - /** - * Returns the column count. - * @return the column count. - */ - fun getColumnCount(): Int = model.getColumnCount() - - /** - * Reset all columns widths. - */ - fun resetWidth() { - for (i in 0 until model.getColumnCount()) { - resetColumnSize(i) - } - } - - /** - * Resets the column size at a given position. - * @param pos The column position. - */ - private fun resetColumnSize(pos: Int) { - val column = model.model.getAccessibleColumn(convertColumnIndexToModel(pos)) - var width: Int - - if (column!!.isFolded && column !is VSeparatorColumn) { - width = 1 - } else if (column is VDecimalColumn || column is VIntegerColumn) { - width = column.label.length.coerceAtLeast(column.width) - // Integer and Fixed column can contain , data generated by operations like sum, multiplication - // --> compute column width occording to data. - width = width.coerceAtLeast(model.model.computeColumnWidth(convertColumnIndexToModel(pos))) - } else { - width = column.label.length.coerceAtLeast(column.width) - } - - if (width != 0) { - width = width * 9 + 2 - } - - columns[pos].width = "${width + 12}px" - } - - /** - * Resets the table cached information. - */ - fun resetCachedInfos() { - selectedColumn = -1 - select(null) - } - - /** - * Provides the value for the column with index [columnIndex] - * - * @param columnIndex the index of the column - */ - inner class ColumnValueProvider( - private val columnIndex: Int, - private val columnModel: VReportColumn - ) : ValueProvider { - var column: Column? = null - - override fun apply(source: DPivotTable.ReportModelItem): String { - column?.textAlign = if (columnModel.align == Constants.ALG_RIGHT) { - ColumnTextAlign.END - } else { - ColumnTextAlign.START - } - - cellStyler.updateStyles(source.rowIndex, columnIndex) - - return source.getValueAt(columnIndex) - } - } -} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/ReportCellStyler.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/ReportCellStyler.kt deleted file mode 100644 index c8f3acc4c..000000000 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/ReportCellStyler.kt +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN - * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.kopi.galite.visual.ui.vaadin.pivotTable - -import java.awt.Color - -import org.kopi.galite.visual.pivotTable.ColumnStyle -import org.kopi.galite.visual.pivotTable.MPivotTable -import org.kopi.galite.visual.pivotTable.Parameters -import org.kopi.galite.visual.pivotTable.VSeparatorColumn - -/** - * The `ReportCellStyler` is the dynamic report styler - * - * @param model The report model. - * @param parameters The style parameters. - */ -class ReportCellStyler(private val model: MPivotTable, private val parameters: Parameters, val table: DTable) { - - //--------------------------------------------------- - // IMPLEMENTATIONS - //--------------------------------------------------- - /** - * Updates the cell styles. - * - * @param i The row index of the cell. - * @param j The column index of the cell. - */ - fun updateStyles(i: Int, j: Int) { - val column = model.getAccessibleColumn(j) - - if (column is VSeparatorColumn) { - return - } - val style = column!!.getStyles()[0] - - updateStyle(style, model.getRow(i)!!.level) - } - - /** - * Updates the CSS style of a given [ColumnStyle]. - * - * @param columnStyle The [ColumnStyle]. - * @param level The column level. - * - */ - private fun updateStyle(columnStyle: ColumnStyle, level: Int) { - val background = if (columnStyle.getBackground() != columnStyle.getBackground()) { - columnStyle.getBackground() - } else { - parameters.getBackground(level) - } - val foreground = if (columnStyle.getForeground() != columnStyle.getForeground()) { - columnStyle.getForeground() - } else { - parameters.getForeground(level) - } - val fontSize = if (columnStyle.getFont().size != columnStyle.getFont().size) { - columnStyle.getFont().size - } else { - parameters.font.size - } - val fontFamily = if (columnStyle.getFont().name != columnStyle.getFont().name) { - columnStyle.getFont().name - } else { - parameters.font.name - } - val isBold = if (columnStyle.getFont().isBold != columnStyle.getFont().isBold) { - columnStyle.getFont().isBold - } else { - parameters.font.isBold - } - val isItalic = if (columnStyle.getFont().isItalic != columnStyle.getFont().isItalic) { - columnStyle.getFont().isItalic - } else { - parameters.font.isItalic - } - - setStyle(level, background, foreground,fontSize, fontFamily, fontWeight(isBold), fontStyle(isItalic)) - } - - /** - * Returns the encapsulated CSS style. - */ - private fun setStyle( - level: Int, - background: Color, - foreground: Color, - fontSize: Int, - fontFamily: String, - fontWeight: String, - fontStyle: String, - ) { - table.style["--level-$level-background"] = getCSSColor(background) - table.style["--level-$level-color"] = getCSSColor(foreground) - table.style["--level-$level-font-size"] = fontSize.toString() - table.style["--level-$level-font-family"] = fontFamily - table.style["--level-$level-font-weight"] = fontWeight - table.style["--level-$level-font-style"] = fontStyle - } - - /** - * Returns the corresponding CSS color of a given [Color]. - * @param color The AWT color. - * @return The CSS color. - */ - private fun getCSSColor(color: Color): String { - return "rgb(" + color.red + "," + color.green + "," + color.blue + ")" - } - - /** - * Returns the bold style. - * @param isBold The bold style. - */ - private fun fontWeight(isBold: Boolean): String = if(isBold) "bold" else "normal" - - /** - * Returns the italic style. - * @param isItalic The italic style. - */ - private fun fontStyle(isItalic: Boolean) : String = if (isItalic) "italic" else "normal" -} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/VTable.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/VTable.kt deleted file mode 100644 index d9f6209a4..000000000 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/VTable.kt +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN - * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.kopi.galite.visual.ui.vaadin.pivotTable - -import org.kopi.galite.visual.pivotTable.VReportColumn -import org.kopi.galite.visual.ui.vaadin.pivotTable.DPivotTable.ReportModelItem - -import com.vaadin.flow.component.grid.Grid -import com.vaadin.flow.data.provider.ListDataProvider -import com.vaadin.flow.data.provider.Query -import com.vaadin.flow.function.SerializablePredicate -import org.kopi.galite.visual.pivotTable.MPivotTable - -/** - * The VTable is a vaadin [Grid] data provider adapted - * to dynamic reports needs. - * - * @param model The table model. - */ -class VTable( - internal val model: MPivotTable, - reportItems: List -): ListDataProvider(reportItems) { - - init { - addFilter { - it != null - } - } - - override fun size(query: Query>?): Int { - return model.getRowCount() - } - - /** - * Notify the report table that the report content has been - * change in order to update the table content. - */ - fun fireContentChanged() { - refreshAll() - } - - /** - * Returns the column align. - * @param column The column index. - * @return The column align. - */ - fun getColumnAlign(column: Int): Int = model.getAccessibleColumn(column)!!.align - - /** - * Returns the column count. - * @return the column count. - */ - fun getColumnCount(): Int = model.getColumnCount() - - /** - * Returns the accessible columns to display in the grid. - */ - val accessibleColumns: Array get() = model.accessibleColumns -} diff --git a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/bill/BillForm.kt b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/bill/BillForm.kt index 504259b34..0e3d2c228 100644 --- a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/bill/BillForm.kt +++ b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/bill/BillForm.kt @@ -59,12 +59,12 @@ class BillForm : DictionaryForm(title = "Bills", locale = Locale.UK) { help = "The bill number" columns(u.numBill) } - val addressBill = mustFill(domain = STRING(30), position = at(1, 1)) { + val addressBill = visit(domain = STRING(30), position = at(1, 1)) { label = "Address" help = "The bill address" columns(u.addressBill) } - val dateBill = mustFill(domain = DATE, position = at(2, 1)) { + val dateBill = visit(domain = DATE, position = at(2, 1)) { label = "Date" help = "The bill date" columns(u.dateBill) diff --git a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/bill/BillP.kt b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/bill/BillP.kt index 3f41b880f..4153729ff 100644 --- a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/bill/BillP.kt +++ b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/bill/BillP.kt @@ -28,39 +28,18 @@ import org.kopi.galite.visual.domain.STRING import org.kopi.galite.visual.dsl.common.Icon import org.kopi.galite.visual.dsl.form.Key import org.kopi.galite.visual.dsl.pivotTable.PivotTable -import org.kopi.galite.visual.dsl.pivotTable.FieldAlignment /** * Bill Report */ class BillP : PivotTable("Bills_Report", locale = Locale.UK) { - val action = menu("Action") val file = menu("File") val quit = actor(menu = file, label = "Quit", help = "Close Report.", ident = "quit") { key = Key.ESCAPE icon = Icon.QUIT } - val csv = actor(menu = action, label = "CSV", help = "CSV Format", ident = "csv") { - key = Key.F8 // key is optional here - icon = Icon.EXPORT_CSV // icon is optional here - } - - val xls = actor(menu = action, label = "XLS", help = "Excel (XLS) Format", ident = "xls") { - key = Key.SHIFT_F8 // key is optional here - icon = Icon.EXPORT_XLSX // icon is optional here - } - - val xlsx = actor(menu = action, label = "XLSX", help = "Excel (XLSX) Format", ident = "xlsx") { - key = Key.SHIFT_F8 // key is optional here - icon = Icon.EXPORT // icon is optional here - } - - val pdf = actor(menu = action, label = "PDF", help = "PDF Format", ident = "pdf") { - key = Key.F9 // key is optional here - icon = Icon.EXPORT_PDF // icon is optional here - } val cmdQuit = command(item = quit) { model.close() @@ -69,30 +48,25 @@ class BillP : PivotTable("Bills_Report", locale = Locale.UK) { val numBill = field(INT(25)) { label = "Number" help = "The bill number" - align = FieldAlignment.LEFT } val addressBill = field(STRING(25)) { label = "Address" help = "The bill address" - align = FieldAlignment.LEFT } val dateBill = field(DATE) { label = "Date" help = "The bill date" - align = FieldAlignment.LEFT } val amountWithTaxes = field(DECIMAL(20, 10)) { label = "Amount to pay" help = "The amount including all taxes to pay" - align = FieldAlignment.LEFT } val refCmd = field(INT(50)) { label = "Command reference" help = "The command reference" - align = FieldAlignment.LEFT } val bills = Bill.selectAll() diff --git a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/billproduct/BillProductP.kt b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/billproduct/BillProductP.kt index fb798c23e..6581d5fe0 100644 --- a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/billproduct/BillProductP.kt +++ b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/billproduct/BillProductP.kt @@ -20,14 +20,10 @@ import java.util.Locale import org.jetbrains.exposed.sql.selectAll import org.jetbrains.exposed.sql.transactions.transaction -import org.kopi.galite.demo.common.ReportDefault import org.kopi.galite.demo.database.BillProduct import org.kopi.galite.visual.domain.DECIMAL import org.kopi.galite.visual.domain.INT -import org.kopi.galite.visual.dsl.common.Icon -import org.kopi.galite.visual.dsl.form.Key import org.kopi.galite.visual.dsl.pivotTable.PivotTable -import org.kopi.galite.visual.dsl.pivotTable.FieldAlignment /** * Products Bill Report @@ -37,7 +33,6 @@ class BillProductP : PivotTable("Bill Product Report", Locale.UK) { val quantity = field(INT(25)) { label = "Quantity" help = "The quantity" - align = FieldAlignment.LEFT } val amount = field(DECIMAL(25, 10)) { @@ -48,7 +43,6 @@ class BillProductP : PivotTable("Bill Product Report", Locale.UK) { val amountWithTaxes = field(DECIMAL(50, 10)) { label = "Amount all taxes included" help = "The amount all taxes included to pay" - align = FieldAlignment.LEFT } val billProducts = BillProduct.selectAll() diff --git a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/provider/ProviderP.kt b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/provider/ProviderP.kt index e8c1cd318..017442619 100644 --- a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/provider/ProviderP.kt +++ b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/provider/ProviderP.kt @@ -26,7 +26,6 @@ import org.kopi.galite.visual.domain.STRING import org.kopi.galite.visual.dsl.common.Icon import org.kopi.galite.visual.dsl.form.Key import org.kopi.galite.visual.dsl.pivotTable.PivotTable -import org.kopi.galite.visual.dsl.pivotTable.FieldAlignment /** * Provider Report @@ -59,37 +58,26 @@ class ProviderP : PivotTable(title = "Providers_Report", locale = Locale.UK) { val nameProvider = field(STRING(50)) { label = "Name" help = "The provider name" - align = FieldAlignment.LEFT - format { value -> - value.toUpperCase() - } } val tel = field(INT(25)) { label = "Phone number" help = "The provider phone number" - align = FieldAlignment.LEFT } val description = field(STRING(255)) { label = "Description" help = "The provider description" - align = FieldAlignment.LEFT - format { value -> - value.toUpperCase() - } } val address = field(STRING(70)) { label = "Address" help = "The provider address" - align = FieldAlignment.LEFT } val zipCode = field(INT(50)) { label = "Zip code" help = "The provider zip code" - align = FieldAlignment.LEFT } val providers = Provider.selectAll() diff --git a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/stock/StockP.kt b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/stock/StockP.kt index b30304f09..11a01d2ea 100644 --- a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/stock/StockP.kt +++ b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/stock/StockP.kt @@ -29,7 +29,6 @@ import org.kopi.galite.visual.domain.STRING import org.kopi.galite.visual.dsl.common.Icon import org.kopi.galite.visual.dsl.form.Key import org.kopi.galite.visual.dsl.pivotTable.PivotTable -import org.kopi.galite.visual.dsl.pivotTable.FieldAlignment /** * Stock Report @@ -61,17 +60,14 @@ class StockP : PivotTable(title = "Stocks", locale = Locale.UK) { val description = field(STRING(25)) { label = "Description" help = "The product description" - align = FieldAlignment.LEFT } val nameProvider = field(STRING(25)) { label = "Provider name" help = "The provider name" - align = FieldAlignment.LEFT } val minAlert = field(INT(25)) { label = "Min Alert" help = "The stock's min alert" - align = FieldAlignment.LEFT } val stocks = Stock.join(Provider, JoinType.INNER, Stock.idStckProv, Provider.idProvider) diff --git a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/taxRule/TaxRuleP.kt b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/taxRule/TaxRuleP.kt index bcbf14668..61d1549c1 100644 --- a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/taxRule/TaxRuleP.kt +++ b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/taxRule/TaxRuleP.kt @@ -26,7 +26,6 @@ import org.kopi.galite.visual.domain.STRING import org.kopi.galite.visual.dsl.common.Icon import org.kopi.galite.visual.dsl.form.Key import org.kopi.galite.visual.dsl.pivotTable.PivotTable -import org.kopi.galite.visual.dsl.pivotTable.FieldAlignment /** * Tax Rules Report @@ -35,36 +34,14 @@ class TaxRuleP : PivotTable(title = "TaxRules_Report", locale = Locale.UK) { val action = menu("Action") - val csv = actor(menu = action, label = "CSV", help = "CSV Format", ident = "csv") { - key = Key.F8 - icon = Icon.EXPORT_CSV - } - - val xls = actor(menu = action, label = "XLS", help = "Excel (XLS) Format", ident = "xls") { - key = Key.SHIFT_F8 - icon = Icon.EXPORT_XLSX - } - - val xlsx = actor(menu = action, label = "XLSX", help = "Excel (XLSX) Format", ident = "xlsx") { - key = Key.SHIFT_F8 - icon = Icon.EXPORT - } - - val pdf = actor(menu = action, label = "PDF", help = "PDF Format", ident = "pdf") { - key = Key.F9 - icon = Icon.EXPORT_PDF - } - val taxName = field(STRING(50)) { label = "Name" help = "The tax name" - align = FieldAlignment.LEFT } val rate = field(INT(25)) { label = "Rate in %" help = "The tax rate in %" - align = FieldAlignment.LEFT } val taxRules = TaxRule.selectAll() From 574cf50599ed79b233d27a1d800b760950b59898 Mon Sep 17 00:00:00 2001 From: Super User Date: Thu, 19 Oct 2023 11:50:41 +0100 Subject: [PATCH 05/20] Pivot table implementation : DSL model, model and UI model --- .../org/kopi/galite/visual/domain/Domain.kt | 4 +- .../visual/dsl/pivotTable/PivotTable.kt | 35 +++---- .../{ReportField.kt => PivotTableField.kt} | 26 ++--- ...ter.kt => PivotTableLocalizationWriter.kt} | 4 +- .../{ReportRow.kt => PivotTableRow.kt} | 20 ++-- .../galite/visual/pivotTable/Constants.kt | 31 ------ .../galite/visual/pivotTable/MPivotTable.kt | 94 ++---------------- .../galite/visual/pivotTable/UPivotTable.kt | 2 +- .../visual/pivotTable/VDefaultReportActor.kt | 51 ---------- .../galite/visual/pivotTable/VGroupRow.kt | 63 ------------ .../visual/pivotTable/VHelpGenerator.kt | 95 ------------------- .../galite/visual/pivotTable/VPivotTable.kt | 63 ++---------- ...{VReportColumn.kt => VPivotTableColumn.kt} | 19 +--- .../{VBaseRow.kt => VPivotTableRow.kt} | 12 ++- .../galite/visual/pivotTable/VReportRow.kt | 60 ------------ .../ui/vaadin/pivotTable/DPivotTable.kt | 10 +- .../kotlin/org/kopi/galite/demo/bill/BillP.kt | 2 +- 17 files changed, 68 insertions(+), 523 deletions(-) rename galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/{ReportField.kt => PivotTableField.kt} (69%) rename galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/{ReportLocalizationWriter.kt => PivotTableLocalizationWriter.kt} (94%) rename galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/{ReportRow.kt => PivotTableRow.kt} (75%) delete mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/Constants.kt delete mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VDefaultReportActor.kt delete mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VGroupRow.kt delete mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VHelpGenerator.kt rename galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/{VReportColumn.kt => VPivotTableColumn.kt} (78%) rename galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/{VBaseRow.kt => VPivotTableRow.kt} (74%) delete mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VReportRow.kt diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/domain/Domain.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/domain/Domain.kt index 43d3579e6..66239bb59 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/domain/Domain.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/domain/Domain.kt @@ -277,11 +277,11 @@ open class Domain(val width: Int? = null, /** * Builds the pivot table column model */ - open fun buildReportFieldModel(field: org.kopi.galite.visual.dsl.pivotTable.ReportField<*>): org.kopi.galite.visual.pivotTable.VReportColumn { + open fun buildReportFieldModel(field: org.kopi.galite.visual.dsl.pivotTable.PivotTableField<*>): org.kopi.galite.visual.pivotTable.VPivotTableColumn { return with(field) { when (kClass) { Int::class, Long::class, String::class, BigDecimal::class, Boolean::class, org.joda.time.LocalDate::class, LocalDate::class, java.sql.Date::class, java.util.Date::class, Month::class, Week::class, org.joda.time.LocalTime::class, LocalTime::class, Instant::class, LocalDateTime::class, DateTime::class -> - org.kopi.galite.visual.pivotTable.VReportColumn(ident) + org.kopi.galite.visual.pivotTable.VPivotTableColumn(ident) else -> throw java.lang.RuntimeException("Type ${kClass!!.qualifiedName} is not supported") } diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTable.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTable.kt index 3243086a8..844d17cfc 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTable.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTable.kt @@ -31,7 +31,7 @@ abstract class PivotTable(title: String, val help: String?, locale: Locale? = nu constructor(title: String, locale: Locale? = null) : this(title, null, locale) /** Report's fields. */ - val fields = mutableListOf>() + val fields = mutableListOf>() /** Report's data rows. */ val reportRows = mutableListOf() @@ -44,12 +44,12 @@ abstract class PivotTable(title: String, val help: String?, locale: Locale? = nu * @return a field. */ inline fun ?> field(domain: Domain, - noinline init: ReportField.() -> Unit): ReportField { + noinline init: PivotTableField.() -> Unit): PivotTableField { domain.kClass = T::class - val field = ReportField(domain, init, "ANM_${fields.size}", domain.source.ifEmpty { `access$sourceFile` }) + val field = PivotTableField(domain, init, "ANM_${fields.size}", domain.source.ifEmpty { `access$sourceFile` }) - field.initialize() + field.initField() val pos = if(model.model.columns.size == 0) 0 else model.model.columns.size - 1 model.model.columns.add(pos, field.buildReportColumn()) @@ -66,8 +66,8 @@ abstract class PivotTable(title: String, val help: String?, locale: Locale? = nu * @return a field. */ inline fun ?> nullableField(domain: Domain, - noinline init: ReportField.() -> Unit): ReportField { - return field(domain, init) as ReportField + noinline init: PivotTableField.() -> Unit): PivotTableField { + return field(domain, init) as PivotTableField } /** @@ -80,7 +80,7 @@ abstract class PivotTable(title: String, val help: String?, locale: Locale? = nu */ inline fun ?> field(fieldsNumber: Int, domain: Domain, - noinline init: ReportField.() -> Unit): List> { + noinline init: PivotTableField.() -> Unit): List> { return (0 until fieldsNumber).map { nullableField(domain, init).also { field -> field.model.label = "${field.label}_${it + 1}" @@ -115,7 +115,7 @@ abstract class PivotTable(title: String, val help: String?, locale: Locale? = nu * * @param rowNumber the index of the desired row. */ - fun getRow(rowNumber: Int): MutableMap, Any?> = reportRows[rowNumber].data + fun getRow(rowNumber: Int): MutableMap, Any?> = reportRows[rowNumber].data /** * Adds default report commands @@ -127,18 +127,11 @@ abstract class PivotTable(title: String, val help: String?, locale: Locale? = nu } // ---------------------------------------------------------------------- - // HELP + // Command // ---------------------------------------------------------------------- - fun showHelp() { - model.showHelp() - } - - fun addDefaultReportCommands() { - model.addDefaultReportCommands() - } - - override fun addCommandTrigger() { + fun addDefaultPivotTableCommands() { + model.addDefaultPivotTableCommands() } // ---------------------------------------------------------------------- @@ -153,7 +146,7 @@ abstract class PivotTable(title: String, val help: String?, locale: Locale? = nu ?: (this.javaClass.classLoader.getResource("")?.path + this.javaClass.`package`.name.replace(".", "/")) try { - val writer = ReportLocalizationWriter() + val writer = PivotTableLocalizationWriter() genLocalization(writer) writer.write(localizationDestination, baseName, locale) } catch (ioe: IOException) { @@ -164,7 +157,7 @@ abstract class PivotTable(title: String, val help: String?, locale: Locale? = nu } fun genLocalization(writer: LocalizationWriter) { - (writer as ReportLocalizationWriter).genReport(title, help, fields, menus, actors) + (writer as PivotTableLocalizationWriter).genReport(title, help, fields, menus, actors) } // ---------------------------------------------------------------------- @@ -188,7 +181,7 @@ abstract class PivotTable(title: String, val help: String?, locale: Locale? = nu model.source = sourceFile if (reportCommands) { - addDefaultReportCommands() + addDefaultPivotTableCommands() } } diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/ReportField.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTableField.kt similarity index 69% rename from galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/ReportField.kt rename to galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTableField.kt index 9dc4acd81..d12ae6141 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/ReportField.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTableField.kt @@ -20,30 +20,20 @@ package org.kopi.galite.visual.dsl.pivotTable import org.kopi.galite.visual.domain.Domain import org.kopi.galite.visual.dsl.common.LocalizationWriter import org.kopi.galite.visual.dsl.field.Field -import org.kopi.galite.visual.pivotTable.VReportColumn -import org.kopi.galite.visual.VCommand +import org.kopi.galite.visual.pivotTable.VPivotTableColumn -class ReportField(override val domain: Domain, - val init: ReportField.() -> Unit, - ident: String? = null, - override val source: String?) : Field(domain, ident) { - /** the options of the field */ - internal var options: Int = 0 - - /** the commands accessible in this field */ - lateinit var commands: Array - - fun initialize() { - initField() - } +class PivotTableField(override val domain: Domain, + val init: PivotTableField.() -> Unit, + ident: String? = null, + override val source: String?) : Field(domain, ident) { fun initField() { init() } - lateinit var model: VReportColumn + lateinit var model: VPivotTableColumn - fun buildReportColumn(): VReportColumn { + fun buildReportColumn(): VPivotTableColumn { model = domain.buildReportFieldModel(this).also { column -> column.label = label ?: "" column.help = help @@ -59,6 +49,6 @@ class ReportField(override val domain: Domain, * Generates localization for the field in the xml file */ override fun genLocalization(writer: LocalizationWriter) { - (writer as ReportLocalizationWriter).genField(ident, label, help) + (writer as PivotTableLocalizationWriter).genField(ident, label, help) } } diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/ReportLocalizationWriter.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTableLocalizationWriter.kt similarity index 94% rename from galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/ReportLocalizationWriter.kt rename to galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTableLocalizationWriter.kt index ad1b178c7..372ff8d46 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/ReportLocalizationWriter.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTableLocalizationWriter.kt @@ -25,10 +25,10 @@ import org.kopi.galite.visual.dsl.common.Menu /** * This class implements an XML localization file generator */ -class ReportLocalizationWriter : LocalizationWriter() { +class PivotTableLocalizationWriter : LocalizationWriter() { fun genReport(title: String?, help: String?, - fields: MutableList>, + fields: MutableList>, menus: MutableList, actors: MutableList) { val self = Element("report") diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/ReportRow.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTableRow.kt similarity index 75% rename from galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/ReportRow.kt rename to galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTableRow.kt index 1de7dcae2..fe3025fa9 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/ReportRow.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTableRow.kt @@ -27,26 +27,26 @@ import org.kopi.galite.type.Week * * @param reportFields the fields that exists in the report. */ -class ReportRow(private val reportFields: MutableList>) { +class ReportRow(private val reportFields: MutableList>) { /** A report data row */ - val data = mutableMapOf, Any?>() + val data = mutableMapOf, Any?>() /** - * Returns data value of a specific [ReportField] in this report row. + * Returns data value of a specific [PivotTableField] in this report row. * * @param field the field. - * @return data value for a specific [ReportField]. + * @return data value for a specific [PivotTableField]. */ @Suppress("UNCHECKED_CAST") - fun getValueOf(field: ReportField): T = data[field] as T + fun getValueOf(field: PivotTableField): T = data[field] as T /** * Gets the value of the field in this report row. * * @param field the field. - * @return data value for a specific [ReportField]. + * @return data value for a specific [PivotTableField]. */ - operator fun get(field: ReportField): T = getValueOf(field) + operator fun get(field: PivotTableField): T = getValueOf(field) /** * Sets the value of the field in this report row. @@ -54,7 +54,7 @@ class ReportRow(private val reportFields: MutableList>) { * @param field the field. * @param value the field's value. */ - operator fun set(field: ReportField, value: T) { + operator fun set(field: PivotTableField, value: T) { if (field in reportFields) { data.putIfAbsent(field, value) } @@ -67,7 +67,7 @@ class ReportRow(private val reportFields: MutableList>) { * @param value the field's value. */ @JvmName("setType0") - operator fun , K> set(field: ReportField, value: K) { + operator fun , K> set(field: PivotTableField, value: K) { if (field in reportFields) { data.putIfAbsent(field, field.toType0(value)) } @@ -77,7 +77,7 @@ class ReportRow(private val reportFields: MutableList>) { /** * Represents the value in sql */ -fun ReportField<*>.toType0(value: T): Any? { +fun PivotTableField<*>.toType0(value: T): Any? { return when(value) { is ExposedBlob -> value is Int -> { diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/Constants.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/Constants.kt deleted file mode 100644 index fc8259472..000000000 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/Constants.kt +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN - * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -package org.kopi.galite.visual.pivotTable - -import org.kopi.galite.visual.form.VConstants -import org.kopi.galite.visual.Constants - -interface Constants : Constants { - companion object { - // --------------------------------------------------------------------- - // PREDEFINED COMMANDS - // --------------------------------------------------------------------- - const val CMD_QUIT = 0 - } -} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/MPivotTable.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/MPivotTable.kt index 4eb03c6e9..ae129eac5 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/MPivotTable.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/MPivotTable.kt @@ -22,112 +22,32 @@ import java.io.Serializable import org.kopi.galite.visual.MessageCode -class MPivotTable : Constants, Serializable { +class MPivotTable : Serializable { // -------------------------------------------------------------------- // DATA MEMBERS // -------------------------------------------------------------------- // Columns contains all columns defined by the user - // accessiblecolumns is a part of columns which contains only visible columns - var columns = mutableListOf() // array of column definitions - var accessibleColumns: Array = arrayOf() // array of visible or hide columns - private set + var columns = mutableListOf() // array of column definitions - // Baserows contains data give by the request of the user - internal var userRows: ArrayList? = ArrayList(500) - lateinit var baseRows: Array // array of base data rows - - // displayOrder contains index column model in display order - // reverseOrder is calculate with displayOrder and contains index column display into model order - private lateinit var displayOrder: IntArray // column mapping from display to model - private lateinit var reverseOrder: IntArray // column mapping from model to display - - // The displayLevels variable is a table which contains the level of each column - private lateinit var displayLevels: IntArray // column levels in display order + // Baserows contains data give by the request of the user + internal var userRows: ArrayList? = ArrayList(500) /** * Add a row to the list of rows defined by the user */ fun addLine(line: Array) { - userRows!!.add(VBaseRow(line)) + userRows!!.add(VPivotTableRow(line)) } /** - * Build the base row table + initialisation + * Build the base row + initialisation */ internal fun build() { // build accessible columns + columns.sortBy { it?.ident } if (userRows!!.size == 0) { throw VNoRowException(MessageCode.getMessage("VIS-00015")) } - createAccessibleTab() - baseRows = userRows!!.toTypedArray() - userRows = null - -// // build working tables -// val columnCount = getAccessibleColumnCount() -// displayOrder = IntArray(columnCount) -// reverseOrder = IntArray(columnCount) -// displayLevels = IntArray(columnCount) -// for (i in 0 until columnCount) { -// displayOrder[i] = i -// reverseOrder[i] = i -// displayLevels[i] = -1 -// } - } - // -------------------------------------------------------------------- - // MEMBER ACCESS - // -------------------------------------------------------------------- - /** - * Return a column definition - * - * @param column the index of the desired column - * @return the desired column - */ - fun getModelColumn(column: Int): VReportColumn = columns[column]!! - - /** - * Returns the number of model columns - * - * @return the number or columns to display - */ - fun getModelColumnCount(): Int = columns.size - - /** - * Returns the number of columns visible or hide - * - * @return the number or columns in the model - */ - fun getAccessibleColumnCount(): Int = accessibleColumns.size - - // -------------------------------------------------------------------- - // REDEFINITION OF METHODS IN AbstractTableModel - // -------------------------------------------------------------------- - /** - * Returns the number of columns managed by the data source object. - * - * @return the number or columns to display - */ - fun getColumnCount(): Int = accessibleColumns.size - - /** - * Makes the table of accessible columns from the columns variable - */ - private fun createAccessibleTab() { - val columnCount = columns.size - var accessiblecolumnCount = 0 - - for (i in 0 until columnCount) { - accessiblecolumnCount += 1 - } - accessibleColumns = arrayOfNulls(accessiblecolumnCount) - accessiblecolumnCount = 0 - for (i in 0 until columnCount) { - accessibleColumns[accessiblecolumnCount++] = columns[i] - } - } - - companion object { - private const val serialVersionUID = 0L } } \ No newline at end of file diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/UPivotTable.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/UPivotTable.kt index 08a4a3065..811452fd7 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/UPivotTable.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/UPivotTable.kt @@ -22,7 +22,7 @@ import org.kopi.galite.visual.UWindow interface UPivotTable : UWindow { /** - * Builds the report; + * Builds the pivot table; */ fun build() } diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VDefaultReportActor.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VDefaultReportActor.kt deleted file mode 100644 index 0dc08f683..000000000 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VDefaultReportActor.kt +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN - * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -package org.kopi.galite.visual.pivotTable - -import org.kopi.galite.visual.VActor -import org.kopi.galite.visual.VlibProperties - -class VDefaultReportActor(menuIdent: String, - actorIdent: String, - iconName: String, - acceleratorKey: Int, - acceleratorModifier: Int) - : VActor(menuIdent, - null, - actorIdent, - null, - null, - acceleratorKey, - acceleratorModifier) { - - init { - this.iconName = iconName - localize() - } - - // ---------------------------------------------------------------------- - // LOCALIZATION - // ---------------------------------------------------------------------- - - private fun localize() { - menuName = VlibProperties.getString(menuIdent) - menuItem = VlibProperties.getString(ident) - help = VlibProperties.getString("$ident-help") - } -} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VGroupRow.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VGroupRow.kt deleted file mode 100644 index 23a5b6af1..000000000 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VGroupRow.kt +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN - * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -package org.kopi.galite.visual.pivotTable - -/** - * Represents a description for a grouping row - * - * @param data The grouping row data - * @param level the grouping row level - */ -class VGroupRow(data: Array, private val level: Int) : VReportRow(data) { - - /** - * Sets data row - * - * @param column the index of the column - * @param value the value for the column - */ - override fun setValueAt(column: Int, value: Any?) { - data[column] = value - } - - /** - * Return the level of the node in the grouping tree - */ - override fun getLevel(): Int { - return level - } - - private fun setChildNodesInvisible() { - visible = false - if (getLevel() > 0) { - for (i in 0 until childCount) { - val row = getChildAt(i) as VReportRow - if (row is VGroupRow) { - row.setChildNodesInvisible() - } else { - row.visible = false - } - } - } - } - - companion object { - private const val serialVersionUID = 0L - } -} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VHelpGenerator.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VHelpGenerator.kt deleted file mode 100644 index 87400c692..000000000 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VHelpGenerator.kt +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN - * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -package org.kopi.galite.visual.pivotTable - -import java.io.BufferedWriter -import java.io.File -import java.io.FileOutputStream -import java.io.IOException -import java.io.OutputStreamWriter -import java.io.PrintWriter - -import org.kopi.galite.visual.base.Utils -import org.kopi.galite.visual.VCommand -import org.kopi.galite.visual.VHelpGenerator - -/** - * This class implements a pretty printer - */ -class VHelpGenerator : VHelpGenerator() { - // ---------------------------------------------------------------------- - // ACCESSORS - // ---------------------------------------------------------------------- - /** - * prints a compilation unit - */ - fun helpOnReport(name: String, - commands: List, - model: MPivotTable, - help: String?): String? { - return try { - val file: File = Utils.getTempFile(name.replace("[:\\\\/*\"?|<>']".toRegex(), " "), "htm") - printer = PrintWriter(BufferedWriter(OutputStreamWriter(FileOutputStream(file), "UTF-8"))) - printer.println("") - printer.println("") - printer.println("
") - printer.println("$name") - printer.println("") - printer.println("") - printer.println("") - printer.println("") - printer.println("") - printer.println("") - printer.println("") - printer.println("

$name

") - if (help != null) { - printer.println("

$help

") - } - helpOnCommands(commands) - val columnCount: Int = model.getModelColumnCount() - printer.println("") - printer.println("") - printer.println("") - printer.println("") - printer.println("") - printer.println("
    
") - printer.println("
") - printer.println("
") - printer.println("
") - printer.println("
") - printer.println("
") - printer.println("
") - printer.println("kopiLeft Services SARL, Tunis TN
") - printer.println("kopiRight Managed Solutions GmbH, Wien AT
") - val version = Utils.getVersion() - for (i in version.indices) { - printer.println("" + version[i] + "
") - } - printer.println("
") - printer.println("
") - printer.println("") - printer.println("") - printer.close() - file.path - } catch (e: IOException) { - System.err.println("IO ERROR $e") - null - } - } -} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VPivotTable.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VPivotTable.kt index 090f63e41..15dd9f121 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VPivotTable.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VPivotTable.kt @@ -18,28 +18,20 @@ package org.kopi.galite.visual.pivotTable -import java.awt.event.KeyEvent -import java.io.File -import java.net.MalformedURLException - -import org.kopi.galite.visual.cross.VDynamicReport -import org.kopi.galite.visual.dsl.common.Trigger import org.kopi.galite.visual.form.VConstants import org.kopi.galite.visual.l10n.LocalizationManager -import org.kopi.galite.util.base.InconsistencyException import org.kopi.galite.visual.ApplicationContext import org.kopi.galite.visual.UIFactory import org.kopi.galite.visual.UWindow import org.kopi.galite.visual.VCommand -import org.kopi.galite.visual.VHelpViewer import org.kopi.galite.visual.VWindow import org.kopi.galite.visual.WindowBuilder import org.kopi.galite.visual.WindowController /** - * Represents a report model. + * Represents a pivot table model. */ -abstract class VPivotTable internal constructor() : VWindow(), Constants, VConstants { +abstract class VPivotTable internal constructor() : VWindow(), VConstants { companion object { init { @@ -88,7 +80,7 @@ abstract class VPivotTable internal constructor() : VWindow(), Constants, VConst */ protected fun build() { init() - // localize the report using the default locale + // localize the pivot table using the default locale localize() model.build() (getDisplay() as UPivotTable?)?.build() @@ -99,6 +91,7 @@ abstract class VPivotTable internal constructor() : VWindow(), Constants, VConst commands.forEachIndexed { i, vCommand -> setCommandEnabled(vCommand, true) } + } // ---------------------------------------------------------------------- // LOCALIZATION @@ -108,7 +101,7 @@ abstract class VPivotTable internal constructor() : VWindow(), Constants, VConst } /** - * Localizes this report + * Localizes this pivot table * */ open fun localize() { @@ -116,7 +109,7 @@ abstract class VPivotTable internal constructor() : VWindow(), Constants, VConst } /** - * Localizes this report + * Localizes this pivot table * * @param manager the manger to use for localization */ @@ -133,7 +126,7 @@ abstract class VPivotTable internal constructor() : VWindow(), Constants, VConst // ---------------------------------------------------------------------- // DISPLAY INTERFACE // ---------------------------------------------------------------------- - open fun initReport() { + open fun initPivotTable() { build() } // ---------------------------------------------------------------------- @@ -161,16 +154,9 @@ abstract class VPivotTable internal constructor() : VWindow(), Constants, VConst setTitle(title) } - fun getColumn(i: Int): VReportColumn { - return model.getModelColumn(i) - } - // ---------------------------------------------------------------------- // PRIVATE METHODS // ---------------------------------------------------------------------- - override fun executeVoidTrigger(trigger: Trigger?) { - trigger?.action?.method?.invoke() - } fun setMenu() { if (!built) { @@ -180,44 +166,13 @@ abstract class VPivotTable internal constructor() : VWindow(), Constants, VConst } // ---------------------------------------------------------------------- - // HELP + // Command // ---------------------------------------------------------------------- - fun genHelp(): String? { - val surl = StringBuffer() - val fileName: String? = VHelpGenerator().helpOnReport(pageTitle, - commands, - model, - help) - - return if (fileName == null) { - null - } else { - try { - surl.append(File(fileName).toURI().toURL().toString()) - } catch (mue: MalformedURLException) { - throw InconsistencyException(mue) - } - surl.toString() - } - } - - fun showHelp() { - VHelpViewer().showHelp(genHelp()) - } - - fun addDefaultReportCommands() { - initDefaultActors() + fun addDefaultPivotTableCommands() { initDefaultCommands() } - private fun initDefaultActors() { - addActors(arrayOf( - VDefaultReportActor("File", "Quit", VDynamicReport.QUIT_ICON, KeyEvent.VK_ESCAPE, 0), - VDefaultReportActor("Help", "Help", VDynamicReport.HELP_ICON, KeyEvent.VK_F1, 0), - )) - } - private fun initDefaultCommands() { actors.forEachIndexed { index, vActor -> commands.add(VCommand(VConstants.MOD_ANY, this, vActor, index, vActor.ident)) diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VReportColumn.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VPivotTableColumn.kt similarity index 78% rename from galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VReportColumn.kt rename to galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VPivotTableColumn.kt index 5abd23b25..912060942 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VReportColumn.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VPivotTableColumn.kt @@ -20,25 +20,20 @@ package org.kopi.galite.visual.pivotTable import org.kopi.galite.visual.l10n.FieldLocalizer import org.kopi.galite.visual.l10n.ReportLocalizer -import org.kopi.galite.visual.util.LineBreaker /** - * Represents a report column description + * Represents a pivot table column description * * @param ident The identifier of the field * */ -class VReportColumn( - val ident: String?) { +class VPivotTableColumn(val ident: String?) { // ---------------------------------------------------------------------- // DATA MEMBERS // ---------------------------------------------------------------------- var label: String = "" var help: String? = null - var isVisible: Boolean = true - open var isFolded: Boolean = false - var isAddedAtRuntime: Boolean = false // ---------------------------------------------------------------------- // LOCALIZATION @@ -54,16 +49,6 @@ class VReportColumn( label = loc.getLabel() ?: "" help = loc.getHelp() - localize(loc) } } - - /** - * Localizes this field - * - * @param parentLocalizer the caller localizer - */ - protected open fun localize(parentLocalizer: FieldLocalizer) { - // by default nothing to do - } } diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VBaseRow.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VPivotTableRow.kt similarity index 74% rename from galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VBaseRow.kt rename to galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VPivotTableRow.kt index 407f1eda2..12b739d30 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VBaseRow.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VPivotTableRow.kt @@ -18,11 +18,17 @@ package org.kopi.galite.visual.pivotTable -class VBaseRow(data: Array) : VReportRow(data) { +import javax.swing.tree.DefaultMutableTreeNode + +class VPivotTableRow(val data: Array) : DefaultMutableTreeNode() { + /** - * Return the level of the node. For base rows it is always 0 + * Return the object at column + * + * @param column the index of the column + * @return the object to be displayed */ - override fun getLevel(): Int = 0 + fun getValueAt(column: Int): Any? = data[column] companion object { private const val serialVersionUID = 0L diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VReportRow.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VReportRow.kt deleted file mode 100644 index f038a3fb6..000000000 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VReportRow.kt +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN - * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -package org.kopi.galite.visual.pivotTable - -import javax.swing.tree.DefaultMutableTreeNode - -abstract class VReportRow(val data: Array) : DefaultMutableTreeNode() { - var visible = false - - /** - * Return the level of the node in the grouping tree, starting with 0 at - * the base rows (leafs). - * - * @return the level of the node in the grouping tree - */ - abstract override fun getLevel(): Int - - /** - * Return the object at column - * - * @param column the index of the column - * @return the object to be displayed - */ - fun getValueAt(column: Int): Any? = data[column] - - /** - * Sets data at column of certain index - * - * @param column the index of the column - * @param value the value for the column - */ - open fun setValueAt(column: Int, value: Any?) { - data[column] = value - } - - /** - * Clone Array's objects - */ - fun cloneArray() = data.clone() - - companion object { - private const val serialVersionUID = 0L - } -} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/DPivotTable.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/DPivotTable.kt index 0e31d84a0..3485d0072 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/DPivotTable.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/DPivotTable.kt @@ -17,8 +17,6 @@ */ package org.kopi.galite.visual.ui.vaadin.pivotTable -import java.awt.Color - import org.kopi.galite.visual.pivotTable.MPivotTable import org.kopi.galite.visual.pivotTable.UPivotTable import org.kopi.galite.visual.pivotTable.VPivotTable @@ -45,7 +43,7 @@ class DPivotTable(private val report: VPivotTable) : DWindow(report), UPivotTabl // IMPLEMENTATIONS //--------------------------------------------------- override fun run() { - report.initReport() + report.initPivotTable() report.setMenu() } @@ -53,18 +51,16 @@ class DPivotTable(private val report: VPivotTable) : DWindow(report), UPivotTabl model.columns.forEach { if(it?.label != "") { - println("column : " + it?.label) pivotData.addColumn(it?.label, it?.javaClass) } } - model.baseRows.forEach { - it?.data?.forEach { row -> + model.userRows?.forEach { + it.data.forEach { row -> if(row != null) { listeRows.add(row) } } - println("rows : " + listeRows) pivotData.addRow(*listeRows.toTypedArray()) listeRows.clear() } diff --git a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/bill/BillP.kt b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/bill/BillP.kt index 4153729ff..036f42f50 100644 --- a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/bill/BillP.kt +++ b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/bill/BillP.kt @@ -32,7 +32,7 @@ import org.kopi.galite.visual.dsl.pivotTable.PivotTable /** * Bill Report */ -class BillP : PivotTable("Bills_Report", locale = Locale.UK) { +class BillP : PivotTable("Bills_Pivot_Table", locale = Locale.UK) { val file = menu("File") From e96fc9e0c5ed17c172fda158b3fb51fa3940f831 Mon Sep 17 00:00:00 2001 From: Super User Date: Thu, 19 Oct 2023 14:14:02 +0100 Subject: [PATCH 06/20] Add dimension to the field --- .../visual/dsl/pivotTable/PivotTableField.kt | 6 +- .../visual/pivotTable/VPivotTableColumn.kt | 3 +- .../ui/vaadin/pivotTable/DPivotTable.kt | 5 + .../kotlin/org/kopi/galite/demo/bill/BillP.kt | 4 + .../org/kopi/galite/demo/client/ClientForm.kt | 11 ++ .../org/kopi/galite/demo/client/ClientP.kt | 111 ++++++++++++++++++ 6 files changed, 137 insertions(+), 3 deletions(-) create mode 100644 galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/client/ClientP.kt diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTableField.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTableField.kt index d12ae6141..9f39d79fc 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTableField.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTableField.kt @@ -27,6 +27,10 @@ class PivotTableField(override val domain: Domain, ident: String? = null, override val source: String?) : Field(domain, ident) { + /** + * Dimension values + */ + var dimension: Boolean? = null fun initField() { init() } @@ -36,7 +40,7 @@ class PivotTableField(override val domain: Domain, fun buildReportColumn(): VPivotTableColumn { model = domain.buildReportFieldModel(this).also { column -> column.label = label ?: "" - column.help = help + column.dimension = dimension } return model diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VPivotTableColumn.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VPivotTableColumn.kt index 912060942..c78ae5771 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VPivotTableColumn.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VPivotTableColumn.kt @@ -33,7 +33,7 @@ class VPivotTableColumn(val ident: String?) { // DATA MEMBERS // ---------------------------------------------------------------------- var label: String = "" - var help: String? = null + var dimension: Boolean? = null // ---------------------------------------------------------------------- // LOCALIZATION @@ -48,7 +48,6 @@ class VPivotTableColumn(val ident: String?) { val loc: FieldLocalizer = parent.getFieldLocalizer(ident!!) label = loc.getLabel() ?: "" - help = loc.getHelp() } } } diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/DPivotTable.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/DPivotTable.kt index 3485d0072..3f6ac2d9c 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/DPivotTable.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/DPivotTable.kt @@ -33,6 +33,7 @@ class DPivotTable(private val report: VPivotTable) : DWindow(report), UPivotTabl private var pivotData = PivotTable.PivotData() private var pivotOptions = PivotTable.PivotOptions() private var listeRows = mutableListOf() + private var listeDimensions = mutableListOf() init { getModel()!!.setDisplay(this) @@ -53,6 +54,9 @@ class DPivotTable(private val report: VPivotTable) : DWindow(report), UPivotTabl if(it?.label != "") { pivotData.addColumn(it?.label, it?.javaClass) } + if (it?.dimension != null && it.dimension!!) { + listeDimensions.add(it.label) + } } model.userRows?.forEach { @@ -64,6 +68,7 @@ class DPivotTable(private val report: VPivotTable) : DWindow(report), UPivotTabl pivotData.addRow(*listeRows.toTypedArray()) listeRows.clear() } + pivotOptions.setCols(*listeDimensions.toTypedArray()) var pivot = PivotTable(pivotData, pivotOptions, PivotTable.PivotMode.INTERACTIVE) add(pivot) diff --git a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/bill/BillP.kt b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/bill/BillP.kt index 036f42f50..6089b05b4 100644 --- a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/bill/BillP.kt +++ b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/bill/BillP.kt @@ -48,15 +48,18 @@ class BillP : PivotTable("Bills_Pivot_Table", locale = Locale.UK) { val numBill = field(INT(25)) { label = "Number" help = "The bill number" + dimension = true } val addressBill = field(STRING(25)) { label = "Address" help = "The bill address" + dimension = true } val dateBill = field(DATE) { label = "Date" help = "The bill date" + dimension = true } val amountWithTaxes = field(DECIMAL(20, 10)) { @@ -67,6 +70,7 @@ class BillP : PivotTable("Bills_Pivot_Table", locale = Locale.UK) { val refCmd = field(INT(50)) { label = "Command reference" help = "The command reference" + dimension = true } val bills = Bill.selectAll() diff --git a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/client/ClientForm.kt b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/client/ClientForm.kt index 1fcf2012d..13bf212de 100644 --- a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/client/ClientForm.kt +++ b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/client/ClientForm.kt @@ -21,6 +21,7 @@ import java.util.Locale import org.jetbrains.exposed.sql.SqlExpressionBuilder import org.jetbrains.exposed.sql.stringLiteral import org.jetbrains.exposed.sql.transactions.transaction +import org.kopi.galite.demo.bill.BillP import org.kopi.galite.demo.command.CommandR import org.kopi.galite.demo.database.Client @@ -136,6 +137,11 @@ class ClientForm : DictionaryForm(title = "Clients", locale = Locale.UK) { ClientR() } } + command(item = pivotTable) { + createPivotTable { + ClientP() + } + } command(item = dynamicReport) { createDynamicReport() } @@ -197,6 +203,11 @@ class ClientForm : DictionaryForm(title = "Clients", locale = Locale.UK) { ClientR() } } + command(item = pivotTable) { + createPivotTable { + ClientP() + } + } command(item = dynamicReport) { createDynamicReport() } diff --git a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/client/ClientP.kt b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/client/ClientP.kt new file mode 100644 index 000000000..4150aa467 --- /dev/null +++ b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/client/ClientP.kt @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +package org.kopi.galite.demo.client + +import java.util.Locale + +import org.jetbrains.exposed.sql.selectAll +import org.jetbrains.exposed.sql.transactions.transaction +import org.kopi.galite.demo.database.Client +import org.kopi.galite.visual.domain.BOOL +import org.kopi.galite.visual.domain.INT +import org.kopi.galite.visual.domain.STRING +import org.kopi.galite.visual.dsl.common.Icon +import org.kopi.galite.visual.dsl.form.Key +import org.kopi.galite.visual.dsl.pivotTable.PivotTable + +/** + * Client Report + */ +class ClientP : PivotTable(title = "Clients_Report", locale = Locale.UK) { + val action = menu("Action") + val file = menu("File") + + val quit = actor(menu = file, label = "Quit", help = "Close Report.", ident = "quit") { + key = Key.ESCAPE + icon = Icon.QUIT + } + + val helpForm = actor(menu = action, label = "Help", help = " Help", ident = "help") { + key = Key.F1 + icon = Icon.HELP + } + + val cmdQuit = command(item = quit) { + model.close() + } + + + val firstName = field(STRING(25)) { + label = "First Name" + help = "The client first name" + } + + val lastName = field(STRING(25)) { + label = "Last Name" + help = "The client last name" + } + + val addressClt = field(STRING(50)) { + label = "Address" + help = "The client address" + } + + val ageClt = field(INT(2)) { + label = "Age" + help = "The client age" + } + + val countryClt = field(STRING(50)) { + label = "Country" + help = "The client country" + } + + val cityClt = field(STRING(50)) { + label = "City" + help = "The client city" + } + + val zipCodeClt = field(INT(2)) { + label = "Zip code" + help = "The client zip code" + } + + val activeClt = field(BOOL) { + label = "Status" + help = "Is the client active?" + } + + val clients = Client.selectAll() + + init { + transaction { + clients.forEach { result -> + add { + this[firstName] = result[Client.firstNameClt] + this[lastName] = result[Client.lastNameClt] + this[addressClt] = result[Client.addressClt] + this[ageClt] = result[Client.ageClt] + this[countryClt] = result[Client.countryClt] + this[cityClt] = result[Client.cityClt] + this[zipCodeClt] = result[Client.zipCodeClt] + this[activeClt] = result[Client.activeClt] + } + } + } + } +} From c51baebb91f051475fbf0f008bc575d2e02fc9cc Mon Sep 17 00:00:00 2001 From: Super User Date: Thu, 19 Oct 2023 17:12:32 +0100 Subject: [PATCH 07/20] optimiser le traitement d'affichage --- .../ui/vaadin/pivotTable/DPivotTable.kt | 29 ++++++++----------- .../galite/tests/examples/CommandsForm.kt | 3 -- .../tests/examples/PivotTableExample.kt | 12 ++------ gradle.properties | 2 +- 4 files changed, 16 insertions(+), 30 deletions(-) diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/DPivotTable.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/DPivotTable.kt index 3f6ac2d9c..00c29fe30 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/DPivotTable.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/DPivotTable.kt @@ -32,8 +32,7 @@ class DPivotTable(private val report: VPivotTable) : DWindow(report), UPivotTabl private val model: MPivotTable = report.model // report model private var pivotData = PivotTable.PivotData() private var pivotOptions = PivotTable.PivotOptions() - private var listeRows = mutableListOf() - private var listeDimensions = mutableListOf() + private val listeDimensions = mutableListOf() init { getModel()!!.setDisplay(this) @@ -50,27 +49,23 @@ class DPivotTable(private val report: VPivotTable) : DWindow(report), UPivotTabl override fun build() { - model.columns.forEach { - if(it?.label != "") { + model.columns + .forEach { pivotData.addColumn(it?.label, it?.javaClass) + if (it?.dimension == true) { + listeDimensions.add(it.label) + } } - if (it?.dimension != null && it.dimension!!) { - listeDimensions.add(it.label) - } - } - model.userRows?.forEach { - it.data.forEach { row -> - if(row != null) { - listeRows.add(row) - } + model.userRows + ?.flatMap { it.data.filterNotNull() } + ?.chunked(model.columns.count()) { rows -> + pivotData.addRow(*rows.toTypedArray()) } - pivotData.addRow(*listeRows.toTypedArray()) - listeRows.clear() - } + pivotOptions.setCols(*listeDimensions.toTypedArray()) + val pivot = PivotTable(pivotData, pivotOptions, PivotTable.PivotMode.INTERACTIVE) - var pivot = PivotTable(pivotData, pivotOptions, PivotTable.PivotMode.INTERACTIVE) add(pivot) } } diff --git a/galite-tests/src/test/kotlin/org/kopi/galite/tests/examples/CommandsForm.kt b/galite-tests/src/test/kotlin/org/kopi/galite/tests/examples/CommandsForm.kt index 558485bf0..d7edc8219 100644 --- a/galite-tests/src/test/kotlin/org/kopi/galite/tests/examples/CommandsForm.kt +++ b/galite-tests/src/test/kotlin/org/kopi/galite/tests/examples/CommandsForm.kt @@ -117,9 +117,6 @@ class CommandsForm : DictionaryForm(title = "Commands Form", locale = Locale.UK) command(item = insertMode) { insertMode() } - command(item = pivottable) { - PivotTableExample().doNotModal() - } } } diff --git a/galite-tests/src/test/kotlin/org/kopi/galite/tests/examples/PivotTableExample.kt b/galite-tests/src/test/kotlin/org/kopi/galite/tests/examples/PivotTableExample.kt index 314666b32..667caebf1 100644 --- a/galite-tests/src/test/kotlin/org/kopi/galite/tests/examples/PivotTableExample.kt +++ b/galite-tests/src/test/kotlin/org/kopi/galite/tests/examples/PivotTableExample.kt @@ -20,34 +20,28 @@ import java.util.Locale import org.kopi.galite.visual.domain.INT import org.kopi.galite.visual.domain.STRING -import org.kopi.galite.visual.pivottable.Function -import org.kopi.galite.visual.pivottable.Grouping -import org.kopi.galite.visual.pivottable.PivotTable +import org.kopi.galite.visual.dsl.pivotTable.PivotTable class PivotTableExample : PivotTable(title = "Form to test Blocks", locale = Locale.UK) { val city = field(STRING(15)) { label = "Country" - help = "The country" + dimension = true } val delegation = field(STRING(15)) { label = "Delegation" - help = "The delegation" + dimension = true } val gender = field(STRING(6)) { label = "Gender" - help = "The gender" } val age = field(INT(3)) { label = "Age" - help = "The age" } init { - aggregate(Function.SUM, age) - grouping = Grouping(listOf(city), listOf(delegation, gender)) add { this[city] = "Ben Arous" diff --git a/gradle.properties b/gradle.properties index ce7b320fb..68ea47791 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.jvmargs=-Xmx4g # group=org.kopi -version=1.4.1 +version=1.4.1-01QYB From ae802e29fd3f16d7dd10ce17ab9cb7a1d00b3d89 Mon Sep 17 00:00:00 2001 From: Super User Date: Fri, 20 Oct 2023 17:10:18 +0100 Subject: [PATCH 08/20] =?UTF-8?q?impl=C3=A9mentation=20des=20tests=20autom?= =?UTF-8?q?atiques?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/kopi/galite/visual/domain/Domain.kt | 2 +- .../visual/dsl/pivotTable/PivotTable.kt | 46 ++- .../visual/dsl/pivotTable/PivotTableField.kt | 4 +- .../PivotTableLocalizationWriter.kt | 19 +- .../visual/dsl/pivotTable/PivotTableRow.kt | 18 +- .../galite/visual/l10n/LocalizationManager.kt | 9 + .../galite/visual/l10n/PivotTableLocalizer.kt | 66 ++++ .../galite/visual/pivotTable/VPivotTable.kt | 6 +- .../visual/pivotTable/VPivotTableColumn.kt | 4 +- .../ui/vaadin/pivotTable/DPivotTable.kt | 8 +- .../org/kopi/galite/demo/bill/BillForm.kt | 1 - .../org/kopi/galite/tests/common/TestBase.kt | 26 ++ .../tests/ui/swing/JApplicationTestBase.kt | 2 + .../tests/ui/vaadin/VApplicationTestBase.kt | 4 + .../org/kopi/galite/test/Menu-en_GB.xml | 2 + .../galite/tests/dsl/PivotTableDSLTests.kt | 96 +++++ .../tests/examples/DocumentationPivotTable.kt | 64 ++++ .../tests/examples/DocumentationReport.kt | 11 +- .../org/kopi/galite/tests/examples/Modules.kt | 2 + .../tests/examples/PivotTableExample.kt | 341 ------------------ .../galite/tests/form/FormWithPivotTable.kt | 44 +++ .../tests/pivotTable/PivotTableTests.kt | 148 ++++++++ .../kopi/galite/tests/pivotTable/VRowTests.kt | 36 ++ 23 files changed, 561 insertions(+), 398 deletions(-) create mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/l10n/PivotTableLocalizer.kt create mode 100644 galite-tests/src/test/kotlin/org/kopi/galite/tests/dsl/PivotTableDSLTests.kt create mode 100644 galite-tests/src/test/kotlin/org/kopi/galite/tests/examples/DocumentationPivotTable.kt delete mode 100644 galite-tests/src/test/kotlin/org/kopi/galite/tests/examples/PivotTableExample.kt create mode 100644 galite-tests/src/test/kotlin/org/kopi/galite/tests/form/FormWithPivotTable.kt create mode 100644 galite-tests/src/test/kotlin/org/kopi/galite/tests/pivotTable/PivotTableTests.kt create mode 100644 galite-tests/src/test/kotlin/org/kopi/galite/tests/pivotTable/VRowTests.kt diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/domain/Domain.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/domain/Domain.kt index 66239bb59..c8c6f40ec 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/domain/Domain.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/domain/Domain.kt @@ -277,7 +277,7 @@ open class Domain(val width: Int? = null, /** * Builds the pivot table column model */ - open fun buildReportFieldModel(field: org.kopi.galite.visual.dsl.pivotTable.PivotTableField<*>): org.kopi.galite.visual.pivotTable.VPivotTableColumn { + open fun buildPivotTableFieldModel(field: org.kopi.galite.visual.dsl.pivotTable.PivotTableField<*>): org.kopi.galite.visual.pivotTable.VPivotTableColumn { return with(field) { when (kClass) { Int::class, Long::class, String::class, BigDecimal::class, Boolean::class, org.joda.time.LocalDate::class, LocalDate::class, java.sql.Date::class, java.util.Date::class, Month::class, Week::class, org.joda.time.LocalTime::class, LocalTime::class, Instant::class, LocalDateTime::class, DateTime::class -> diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTable.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTable.kt index 844d17cfc..4d6a5ffed 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTable.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTable.kt @@ -20,21 +20,23 @@ package org.kopi.galite.visual.dsl.pivotTable import java.io.IOException import java.util.Locale +import org.kopi.galite.visual.ApplicationContext import org.kopi.galite.visual.domain.Domain import org.kopi.galite.visual.dsl.common.LocalizationWriter import org.kopi.galite.visual.dsl.common.Window import org.kopi.galite.visual.pivotTable.VPivotTable -import org.kopi.galite.visual.ApplicationContext abstract class PivotTable(title: String, val help: String?, locale: Locale? = null) : Window(title, locale) { constructor(title: String, locale: Locale? = null) : this(title, null, locale) - /** Report's fields. */ + /** Pivot table's fields. */ val fields = mutableListOf>() - /** Report's data rows. */ - val reportRows = mutableListOf() + var positionfield = 0 + + /** Pivot table's data rows. */ + val pivotTableRows = mutableListOf() /** * creates and returns a field. It uses [init] method to initialize the field. @@ -51,9 +53,9 @@ abstract class PivotTable(title: String, val help: String?, locale: Locale? = nu field.initField() - val pos = if(model.model.columns.size == 0) 0 else model.model.columns.size - 1 - model.model.columns.add(pos, field.buildReportColumn()) + model.model.columns.add(positionfield, field.buildPivotTableColumn()) fields.add(field) + positionfield ++ return field } @@ -89,22 +91,22 @@ abstract class PivotTable(title: String, val help: String?, locale: Locale? = nu } /** - * Adds a row to the report. + * Adds a row to the Pivot table. * * @param init initializes the row with values. */ - fun add(init: ReportRow.() -> Unit) { - val row = ReportRow(fields) + fun add(init: PivotTableRow.() -> Unit) { + val row = PivotTableRow(fields) row.init() - val list = row.addReportLine() + val list = row.addLine() // Last null value is added for the separator column model.model.addLine((list + listOf(null)).toTypedArray()) - reportRows.add(row) + pivotTableRows.add(row) } - private fun ReportRow.addReportLine(): List { + private fun PivotTableRow.addLine(): List { return fields.map { field -> data[field] } @@ -115,12 +117,18 @@ abstract class PivotTable(title: String, val help: String?, locale: Locale? = nu * * @param rowNumber the index of the desired row. */ - fun getRow(rowNumber: Int): MutableMap, Any?> = reportRows[rowNumber].data + fun getRow(rowNumber: Int): MutableMap, Any?> = pivotTableRows[rowNumber].data /** - * Adds default report commands + * Returns rows of data for a specific [field]. + * + * @param field the field. + */ + fun getRowsForField(field: PivotTableField<*>) = pivotTableRows.map { it.data[field] } + /** + * Adds default Pivot table commands */ - open val reportCommands = false + open val pivotTableCommands = false fun setMenu() { model.setMenu() @@ -157,11 +165,11 @@ abstract class PivotTable(title: String, val help: String?, locale: Locale? = nu } fun genLocalization(writer: LocalizationWriter) { - (writer as PivotTableLocalizationWriter).genReport(title, help, fields, menus, actors) + (writer as PivotTableLocalizationWriter).genPivotTable(title, fields, menus, actors) } // ---------------------------------------------------------------------- - // REPORT MODEL + // Pivot table MODEL // ---------------------------------------------------------------------- override val model: VPivotTable = object : VPivotTable() { @@ -180,7 +188,7 @@ abstract class PivotTable(title: String, val help: String?, locale: Locale? = nu model.help = help model.source = sourceFile - if (reportCommands) { + if (pivotTableCommands) { addDefaultPivotTableCommands() } } @@ -188,4 +196,4 @@ abstract class PivotTable(title: String, val help: String?, locale: Locale? = nu @PublishedApi internal val `access$sourceFile`: String get() = sourceFile -} \ No newline at end of file +} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTableField.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTableField.kt index 9f39d79fc..64b9bd6e9 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTableField.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTableField.kt @@ -37,8 +37,8 @@ class PivotTableField(override val domain: Domain, lateinit var model: VPivotTableColumn - fun buildReportColumn(): VPivotTableColumn { - model = domain.buildReportFieldModel(this).also { column -> + fun buildPivotTableColumn(): VPivotTableColumn { + model = domain.buildPivotTableFieldModel(this).also { column -> column.label = label ?: "" column.dimension = dimension } diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTableLocalizationWriter.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTableLocalizationWriter.kt index 372ff8d46..d9ffd9477 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTableLocalizationWriter.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTableLocalizationWriter.kt @@ -26,17 +26,14 @@ import org.kopi.galite.visual.dsl.common.Menu * This class implements an XML localization file generator */ class PivotTableLocalizationWriter : LocalizationWriter() { - fun genReport(title: String?, - help: String?, - fields: MutableList>, - menus: MutableList, - actors: MutableList) { - val self = Element("report") + fun genPivotTable(title: String?, + fields: MutableList>, + menus: MutableList, + actors: MutableList) { + val self = Element("pivotTable") self.setAttribute("title", title) - if (help != null) { - self.setAttribute("help", help) - } + pushNode(self) // Menus @@ -61,9 +58,7 @@ class PivotTableLocalizationWriter : LocalizationWriter() { if (label != null) { self.setAttribute("label", label) } - if (help != null) { - self.setAttribute("help", help) - } + peekNode(null).addContent(self) } } diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTableRow.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTableRow.kt index fe3025fa9..612a1ca2e 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTableRow.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTableRow.kt @@ -25,14 +25,14 @@ import org.kopi.galite.type.Week /** * Represents a data row of a [PivotTable]. * - * @param reportFields the fields that exists in the report. + * @param pivotTableFields the fields that exists in the pivot table. */ -class ReportRow(private val reportFields: MutableList>) { - /** A report data row */ +class PivotTableRow(private val pivotTableFields: MutableList>) { + /** A pivot table data row */ val data = mutableMapOf, Any?>() /** - * Returns data value of a specific [PivotTableField] in this report row. + * Returns data value of a specific [PivotTableField] in this pivot table row. * * @param field the field. * @return data value for a specific [PivotTableField]. @@ -41,7 +41,7 @@ class ReportRow(private val reportFields: MutableList>) { fun getValueOf(field: PivotTableField): T = data[field] as T /** - * Gets the value of the field in this report row. + * Gets the value of the field in this pivot table row. * * @param field the field. * @return data value for a specific [PivotTableField]. @@ -49,26 +49,26 @@ class ReportRow(private val reportFields: MutableList>) { operator fun get(field: PivotTableField): T = getValueOf(field) /** - * Sets the value of the field in this report row. + * Sets the value of the field in this pivot table row. * * @param field the field. * @param value the field's value. */ operator fun set(field: PivotTableField, value: T) { - if (field in reportFields) { + if (field in pivotTableFields) { data.putIfAbsent(field, value) } } /** - * Sets the value of the field in this report row. + * Sets the value of the field in this pivot table row. * * @param field the field. * @param value the field's value. */ @JvmName("setType0") operator fun , K> set(field: PivotTableField, value: K) { - if (field in reportFields) { + if (field in pivotTableFields) { data.putIfAbsent(field, field.toType0(value)) } } diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/l10n/LocalizationManager.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/l10n/LocalizationManager.kt index 0271ca8a9..f48c20445 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/l10n/LocalizationManager.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/l10n/LocalizationManager.kt @@ -115,6 +115,15 @@ class LocalizationManager(val locale: Locale?, private val defaultLocale: Locale return ChartLocalizer(this, getDocument(source)) } + /** + * Constructs a chart localizer using the specified source. + * + * @param source the source qualified name + */ + fun getPivotTableLocalizer(source: String?): PivotTableLocalizer { + return PivotTableLocalizer(this, getDocument(source)) + } + /** * Constructs a module localizer using the specified source. * diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/l10n/PivotTableLocalizer.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/l10n/PivotTableLocalizer.kt new file mode 100644 index 000000000..555aa02e1 --- /dev/null +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/l10n/PivotTableLocalizer.kt @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package org.kopi.galite.visual.l10n + +import org.jdom2.Document +import org.jdom2.Element +import org.kopi.galite.util.base.InconsistencyException + +/** + * Implements a pivot table localizer. + * + * @param manager the manager to use for localization + * @param document the document containing the pivot table localization + */ +class PivotTableLocalizer(manager: LocalizationManager, document: Document) : Localizer(manager) { + + // ---------------------------------------------------------------------- + // DATA MEMBERS + // ---------------------------------------------------------------------- + private val root: Element = document.rootElement + + // ---------------------------------------------------------------------- + // CONSTRUCTOR + // ---------------------------------------------------------------------- + init { + if (root.name != "pivottable") { + throw InconsistencyException("bad root element $root") + } + } + + /** + * Returns the value of the title attribute. + */ + fun getTitle(): String = root.getAttributeValue("title") + + /** + * Returns the value of the help attribute. + */ + fun getHelp(): String? = root.getAttributeValue("help") + + /** + * Constructs a field localizer for the given field. + * + * @param ident the identifier of the field + */ + fun getFieldLocalizer(ident: String): FieldLocalizer { + return FieldLocalizer(manager, + Utils.lookupChild(root, "field", "ident", ident)) + } +} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VPivotTable.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VPivotTable.kt index 15dd9f121..8aa25c655 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VPivotTable.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VPivotTable.kt @@ -18,9 +18,9 @@ package org.kopi.galite.visual.pivotTable +import org.kopi.galite.visual.ApplicationContext import org.kopi.galite.visual.form.VConstants import org.kopi.galite.visual.l10n.LocalizationManager -import org.kopi.galite.visual.ApplicationContext import org.kopi.galite.visual.UIFactory import org.kopi.galite.visual.UWindow import org.kopi.galite.visual.VCommand @@ -88,7 +88,7 @@ abstract class VPivotTable internal constructor() : VWindow(), VConstants { // all commands are by default enabled activeCommands.clear() - commands.forEachIndexed { i, vCommand -> + commands.forEach { vCommand -> setCommandEnabled(vCommand, true) } @@ -115,7 +115,7 @@ abstract class VPivotTable internal constructor() : VWindow(), VConstants { */ private fun localize(manager: LocalizationManager) { if(ApplicationContext.getDefaultLocale() != locale) { - val loc = manager.getReportLocalizer(source) + val loc = manager.getPivotTableLocalizer(source) setPageTitle(loc.getTitle()) help = loc.getHelp() diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VPivotTableColumn.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VPivotTableColumn.kt index c78ae5771..0b8af8d3a 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VPivotTableColumn.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VPivotTableColumn.kt @@ -19,7 +19,7 @@ package org.kopi.galite.visual.pivotTable import org.kopi.galite.visual.l10n.FieldLocalizer -import org.kopi.galite.visual.l10n.ReportLocalizer +import org.kopi.galite.visual.l10n.PivotTableLocalizer /** * Represents a pivot table column description @@ -43,7 +43,7 @@ class VPivotTableColumn(val ident: String?) { * * @param parent the caller localizer */ - fun localize(parent: ReportLocalizer) { + fun localize(parent: PivotTableLocalizer) { if (ident != "") { val loc: FieldLocalizer = parent.getFieldLocalizer(ident!!) diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/DPivotTable.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/DPivotTable.kt index 00c29fe30..e5d096890 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/DPivotTable.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/DPivotTable.kt @@ -24,12 +24,12 @@ import org.kopi.galite.visual.ui.vaadin.visual.DWindow import org.vaadin.addons.componentfactory.PivotTable -class DPivotTable(private val report: VPivotTable) : DWindow(report), UPivotTable { +class DPivotTable(private val pivotTable: VPivotTable) : DWindow(pivotTable), UPivotTable { //--------------------------------------------------- // DATA MEMBERS //--------------------------------------------------- - private val model: MPivotTable = report.model // report model + private val model: MPivotTable = pivotTable.model // report model private var pivotData = PivotTable.PivotData() private var pivotOptions = PivotTable.PivotOptions() private val listeDimensions = mutableListOf() @@ -43,8 +43,8 @@ class DPivotTable(private val report: VPivotTable) : DWindow(report), UPivotTabl // IMPLEMENTATIONS //--------------------------------------------------- override fun run() { - report.initPivotTable() - report.setMenu() + pivotTable.initPivotTable() + pivotTable.setMenu() } override fun build() { diff --git a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/bill/BillForm.kt b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/bill/BillForm.kt index 0e3d2c228..f52611aea 100644 --- a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/bill/BillForm.kt +++ b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/bill/BillForm.kt @@ -16,7 +16,6 @@ */ package org.kopi.galite.demo.bill -import org.kopi.galite.demo.command.CommandR import java.util.Locale import org.kopi.galite.demo.database.Bill diff --git a/galite-tests/src/main/kotlin/org/kopi/galite/tests/common/TestBase.kt b/galite-tests/src/main/kotlin/org/kopi/galite/tests/common/TestBase.kt index 923fbf3c6..a8bb79f4a 100644 --- a/galite-tests/src/main/kotlin/org/kopi/galite/tests/common/TestBase.kt +++ b/galite-tests/src/main/kotlin/org/kopi/galite/tests/common/TestBase.kt @@ -24,7 +24,11 @@ import org.kopi.galite.visual.base.UComponent import org.kopi.galite.visual.chart.UChart import org.kopi.galite.visual.chart.VChart import org.kopi.galite.visual.dsl.chart.Chart +import org.kopi.galite.visual.dsl.pivotTable.PivotTable import org.kopi.galite.visual.dsl.report.Report +import org.kopi.galite.visual.pivotTable.MPivotTable +import org.kopi.galite.visual.pivotTable.UPivotTable +import org.kopi.galite.visual.pivotTable.VPivotTable import org.kopi.galite.visual.report.MReport import org.kopi.galite.visual.report.UReport import org.kopi.galite.visual.report.VReport @@ -46,6 +50,8 @@ open class TestBase { open fun getChartDisplay(model: VChart): UComponent? = null + open fun getPivotTableDisplay(model: VPivotTable): UComponent? = null + /** * Tests operation on a report. * @@ -86,6 +92,26 @@ open class TestBase { } } + /** + * Tests operation on a pivot table. + * + * @param pivotTable The pivot table to test + * @param operations operations to apply on the pivot table + */ + fun withPivotTable(pivotTable: T, operations: (T.(model: MPivotTable) -> Unit)? = null) { + val display = getPivotTableDisplay(pivotTable.model) + + //assertNotNull(display) + + pivotTable.model.setDisplay( + (display as UPivotTable) + ) + + if (operations != null) { + pivotTable.operations(pivotTable.model.model) + } + } + // ---------------------------------------------------------------------- // Testing extension methods // ---------------------------------------------------------------------- diff --git a/galite-tests/src/main/kotlin/org/kopi/galite/tests/ui/swing/JApplicationTestBase.kt b/galite-tests/src/main/kotlin/org/kopi/galite/tests/ui/swing/JApplicationTestBase.kt index 1b1e916b1..9393b3710 100644 --- a/galite-tests/src/main/kotlin/org/kopi/galite/tests/ui/swing/JApplicationTestBase.kt +++ b/galite-tests/src/main/kotlin/org/kopi/galite/tests/ui/swing/JApplicationTestBase.kt @@ -32,6 +32,8 @@ import org.kopi.galite.visual.ImageHandler import org.kopi.galite.visual.PropertyException import org.kopi.galite.visual.UIFactory import org.kopi.galite.visual.WindowController +import org.kopi.galite.visual.pivotTable.VPivotTable +import org.kopi.galite.visual.ui.vaadin.pivotTable.DPivotTable import org.kopi.vkopi.lib.ui.swing.chart.DChart import org.kopi.vkopi.lib.ui.swing.report.DReport import org.kopi.vkopi.lib.ui.swing.visual.JApplication diff --git a/galite-tests/src/main/kotlin/org/kopi/galite/tests/ui/vaadin/VApplicationTestBase.kt b/galite-tests/src/main/kotlin/org/kopi/galite/tests/ui/vaadin/VApplicationTestBase.kt index 857d4d7a3..d1b11b236 100644 --- a/galite-tests/src/main/kotlin/org/kopi/galite/tests/ui/vaadin/VApplicationTestBase.kt +++ b/galite-tests/src/main/kotlin/org/kopi/galite/tests/ui/vaadin/VApplicationTestBase.kt @@ -42,6 +42,8 @@ import org.kopi.galite.visual.UIFactory import org.kopi.galite.visual.WindowController import com.vaadin.flow.router.Route +import org.kopi.galite.visual.pivotTable.VPivotTable +import org.kopi.galite.visual.ui.vaadin.pivotTable.DPivotTable /** * TestBase class for all tests. @@ -66,6 +68,8 @@ open class VApplicationTestBase : ApplicationTestBase() { override fun getChartDisplay(model: VChart): UComponent? = DChart(model).also { it.run() } + override fun getPivotTableDisplay(model: VPivotTable): UComponent? = DPivotTable(model).also { it.run() } + companion object { val applicationContext = VApplicationContext() val fileHandler = VFileHandler() diff --git a/galite-tests/src/main/resources/org/kopi/galite/test/Menu-en_GB.xml b/galite-tests/src/main/resources/org/kopi/galite/test/Menu-en_GB.xml index 559cdda3c..f496d3987 100644 --- a/galite-tests/src/main/resources/org/kopi/galite/test/Menu-en_GB.xml +++ b/galite-tests/src/main/resources/org/kopi/galite/test/Menu-en_GB.xml @@ -4,6 +4,8 @@ + + diff --git a/galite-tests/src/test/kotlin/org/kopi/galite/tests/dsl/PivotTableDSLTests.kt b/galite-tests/src/test/kotlin/org/kopi/galite/tests/dsl/PivotTableDSLTests.kt new file mode 100644 index 000000000..ad4b8f0fc --- /dev/null +++ b/galite-tests/src/test/kotlin/org/kopi/galite/tests/dsl/PivotTableDSLTests.kt @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +package org.kopi.galite.tests.dsl + +import java.util.Locale + +import kotlin.test.assertEquals + +import org.junit.Test +import org.kopi.galite.tests.ui.vaadin.VApplicationTestBase +import org.kopi.galite.visual.domain.INT +import org.kopi.galite.visual.domain.STRING +import org.kopi.galite.visual.dsl.pivotTable.PivotTable + +class PivotTableDSLTests : VApplicationTestBase() { + + @Test + fun `test generated model from a basic pivot table`() { + val pivotTable = BasicPivotTable() + val model = pivotTable.model + + assertEquals(pivotTable.locale, model.locale) + assertEquals(pivotTable.title, model.getTitle()) + assertEquals(pivotTable.help, model.help) + } + + @Test + fun `test pivot table fields`() { + val pivotTable = PivotTableWithData() + val pivotTableModel = pivotTable.model + + assertEquals(3, pivotTableModel.model.columns.size) + println(pivotTableModel.model.columns[0]!!.label) + println(pivotTableModel.model.columns[1]!!.label) + println(pivotTableModel.model.columns[2]!!.label) + assertEquals(pivotTable.firstName.label, pivotTableModel.model.columns[0]!!.label) + assertEquals(pivotTable.addressClt.label, pivotTableModel.model.columns[1]!!.label) + assertEquals(pivotTable.ageClt.label, pivotTableModel.model.columns[2]!!.label) + } +} + +class BasicPivotTable : PivotTable( + title = "Clients Pivot Table", + help = "This is a pivot table that contains information about clients", + locale = Locale.UK +) + +class PivotTableWithData : PivotTable(title = "Clients Pivot Table", locale = Locale.UK) { + + val firstName = field(STRING(25)) { + label = "First Name" + help = "The client first name" + } + + val addressClt = field(STRING(50)) { + label = "Address" + help = "The client address" + } + + val ageClt = field(INT(2)) { + label = "Age" + help = "The client age" + } + + init { + add { + this[firstName] = "client 1" + this[addressClt] = "Tunis" + this[ageClt] = 20 + } + add { + this[firstName] = "client 1" + this[addressClt] = "Bizerte" + this[ageClt] = 20 + } + add { + this[firstName] = "client 2" + this[addressClt] = "Ben Arous" + this[ageClt] = 30 + } + } +} diff --git a/galite-tests/src/test/kotlin/org/kopi/galite/tests/examples/DocumentationPivotTable.kt b/galite-tests/src/test/kotlin/org/kopi/galite/tests/examples/DocumentationPivotTable.kt new file mode 100644 index 000000000..d4c92334e --- /dev/null +++ b/galite-tests/src/test/kotlin/org/kopi/galite/tests/examples/DocumentationPivotTable.kt @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +package org.kopi.galite.tests.examples + +import java.util.Locale + +import org.jetbrains.exposed.sql.selectAll +import org.jetbrains.exposed.sql.transactions.transaction +import org.kopi.galite.visual.domain.INT +import org.kopi.galite.visual.domain.STRING +import org.kopi.galite.visual.dsl.pivotTable.PivotTable + +class DocumentationPivotTable : PivotTable(title = "Test Pivot Table", locale = Locale.UK) { + + + // test to upper Case format + align left + val name = field(STRING(25)) { + label = "Name" + help = "The name" + } + + // test to lower Case format + align right + val lastName = nullableField(STRING(25)) { + label = "last Name " + } + + // test normal format + align center + val middleName = nullableField(STRING(25)) { + label = "middleName" + } + + val age = nullableField(INT(25)) { + label = "age" + } + + val testTable = TestTable.selectAll() + + init { + transaction { + testTable.forEach { result -> + add { + this[name] = result[TestTable.name] + this[lastName] = result[TestTable.lastName] + this[middleName] = result[TestTable.lastName] + this[age] = result[TestTable.age] + } + } + } + } +} diff --git a/galite-tests/src/test/kotlin/org/kopi/galite/tests/examples/DocumentationReport.kt b/galite-tests/src/test/kotlin/org/kopi/galite/tests/examples/DocumentationReport.kt index 4030fd2de..5b886b4e5 100644 --- a/galite-tests/src/test/kotlin/org/kopi/galite/tests/examples/DocumentationReport.kt +++ b/galite-tests/src/test/kotlin/org/kopi/galite/tests/examples/DocumentationReport.kt @@ -20,12 +20,10 @@ import java.util.Locale import org.kopi.galite.tests.desktop.runForm import org.kopi.galite.visual.domain.INT -import org.kopi.galite.visual.dsl.common.Icon import org.kopi.galite.visual.dsl.form.Block -import org.kopi.galite.visual.dsl.form.Key -import org.kopi.galite.visual.dsl.form.ReportSelectionForm +import org.kopi.galite.visual.dsl.form.DictionaryForm -class DocumentationReport : ReportSelectionForm(title = "Test Report Form", locale = Locale.UK) { +class DocumentationReport : DictionaryForm(title = "Test Report Form", locale = Locale.UK) { //Menus Definition @@ -44,6 +42,11 @@ class DocumentationReport : ReportSelectionForm(title = "Test Report Form", loca DocumentationReportR() } } + command(item = pivotTable) { + createPivotTable { + DocumentationPivotTable() + } + } } } } diff --git a/galite-tests/src/test/kotlin/org/kopi/galite/tests/examples/Modules.kt b/galite-tests/src/test/kotlin/org/kopi/galite/tests/examples/Modules.kt index 12a555622..b5faefb6c 100644 --- a/galite-tests/src/test/kotlin/org/kopi/galite/tests/examples/Modules.kt +++ b/galite-tests/src/test/kotlin/org/kopi/galite/tests/examples/Modules.kt @@ -18,6 +18,7 @@ package org.kopi.galite.tests.examples import org.jetbrains.exposed.sql.transactions.transaction import org.kopi.galite.tests.database.insertIntoModule +import org.kopi.galite.tests.form.FormWithPivotTable import org.kopi.galite.tests.form.FormWithReport import org.kopi.galite.tests.localization.LocalizedForm import org.kopi.galite.tests.ui.vaadin.field.FormToTestFormPopUp @@ -30,6 +31,7 @@ fun initModules() { transaction { insertIntoModule("1000", "org/kopi/galite/test/Menu", 0) insertIntoModule("1001", "org/kopi/galite/test/Menu", 1, "1000", FormWithReport::class) + insertIntoModule("1002", "org/kopi/galite/test/Menu", 2, "1000", FormWithPivotTable::class) insertIntoModule("2000", "org/kopi/galite/test/Menu", 100) insertIntoModule("2001", "org/kopi/galite/test/Menu", 101, "2000", CommandsForm::class) insertIntoModule("2002", "org/kopi/galite/test/Menu", 102, "2000", FormExample::class) diff --git a/galite-tests/src/test/kotlin/org/kopi/galite/tests/examples/PivotTableExample.kt b/galite-tests/src/test/kotlin/org/kopi/galite/tests/examples/PivotTableExample.kt deleted file mode 100644 index 667caebf1..000000000 --- a/galite-tests/src/test/kotlin/org/kopi/galite/tests/examples/PivotTableExample.kt +++ /dev/null @@ -1,341 +0,0 @@ -/* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.kopi.galite.tests.examples - -import java.util.Locale - -import org.kopi.galite.visual.domain.INT -import org.kopi.galite.visual.domain.STRING -import org.kopi.galite.visual.dsl.pivotTable.PivotTable - -class PivotTableExample : PivotTable(title = "Form to test Blocks", locale = Locale.UK) { - val city = field(STRING(15)) { - label = "Country" - dimension = true - } - - val delegation = field(STRING(15)) { - label = "Delegation" - dimension = true - } - - val gender = field(STRING(6)) { - label = "Gender" - } - - val age = field(INT(3)) { - label = "Age" - } - - init { - - add { - this[city] = "Ben Arous" - this[delegation] = "Mourouj" - this[gender] = "Female" - this[age] = 22 - } - add { - this[city] = "Ben Arous" - this[delegation] = "Rades" - this[gender] = "Female" - this[age] = 22 - } - add { - this[city] = "Ben Arous" - this[delegation] = "Mourouj" - this[gender] = "Female" - this[age] = 22 - } - add { - this[city] = "Ben Arous" - this[delegation] = "Mourouj" - this[gender] = "Female" - this[age] = 22 - } - add { - this[city] = "Tunis" - this[delegation] = "Notre damme" - this[gender] = "Female" - this[age] = 22 - } - add { - this[city] = "Ben Arous" - this[delegation] = "Mourouj" - this[gender] = "Female" - this[age] = 22 - } - add { - this[city] = "Ben Arous" - this[delegation] = "Rades" - this[gender] = "Female" - this[age] = 22 - } - add { - this[city] = "Ben Arous" - this[delegation] = "Mourouj" - this[gender] = "Female" - this[age] = 22 - } - add { - this[city] = "Ben Arous" - this[delegation] = "Yassminet" - this[gender] = "Female" - this[age] = 22 - } - add { - this[city] = "Ben Arous" - this[delegation] = "Yassminet" - this[gender] = "Female" - this[age] = 22 - } - add { - this[city] = "Ben Arous" - this[delegation] = "Yassminet" - this[gender] = "Female" - this[age] = 22 - } - add { - this[city] = "Ben Arous" - this[delegation] = "Yassminet" - this[gender] = "Female" - this[age] = 22 - } - add { - this[city] = "Ben Arous" - this[delegation] = "Yassminet" - this[gender] = "Female" - this[age] = 22 - } - add { - this[city] = "Ben Arous" - this[delegation] = "Mourouj" - this[gender] = "Female" - this[age] = 22 - } - add { - this[city] = "Tunis" - this[delegation] = "Notre damme" - this[gender] = "Female" - this[age] = 22 - } - add { - this[city] = "Ben Arous" - this[delegation] = "Mourouj" - this[gender] = "Female" - this[age] = 22 - } - add { - this[city] = "Ben Arous" - this[delegation] = "Mourouj" - this[gender] = "Female" - this[age] = 22 - } - add { - this[city] = "Ben Arous" - this[delegation] = "Mourouj" - this[gender] = "Female" - this[age] = 22 - } - add { - this[city] = "Tunis" - this[delegation] = "Notre damme" - this[gender] = "Female" - this[age] = 22 - } - add { - this[city] = "Ben Arous" - this[delegation] = "Mourouj" - this[gender] = "Female" - this[age] = 22 - } - add { - this[city] = "Ben Arous" - this[delegation] = "Mourouj" - this[gender] = "Female" - this[age] = 22 - } - add { - this[city] = "Ben Arous" - this[delegation] = "Yassminet" - this[gender] = "Female" - this[age] = 22 - } - add { - this[city] = "Ben Arous" - this[delegation] = "Mourouj" - this[gender] = "Female" - this[age] = 22 - } - add { - this[city] = "Ben Arous" - this[delegation] = "Green" - this[gender] = "Female" - this[age] = 22 - } - add { - this[city] = "Tunis" - this[delegation] = "Notre damme" - this[gender] = "Female" - this[age] = 22 - } - add { - this[city] = "Ben Arous" - this[delegation] = "Yassminet" - this[gender] = "Female" - this[age] = 22 - } - add { - this[city] = "Ben Arous" - this[delegation] = "Yassminet" - this[gender] = "Female" - this[age] = 22 - } - add { - this[city] = "Ben Arous" - this[delegation] = "Mourouj" - this[gender] = "Female" - this[age] = 22 - } - add { - this[city] = "Ben Arous" - this[delegation] = "Mourouj" - this[gender] = "Female" - this[age] = 22 - } - add { - this[city] = "Ben Arous" - this[delegation] = "Yassminet" - this[gender] = "Male" - this[age] = 26 - } - add { - this[city] = "Ben Arous" - this[delegation] = "Mourouj" - this[gender] = "Male" - this[age] = 26 - } - add { - this[city] = "Ben Arous" - this[delegation] = "Yassminet" - this[gender] = "Male" - this[age] = 26 - } - add { - this[city] = "Ben Arous" - this[delegation] = "Yassminet" - this[gender] = "Male" - this[age] = 26 - } - add { - this[city] = "Ben Arous" - this[delegation] = "Mourouj" - this[gender] = "Male" - this[age] = 26 - } - add { - this[city] = "Ben Arous" - this[delegation] = "Yassminet" - this[gender] = "Male" - this[age] = 26 - } - add { - this[city] = "Ben Arous" - this[delegation] = "Mourouj" - this[gender] = "Male" - this[age] = 26 - } - add { - this[city] = "Ben Arous" - this[delegation] = "Yassminet" - this[gender] = "Male" - this[age] = 26 - } - add { - this[city] = "Ben Arous" - this[delegation] = "Yassminet" - this[gender] = "Male" - this[age] = 26 - } - add { - this[city] = "Ben Arous" - this[delegation] = "Yassminet" - this[gender] = "Male" - this[age] = 26 - } - add { - this[city] = "Ben Arous" - this[delegation] = "Yassminet" - this[gender] = "Male" - this[age] = 26 - } - add { - this[city] = "Ben Arous" - this[delegation] = "Mourouj" - this[gender] = "Male" - this[age] = 26 - } - add { - this[city] = "Ben Arous" - this[delegation] = "Yassminet" - this[gender] = "Male" - this[age] = 26 - } - add { - this[city] = "Ben Arous" - this[delegation] = "Mourouj" - this[gender] = "Male" - this[age] = 26 - } - add { - this[city] = "Ben Arous" - this[delegation] = "Mourouj" - this[gender] = "Male" - this[age] = 26 - } - add { - this[city] = "Ben Arous" - this[delegation] = "Mourouj" - this[gender] = "Male" - this[age] = 26 - } - add { - this[city] = "Ben Arous" - this[delegation] = "Yassminet" - this[gender] = "Male" - this[age] = 26 - } - add { - this[city] = "Ben Arous" - this[delegation] = "Mourouj" - this[gender] = "Male" - this[age] = 26 - } - add { - this[city] = "Ben Arous" - this[delegation] = "Yassminet" - this[gender] = "Male" - this[age] = 26 - } - add { - this[city] = "Ben Arous" - this[delegation] = "Yassminet" - this[gender] = "Male" - this[age] = 26 - } - } -} diff --git a/galite-tests/src/test/kotlin/org/kopi/galite/tests/form/FormWithPivotTable.kt b/galite-tests/src/test/kotlin/org/kopi/galite/tests/form/FormWithPivotTable.kt new file mode 100644 index 000000000..d8c057c8a --- /dev/null +++ b/galite-tests/src/test/kotlin/org/kopi/galite/tests/form/FormWithPivotTable.kt @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +package org.kopi.galite.tests.form + +import java.util.Locale + +import org.kopi.galite.tests.desktop.runForm +import org.kopi.galite.tests.pivotTable.SimplePivotTable +import org.kopi.galite.tests.report.SimpleReport +import org.kopi.galite.visual.dsl.common.Icon +import org.kopi.galite.visual.dsl.form.DictionaryForm +import org.kopi.galite.visual.dsl.form.Key +import org.kopi.galite.visual.dsl.form.ReportSelectionForm + +class FormWithPivotTable : DictionaryForm(title = "SimplePivotTable", locale = Locale.UK) { + + val testPage = page("test page") + + val block = testPage.insertBlock(BlockSample) { + command(item = pivotTable) { + createPivotTable { + SimplePivotTable() + } + } + } +} + +fun main() { + runForm(FormWithPivotTable()) +} diff --git a/galite-tests/src/test/kotlin/org/kopi/galite/tests/pivotTable/PivotTableTests.kt b/galite-tests/src/test/kotlin/org/kopi/galite/tests/pivotTable/PivotTableTests.kt new file mode 100644 index 000000000..d9fc767d3 --- /dev/null +++ b/galite-tests/src/test/kotlin/org/kopi/galite/tests/pivotTable/PivotTableTests.kt @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +package org.kopi.galite.tests.pivotTable + +import java.io.File +import java.math.BigDecimal +import java.util.Locale + +import kotlin.test.assertEquals + +import org.jdom2.input.SAXBuilder +import org.junit.Test +import org.kopi.galite.tests.ui.vaadin.VApplicationTestBase +import org.kopi.galite.visual.domain.DECIMAL +import org.kopi.galite.visual.domain.INT +import org.kopi.galite.visual.domain.STRING +import org.kopi.galite.visual.dsl.pivotTable.PivotTable + +class PivotTableTests: VApplicationTestBase() { + + val SimplePivotTable = SimplePivotTable() + + /** + * Tests that fields has been registered in the pivot table. + */ + @Test + fun pivotTableFieldsTest() { + assertEquals(SimplePivotTable.fields[0], SimplePivotTable.name) + assertEquals(SimplePivotTable.fields[1], SimplePivotTable.age) + } + + /** + * Tests that fields has been registered in the pivot table. + */ + @Test + fun PivotTableDataTest() { + val rows = SimplePivotTable.getRowsForField(SimplePivotTable.name) + assertEquals(listOf("Sami", "Sofia", "Sofia"), rows) + + val firstRow = SimplePivotTable.getRow(0) + assertMapsEquals(mapOf(SimplePivotTable.name to "Sami", + SimplePivotTable.age to 22, + SimplePivotTable.profession to "Journalist", + SimplePivotTable.salary to BigDecimal("2000") + ), + firstRow) + + val secondRow = SimplePivotTable.getRow(1) + assertMapsEquals(mapOf(SimplePivotTable.name to "Sofia", + SimplePivotTable.age to 23, + SimplePivotTable.profession to "Dentist", + SimplePivotTable.salary to BigDecimal("2000.55")), + secondRow) + + val thirdRow = SimplePivotTable.getRow(2) + assertMapsEquals(mapOf(SimplePivotTable.name to "Sofia", + SimplePivotTable.age to 25, + SimplePivotTable.profession to "Baker", + SimplePivotTable.salary to BigDecimal("2000.55")), + thirdRow) + } + + /** + * Tests that fields localization is generated to the xml file + */ + @Test + fun fieldLocalizationTest() { + val builder = SAXBuilder() + val tempDir = createTempDir("galite", "") + tempDir.deleteOnExit() + + val sourceFilePath = SimplePivotTable.javaClass.classLoader.getResource("").path + + this.javaClass.`package`.name.replace(".", "/") + File.separatorChar + SimplePivotTable.genLocalization() + + val generatedFile = File("${sourceFilePath}/SimplePivotTable-${SimplePivotTable.locale}.xml") + assertEquals(true, generatedFile.exists()) + val document = builder.build(generatedFile) + + // Check that generated xml file contains fields localization + val rootElement = document.rootElement + val nameField = rootElement.children[0] + val ageField = rootElement.children[1] + assertEquals("pivotTable", rootElement.name) + assertEquals("SimplePivotTable", rootElement.getAttributeValue("title")) + assertEquals("ANM_0", nameField.getAttributeValue("ident")) + assertEquals("name", nameField.getAttributeValue("label")) + assertEquals("ANM_1", ageField.getAttributeValue("ident")) + assertEquals("age", ageField.getAttributeValue("label")) + } +} + +/** + * Simple Pivot table with two fields. + */ +class SimplePivotTable : PivotTable(title = "SimplePivotTable", locale = Locale.UK) { + + val name = field(STRING(20)) { + label = "name" + } + + val age = field(INT(3)) { + label = "age" + } + + val profession = field(STRING(20)) { + label = "profession" + } + + val salary = field(DECIMAL(width = 10, scale = 5)) { + label = "salary" + } + + init { + add { + this[name] = "Sami" + this[age] = 22 + this[profession] = "Journalist" + this[salary] = BigDecimal("2000") + } + add { + this[name] = "Sofia" + this[age] = 23 + this[profession] = "Dentist" + this[salary] = BigDecimal("2000.55") + } + add { + this[age] = 25 + this[profession] = "Baker" + this[name] = "Sofia" + this[salary] = BigDecimal("2000.55") + } + } +} diff --git a/galite-tests/src/test/kotlin/org/kopi/galite/tests/pivotTable/VRowTests.kt b/galite-tests/src/test/kotlin/org/kopi/galite/tests/pivotTable/VRowTests.kt new file mode 100644 index 000000000..cc0ac9483 --- /dev/null +++ b/galite-tests/src/test/kotlin/org/kopi/galite/tests/pivotTable/VRowTests.kt @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +package org.kopi.galite.tests.pivotTable + +import kotlin.test.assertEquals + +import org.junit.Test +import org.kopi.galite.tests.common.TestBase +import org.kopi.galite.visual.pivotTable.VPivotTableRow + +class VRowTests : TestBase() { + + val intData: Array = arrayOf(1, 2, 3, 4) + + @Test + fun vBaseRowIntTest() { + /**Base row containing integer data*/ + val vBaseRowIntTest = VPivotTableRow(intData) + + assertEquals(1, vBaseRowIntTest.getValueAt(0)) + } +} From 2b6b8a43a64856ca0b61e1e0b718925ace8258f7 Mon Sep 17 00:00:00 2001 From: Super User Date: Wed, 25 Oct 2023 14:31:15 +0100 Subject: [PATCH 09/20] Added XML file for French language support. --- .../kopi/galite/visual/l10n/ActorLocalizer.kt | 2 +- .../kopi/galite/visual/l10n/MenuLocalizer.kt | 2 +- .../kotlin/org/kopi/galite/demo/bill/BillP.kt | 5 ---- .../galite/demo/billproduct/BillProductP.kt | 3 --- .../org/kopi/galite/demo/client/ClientP.kt | 10 +------ .../kopi/galite/demo/provider/ProviderP.kt | 26 ------------------- .../org/kopi/galite/demo/stock/StockP.kt | 23 ---------------- .../org/kopi/galite/demo/taxRule/TaxRuleP.kt | 2 -- .../org/kopi/galite/demo/bill/BillP-fr_FR.xml | 16 ++++++++++++ .../demo/billproduct/BillProductP-fr_FR.xml | 14 ++++++++++ .../kopi/galite/demo/client/ClientP-fr_FR.xml | 19 ++++++++++++++ .../galite/demo/provider/ProviderP-fr_FR.xml | 16 ++++++++++++ .../kopi/galite/demo/stock/StockP-fr_FR.xml | 14 ++++++++++ .../galite/demo/taxRule/TaxRuleP-fr_FR.xml | 13 ++++++++++ 14 files changed, 95 insertions(+), 70 deletions(-) create mode 100644 galite-demo/galite-vaadin/src/main/resources/org/kopi/galite/demo/bill/BillP-fr_FR.xml create mode 100644 galite-demo/galite-vaadin/src/main/resources/org/kopi/galite/demo/billproduct/BillProductP-fr_FR.xml create mode 100644 galite-demo/galite-vaadin/src/main/resources/org/kopi/galite/demo/client/ClientP-fr_FR.xml create mode 100644 galite-demo/galite-vaadin/src/main/resources/org/kopi/galite/demo/provider/ProviderP-fr_FR.xml create mode 100644 galite-demo/galite-vaadin/src/main/resources/org/kopi/galite/demo/stock/StockP-fr_FR.xml create mode 100644 galite-demo/galite-vaadin/src/main/resources/org/kopi/galite/demo/taxRule/TaxRuleP-fr_FR.xml diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/l10n/ActorLocalizer.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/l10n/ActorLocalizer.kt index 85aa9c666..2ac0d15d3 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/l10n/ActorLocalizer.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/l10n/ActorLocalizer.kt @@ -50,7 +50,7 @@ class ActorLocalizer(document: Document, ident: String) { init { val root: Element = document.rootElement - val names = listOf("form", "report", "chart", "insert") // FIXME: Do we steel need insert root element? + val names = listOf("form", "report", "chart", "insert", "pivottable") // FIXME: Do we steel need insert root element? if (root.name !in names) { throw InconsistencyException("bad root element $root") diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/l10n/MenuLocalizer.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/l10n/MenuLocalizer.kt index 6dd395f31..dd753d20f 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/l10n/MenuLocalizer.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/l10n/MenuLocalizer.kt @@ -40,7 +40,7 @@ class MenuLocalizer(document: Document, ident: String) { // ---------------------------------------------------------------------- init { val root: Element = document.rootElement - val names = listOf("form", "report", "chart", "insert") // FIXME: Do we steel need insert root element? + val names = listOf("form", "report", "chart", "insert", "pivottable") // FIXME: Do we steel need insert root element? if (root.name !in names) { throw InconsistencyException("bad root element $root") diff --git a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/bill/BillP.kt b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/bill/BillP.kt index 6089b05b4..a23a1514e 100644 --- a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/bill/BillP.kt +++ b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/bill/BillP.kt @@ -47,29 +47,24 @@ class BillP : PivotTable("Bills_Pivot_Table", locale = Locale.UK) { val numBill = field(INT(25)) { label = "Number" - help = "The bill number" dimension = true } val addressBill = field(STRING(25)) { label = "Address" - help = "The bill address" dimension = true } val dateBill = field(DATE) { label = "Date" - help = "The bill date" dimension = true } val amountWithTaxes = field(DECIMAL(20, 10)) { label = "Amount to pay" - help = "The amount including all taxes to pay" } val refCmd = field(INT(50)) { label = "Command reference" - help = "The command reference" dimension = true } diff --git a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/billproduct/BillProductP.kt b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/billproduct/BillProductP.kt index 6581d5fe0..59f97cceb 100644 --- a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/billproduct/BillProductP.kt +++ b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/billproduct/BillProductP.kt @@ -32,17 +32,14 @@ class BillProductP : PivotTable("Bill Product Report", Locale.UK) { val quantity = field(INT(25)) { label = "Quantity" - help = "The quantity" } val amount = field(DECIMAL(25, 10)) { label = "Amount before tax" - help = "The amount before tax to pay" } val amountWithTaxes = field(DECIMAL(50, 10)) { label = "Amount all taxes included" - help = "The amount all taxes included to pay" } val billProducts = BillProduct.selectAll() diff --git a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/client/ClientP.kt b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/client/ClientP.kt index 4150aa467..bde4793ec 100644 --- a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/client/ClientP.kt +++ b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/client/ClientP.kt @@ -31,7 +31,7 @@ import org.kopi.galite.visual.dsl.pivotTable.PivotTable /** * Client Report */ -class ClientP : PivotTable(title = "Clients_Report", locale = Locale.UK) { +class ClientP : PivotTable(title = "Clients_Pivot_Table", locale = Locale.UK) { val action = menu("Action") val file = menu("File") @@ -52,42 +52,34 @@ class ClientP : PivotTable(title = "Clients_Report", locale = Locale.UK) { val firstName = field(STRING(25)) { label = "First Name" - help = "The client first name" } val lastName = field(STRING(25)) { label = "Last Name" - help = "The client last name" } val addressClt = field(STRING(50)) { label = "Address" - help = "The client address" } val ageClt = field(INT(2)) { label = "Age" - help = "The client age" } val countryClt = field(STRING(50)) { label = "Country" - help = "The client country" } val cityClt = field(STRING(50)) { label = "City" - help = "The client city" } val zipCodeClt = field(INT(2)) { label = "Zip code" - help = "The client zip code" } val activeClt = field(BOOL) { label = "Status" - help = "Is the client active?" } val clients = Client.selectAll() diff --git a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/provider/ProviderP.kt b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/provider/ProviderP.kt index 017442619..af51ecd6b 100644 --- a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/provider/ProviderP.kt +++ b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/provider/ProviderP.kt @@ -34,50 +34,24 @@ class ProviderP : PivotTable(title = "Providers_Report", locale = Locale.UK) { val action = menu("Action") - val csv = actor(menu = action, label = "CSV", help = "CSV Format", ident = "csv") { - key = Key.F8 - icon = Icon.EXPORT_CSV - } - - val xls = actor(menu = action, label = "XLS", help = "Excel (XLS) Format", ident = "xls") { - key = Key.SHIFT_F8 - icon = Icon.EXPORT_XLSX - } - - val xlsx = actor(menu = action, label = "XLSX", help = "Excel (XLSX) Format", ident = "xlsx") { - key = Key.SHIFT_F8 - icon = Icon.EXPORT - } - - val pdf = actor(menu = action, label = "PDF", help = "PDF Format", ident = "pdf") { - key = Key.F9 - icon = Icon.EXPORT_PDF - } - - val nameProvider = field(STRING(50)) { label = "Name" - help = "The provider name" } val tel = field(INT(25)) { label = "Phone number" - help = "The provider phone number" } val description = field(STRING(255)) { label = "Description" - help = "The provider description" } val address = field(STRING(70)) { label = "Address" - help = "The provider address" } val zipCode = field(INT(50)) { label = "Zip code" - help = "The provider zip code" } val providers = Provider.selectAll() diff --git a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/stock/StockP.kt b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/stock/StockP.kt index 11a01d2ea..fdd49a2d3 100644 --- a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/stock/StockP.kt +++ b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/stock/StockP.kt @@ -37,37 +37,14 @@ class StockP : PivotTable(title = "Stocks", locale = Locale.UK) { val action = menu("Action") - val csv = actor(menu = action, label = "CSV", help = "CSV Format", ident = "csv") { - key = Key.F8 - icon = Icon.EXPORT_CSV - } - - val xls = actor(menu = action, label = "XLS", help = "Excel (XLS) Format", ident = "xls") { - key = Key.SHIFT_F8 - icon = Icon.EXPORT_XLSX - } - - val xlsx = actor(menu = action, label = "XLSX", help = "Excel (XLSX) Format", ident = "xlsx") { - key = Key.SHIFT_F8 - icon = Icon.EXPORT - } - - val pdf = actor(menu = action, label = "PDF", help = "PDF Format", ident = "pdf") { - key = Key.F9 - icon = Icon.EXPORT_PDF - } - val description = field(STRING(25)) { label = "Description" - help = "The product description" } val nameProvider = field(STRING(25)) { label = "Provider name" - help = "The provider name" } val minAlert = field(INT(25)) { label = "Min Alert" - help = "The stock's min alert" } val stocks = Stock.join(Provider, JoinType.INNER, Stock.idStckProv, Provider.idProvider) diff --git a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/taxRule/TaxRuleP.kt b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/taxRule/TaxRuleP.kt index 61d1549c1..f44dbba55 100644 --- a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/taxRule/TaxRuleP.kt +++ b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/taxRule/TaxRuleP.kt @@ -36,12 +36,10 @@ class TaxRuleP : PivotTable(title = "TaxRules_Report", locale = Locale.UK) { val taxName = field(STRING(50)) { label = "Name" - help = "The tax name" } val rate = field(INT(25)) { label = "Rate in %" - help = "The tax rate in %" } val taxRules = TaxRule.selectAll() diff --git a/galite-demo/galite-vaadin/src/main/resources/org/kopi/galite/demo/bill/BillP-fr_FR.xml b/galite-demo/galite-vaadin/src/main/resources/org/kopi/galite/demo/bill/BillP-fr_FR.xml new file mode 100644 index 000000000..b0da03e14 --- /dev/null +++ b/galite-demo/galite-vaadin/src/main/resources/org/kopi/galite/demo/bill/BillP-fr_FR.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/galite-demo/galite-vaadin/src/main/resources/org/kopi/galite/demo/billproduct/BillProductP-fr_FR.xml b/galite-demo/galite-vaadin/src/main/resources/org/kopi/galite/demo/billproduct/BillProductP-fr_FR.xml new file mode 100644 index 000000000..c37cf8c43 --- /dev/null +++ b/galite-demo/galite-vaadin/src/main/resources/org/kopi/galite/demo/billproduct/BillProductP-fr_FR.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/galite-demo/galite-vaadin/src/main/resources/org/kopi/galite/demo/client/ClientP-fr_FR.xml b/galite-demo/galite-vaadin/src/main/resources/org/kopi/galite/demo/client/ClientP-fr_FR.xml new file mode 100644 index 000000000..10f28601f --- /dev/null +++ b/galite-demo/galite-vaadin/src/main/resources/org/kopi/galite/demo/client/ClientP-fr_FR.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/galite-demo/galite-vaadin/src/main/resources/org/kopi/galite/demo/provider/ProviderP-fr_FR.xml b/galite-demo/galite-vaadin/src/main/resources/org/kopi/galite/demo/provider/ProviderP-fr_FR.xml new file mode 100644 index 000000000..525893471 --- /dev/null +++ b/galite-demo/galite-vaadin/src/main/resources/org/kopi/galite/demo/provider/ProviderP-fr_FR.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/galite-demo/galite-vaadin/src/main/resources/org/kopi/galite/demo/stock/StockP-fr_FR.xml b/galite-demo/galite-vaadin/src/main/resources/org/kopi/galite/demo/stock/StockP-fr_FR.xml new file mode 100644 index 000000000..8d94a47e7 --- /dev/null +++ b/galite-demo/galite-vaadin/src/main/resources/org/kopi/galite/demo/stock/StockP-fr_FR.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/galite-demo/galite-vaadin/src/main/resources/org/kopi/galite/demo/taxRule/TaxRuleP-fr_FR.xml b/galite-demo/galite-vaadin/src/main/resources/org/kopi/galite/demo/taxRule/TaxRuleP-fr_FR.xml new file mode 100644 index 000000000..1f8a0b03f --- /dev/null +++ b/galite-demo/galite-vaadin/src/main/resources/org/kopi/galite/demo/taxRule/TaxRuleP-fr_FR.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + From 1581bf9aed88204bbbc5bd01812d8ddbcbd92e99 Mon Sep 17 00:00:00 2001 From: Super User Date: Fri, 27 Oct 2023 09:35:39 +0100 Subject: [PATCH 10/20] Add pivottable.css --- .../ui/vaadin/pivotTable/DPivotTable.kt | 8 +- .../frontend/styles/galite/pivottable.css | 132 ++++++++++++++++++ 2 files changed, 137 insertions(+), 3 deletions(-) create mode 100644 galite-core/src/main/resources/META-INF/resources/frontend/styles/galite/pivottable.css diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/DPivotTable.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/DPivotTable.kt index e5d096890..2bd04c3da 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/DPivotTable.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/DPivotTable.kt @@ -17,6 +17,7 @@ */ package org.kopi.galite.visual.ui.vaadin.pivotTable +import com.vaadin.flow.component.dependency.CssImport import org.kopi.galite.visual.pivotTable.MPivotTable import org.kopi.galite.visual.pivotTable.UPivotTable import org.kopi.galite.visual.pivotTable.VPivotTable @@ -24,12 +25,13 @@ import org.kopi.galite.visual.ui.vaadin.visual.DWindow import org.vaadin.addons.componentfactory.PivotTable +@CssImport("./styles/galite/pivottable.css") class DPivotTable(private val pivotTable: VPivotTable) : DWindow(pivotTable), UPivotTable { //--------------------------------------------------- // DATA MEMBERS //--------------------------------------------------- - private val model: MPivotTable = pivotTable.model // report model + private val model: MPivotTable = pivotTable.model // pivot table model private var pivotData = PivotTable.PivotData() private var pivotOptions = PivotTable.PivotOptions() private val listeDimensions = mutableListOf() @@ -63,9 +65,9 @@ class DPivotTable(private val pivotTable: VPivotTable) : DWindow(pivotTable), UP pivotData.addRow(*rows.toTypedArray()) } - pivotOptions.setCols(*listeDimensions.toTypedArray()) + pivotOptions.setRows(*listeDimensions.toTypedArray()) val pivot = PivotTable(pivotData, pivotOptions, PivotTable.PivotMode.INTERACTIVE) add(pivot) } -} +} \ No newline at end of file diff --git a/galite-core/src/main/resources/META-INF/resources/frontend/styles/galite/pivottable.css b/galite-core/src/main/resources/META-INF/resources/frontend/styles/galite/pivottable.css new file mode 100644 index 000000000..1c1f6a234 --- /dev/null +++ b/galite-core/src/main/resources/META-INF/resources/frontend/styles/galite/pivottable.css @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +.pvtUi {color: #333;} + + +table.pvtTable { + font-size: 8pt; + text-align: left; + border-collapse: collapse; +} +table.pvtTable thead tr th, table.pvtTable tbody tr th { + background-color: #e6EEEE; + border: 1px solid #CDCDCD; + font-size: 8pt; + padding: 5px !important; +} + +table.pvtTable .pvtColLabel {text-align: center;} +table.pvtTable .pvtTotalLabel {text-align: right;} + +table.pvtTable tbody tr td { + color: #3D3D3D; + padding: 5px; + background-color: #FFF; + border: 1px solid #CDCDCD; + vertical-align: top; + text-align: center; +} + +.pvtTotal, .pvtGrandTotal { font-weight: bold; } + +.pvtVals { text-align: center; white-space: nowrap;} +.pvtRowOrder, .pvtColOrder { + cursor:pointer; + width: 15px; + margin-left: 5px; + display: inline-block; } +.pvtAggregator { margin-bottom: 5px ;} + +.pvtAxisContainer, .pvtVals { + border: 1px solid gray; + background: #EEE; + padding: 5px; + min-width: 20px; + min-height: 20px; + + user-select: none; + -webkit-user-select: none; + -moz-user-select: none; + -khtml-user-select: none; + -ms-user-select: none; +} +.pvtAxisContainer li { + padding: 8px 6px; + list-style-type: none; + cursor:move; +} +.pvtAxisContainer li.pvtPlaceholder { + -webkit-border-radius: 5px; + padding: 3px 15px; + -moz-border-radius: 5px; + border-radius: 5px; + border: 1px dashed #aaa; +} + +.pvtAxisContainer li span.pvtAttr { + -webkit-text-size-adjust: 100%; + background: #F3F3F3; + border: 1px solid #DEDEDE; + padding: 2px 5px; + white-space:nowrap; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; +} + +.pvtTriangle { + cursor:pointer; + color: grey; +} + +.pvtHorizList li { display: inline; } +.pvtVertList { vertical-align: top; } + +.pvtFilteredAttribute { font-style: italic } + +.pvtFilterBox{ + z-index: 100; + width: 300px; + border: 1px solid gray; + background-color: #fff; + position: absolute; + text-align: center; +} + +.pvtFilterBox h4{ margin: 15px; } +.pvtFilterBox p { margin: 10px auto; } +.pvtFilterBox label { font-weight: normal; } +.pvtFilterBox input[type='checkbox'] { margin-right: 10px; margin-left: 10px; } +.pvtFilterBox input[type='text'] { width: 230px; } +.pvtFilterBox .count { color: gray; font-weight: normal; margin-left: 3px;} + +.pvtCheckContainer{ + text-align: left; + font-size: 14px; + white-space: nowrap; + overflow-y: scroll; + width: 100%; + max-height: 250px; + border-top: 1px solid lightgrey; + border-bottom: 1px solid lightgrey; +} + +.pvtCheckContainer p{ margin: 5px; } + +.pvtRendererArea {padding: 5px;} \ No newline at end of file From fc8336143c0bf923cd719d7bf76cad37e9ce90f8 Mon Sep 17 00:00:00 2001 From: Super User Date: Tue, 31 Oct 2023 10:08:46 +0100 Subject: [PATCH 11/20] add element style to pivot table --- .../galite/visual/ui/vaadin/pivotTable/DPivotTable.kt | 8 +++++++- .../META-INF/resources/frontend/styles/galite/common.css | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/DPivotTable.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/DPivotTable.kt index 2bd04c3da..025400cfd 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/DPivotTable.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/DPivotTable.kt @@ -39,6 +39,12 @@ class DPivotTable(private val pivotTable: VPivotTable) : DWindow(pivotTable), UP init { getModel()!!.setDisplay(this) setSizeFull() + element.style["display"] = "flex!important" + element.style["flex-direction"] = "column!important" + element.style["overflow"] = "auto!important" + element.style["position"] = "relative!important" + element.style["outline"] = "none!important" + element.style["z-index"] = "0!important" } //--------------------------------------------------- @@ -70,4 +76,4 @@ class DPivotTable(private val pivotTable: VPivotTable) : DWindow(pivotTable), UP add(pivot) } -} \ No newline at end of file +} diff --git a/galite-core/src/main/resources/META-INF/resources/frontend/styles/galite/common.css b/galite-core/src/main/resources/META-INF/resources/frontend/styles/galite/common.css index 9a5820245..e605cd732 100644 --- a/galite-core/src/main/resources/META-INF/resources/frontend/styles/galite/common.css +++ b/galite-core/src/main/resources/META-INF/resources/frontend/styles/galite/common.css @@ -18,6 +18,7 @@ html, body, #main, #content, #actors { width: 100%; + height: 100%; display: inline-block; } From f26b34f0201a485d9e1376b6030d7bed94b91833 Mon Sep 17 00:00:00 2001 From: Super User Date: Tue, 31 Oct 2023 14:53:49 +0100 Subject: [PATCH 12/20] Pivot Table : Add Triggers implementation --- .../visual/dsl/pivotTable/PivotTable.kt | 100 ++++++++++++------ .../galite/visual/pivotTable/Constants.kt | 93 ++++++++++++++++ .../galite/visual/pivotTable/VPivotTable.kt | 66 +++++++++++- .../ui/vaadin/pivotTable/DPivotTable.kt | 5 +- .../org/kopi/galite/demo/client/ClientP.kt | 6 ++ .../tests/examples/DocumentationPivotTable.kt | 13 ++- 6 files changed, 241 insertions(+), 42 deletions(-) create mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/Constants.kt diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTable.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTable.kt index 4d6a5ffed..9aedba7d2 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTable.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTable.kt @@ -22,8 +22,9 @@ import java.util.Locale import org.kopi.galite.visual.ApplicationContext import org.kopi.galite.visual.domain.Domain -import org.kopi.galite.visual.dsl.common.LocalizationWriter -import org.kopi.galite.visual.dsl.common.Window +import org.kopi.galite.visual.dsl.common.* +import org.kopi.galite.visual.form.VConstants +import org.kopi.galite.visual.pivotTable.Constants import org.kopi.galite.visual.pivotTable.VPivotTable abstract class PivotTable(title: String, val help: String?, locale: Locale? = null) : Window(title, locale) { @@ -60,36 +61,6 @@ abstract class PivotTable(title: String, val help: String?, locale: Locale? = nu return field } - /** - * creates and returns a field that accept nulls. It uses [init] method to initialize the field. - * - * @param domain the domain of the field. - * @param init initialization method. - * @return a field. - */ - inline fun ?> nullableField(domain: Domain, - noinline init: PivotTableField.() -> Unit): PivotTableField { - return field(domain, init) as PivotTableField - } - - /** - * creates and returns fields. It uses [init] method to initialize the fields. - * - * @param fieldsNumber the number of fields to create. - * @param domain the domain of the field. - * @param init initialization method. - * @return a field. - */ - inline fun ?> field(fieldsNumber: Int, - domain: Domain, - noinline init: PivotTableField.() -> Unit): List> { - return (0 until fieldsNumber).map { - nullableField(domain, init).also { field -> - field.model.label = "${field.label}_${it + 1}" - } - } - } - /** * Adds a row to the Pivot table. * @@ -112,6 +83,42 @@ abstract class PivotTable(title: String, val help: String?, locale: Locale? = nu } } + /** + * Adds triggers to this pivot table + * + * @param pivotTriggerEvents the trigger events to add + * @param method the method to execute when trigger is called + */ + fun trigger(vararg pivotTriggerEvents: PivotTableTriggerEvent, method: () -> T): Trigger { + val event = formEventList(pivotTriggerEvents) + val pivotTableAction = Action(null, method) + val trigger = FormTrigger(event, pivotTableAction) + + triggers.add(trigger) + + // PIVOT TABLE TRIGGERS + triggers.forEach { trigger -> + + for (i in VConstants.TRG_TYPES.indices) { + if (trigger.events shr i and 1 > 0) { + model.PIVOT_TABLE_Triggers[0][i] = trigger + } + } + } + + return trigger + } + + private fun formEventList(PivotTableTriggerEvent: Array>): Long { + var self = 0L + + PivotTableTriggerEvent.forEach { trigger -> + self = self or (1L shl trigger.event) + } + + return self + } + /** * Returns the row's data. * @@ -142,6 +149,23 @@ abstract class PivotTable(title: String, val help: String?, locale: Locale? = nu model.addDefaultPivotTableCommands() } + /////////////////////////////////////////////////////////////////////////// + // PIVOT TABLE TRIGGERS EVENTS + /////////////////////////////////////////////////////////////////////////// + + /** + * Pivot table Triggers + * + * @param event the event of the trigger + */ + open class PivotTableTriggerEvent(val event: Int) + + /** + * Executed at pivot table initialization. + */ + + val INITPIVOTTABLE = PivotTableTriggerEvent(Constants.TRG_INIT) + // ---------------------------------------------------------------------- // XML LOCALIZATION GENERATION // ---------------------------------------------------------------------- @@ -168,6 +192,18 @@ abstract class PivotTable(title: String, val help: String?, locale: Locale? = nu (writer as PivotTableLocalizationWriter).genPivotTable(title, fields, menus, actors) } + var pivotTableType: String + get() = model.pivottableType + set(value) { + model.setType(value) + } + + var aggregator: Pair + get() = model.aggregator + set(value) { + model.setAggregator(value) + } + // ---------------------------------------------------------------------- // Pivot table MODEL // ---------------------------------------------------------------------- diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/Constants.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/Constants.kt new file mode 100644 index 000000000..0aae00d6f --- /dev/null +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/Constants.kt @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package org.kopi.galite.visual.pivotTable + +import org.kopi.galite.visual.form.VConstants +import org.kopi.galite.visual.Constants + +/** + * Collects some constants for the pivot table implementation + */ +interface Constants : Constants { + companion object { + // --------------------------------------------------------------------- + // PIVOT TABLE RENDERER + // --------------------------------------------------------------------- + const val DEFAULT_RENDERER = "Table" + const val TABLE_BARCHART = "Table Barchart" + const val TABLE_HEATMAP = "Heatmap" + const val ROW_HEATMAP = "Row Heatmap" + const val COL_HEATMAP = "Col Heatmap" + + // --------------------------------------------------------------------- + // PIVOT TABLE Aggregator + // --------------------------------------------------------------------- + const val DEFAULT_AGGREGATOR = "Count" + const val DEFAULT_AGGREGATE_COLUMN = "" + const val COUNT_UNIQUE_VALUES = "Count Unique Values" + const val LIST_UNIQUE_VALUES = "List Unique Values" + const val SUM = "Sum" + const val INTEGER_SUM = "Integer Sum" + const val AVERAGE = "Average" + const val MEDIAN = "Median" + const val SAMPLE_VARIANCE = "Sample Variance" + const val SAMPLE_STANDARD_DEVIATION = "Sample Standard Deviation" + const val MINIMUM = "Minimum" + const val MAXIMUM = "Maximum" + const val FIRST = "First" + const val LAST = "Last" + const val SUM_OVER_SUM = "Sum Over Sum" + const val UPPER_BOUND = "80% Upper Bound" + const val LOWER_BOUND = "80% Lower Bound" + const val SUM_FRACTION_TOTALS = "Sum as Fraction of Total" + const val SUM_FRACTION_ROWS = "Sum as Fraction of Rows" + const val SUM_FRACTION_COLUMNS = "Sum as Fraction of Columns" + const val COUNT_FRACTION_TOTALS = "Count as Fraction of Total" + const val COUNT_FRACTION_ROWS = "Count as Fraction of Rows" + const val COUNT_FRACTION_COLUMNS = "Count as Fraction of Columns" + + // --------------------------------------------------------------------- + // TRIGGERED EVENTS + // --------------------------------------------------------------------- + const val TRG_INIT = 0 + const val TRG_PRE_PIVOT_TABLE = 1 + const val TRG_POST_PIVOT_TABLE = 2 + const val TRG_VOID = VConstants.TRG_VOID + const val TRG_OBJECT = VConstants.TRG_OBJECT + + // --------------------------------------------------------------------- + // PREDEFINED COMMANDS + // --------------------------------------------------------------------- + const val CMD_QUIT = 0 + + // --------------------------------------------------------------------- + // TRIGGER INFO + // --------------------------------------------------------------------- + val TRG_NAMES = arrayOf( + "TRG_INIT", + "TRG_PRE_PIVOT_TABLE", + "TRG_POST_PIVOT_TABLE", + ) + val TRG_TYPES = intArrayOf( + TRG_VOID, + TRG_VOID, + TRG_VOID + ) + } +} \ No newline at end of file diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VPivotTable.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VPivotTable.kt index 8aa25c655..948373ff8 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VPivotTable.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VPivotTable.kt @@ -18,6 +18,7 @@ package org.kopi.galite.visual.pivotTable +import org.kopi.galite.util.base.InconsistencyException import org.kopi.galite.visual.ApplicationContext import org.kopi.galite.visual.form.VConstants import org.kopi.galite.visual.l10n.LocalizationManager @@ -27,6 +28,7 @@ import org.kopi.galite.visual.VCommand import org.kopi.galite.visual.VWindow import org.kopi.galite.visual.WindowBuilder import org.kopi.galite.visual.WindowController +import org.kopi.galite.visual.dsl.common.Trigger /** * Represents a pivot table model. @@ -53,6 +55,9 @@ abstract class VPivotTable internal constructor() : VWindow(), VConstants { val model: MPivotTable = MPivotTable() private var built = false private var pageTitle = "" + var pivottableType = Constants.DEFAULT_RENDERER // Default pivot table type + var aggregator = Pair(Constants.DEFAULT_AGGREGATOR, Constants.DEFAULT_AGGREGATE_COLUMN) // default Aggregator + val PIVOT_TABLE_Triggers = listOf(arrayOfNulls(Constants.TRG_TYPES.size)) private val activeCommands = ArrayList() var help: String? = null @@ -70,6 +75,22 @@ abstract class VPivotTable internal constructor() : VWindow(), VConstants { super.destroyModel() } + /** + * Sets the new type of this pivot table model. + * @param type The new pivot table type. + */ + internal fun setType(type: String) { + pivottableType = type + } + + /** + * Sets the new type of this pivot table model. + * @param type The new pivot table type. + */ + internal fun setAggregator(aggregate: Pair) { + aggregator = aggregate + } + /** * initialise fields */ @@ -82,6 +103,9 @@ abstract class VPivotTable internal constructor() : VWindow(), VConstants { init() // localize the pivot table using the default locale localize() + if (hasTrigger(Constants.TRG_INIT)) { + callTrigger(Constants.TRG_INIT) + } model.build() (getDisplay() as UPivotTable?)?.build() built = true @@ -91,8 +115,8 @@ abstract class VPivotTable internal constructor() : VWindow(), VConstants { commands.forEach { vCommand -> setCommandEnabled(vCommand, true) } - } + // ---------------------------------------------------------------------- // LOCALIZATION // ---------------------------------------------------------------------- @@ -128,6 +152,7 @@ abstract class VPivotTable internal constructor() : VWindow(), VConstants { // ---------------------------------------------------------------------- open fun initPivotTable() { build() + callTrigger(Constants.TRG_PRE_PIVOT_TABLE) } // ---------------------------------------------------------------------- // INTERFACE (COMMANDS) @@ -165,6 +190,45 @@ abstract class VPivotTable internal constructor() : VWindow(), VConstants { } } + // -------------------------------------------------------------------- + // TRIGGER HANDLING + // -------------------------------------------------------------------- + + override fun executeVoidTrigger(trigger: Trigger?) { + trigger?.action?.method?.invoke() + super.executeVoidTrigger(trigger) + } + + fun executeObjectTrigger(trigger: Trigger?): Any? { + return (trigger?.action?.method as () -> Any?).invoke() + } + + /** + * Calls trigger for given event, returns last trigger called 's value. + */ + protected fun callTrigger(event: Int): Any? { + return callTrigger(event, 0, PIVOT_TABLE_Triggers) + } + + /** + * Calls trigger for given event, returns last trigger called 's value. + */ + private fun callTrigger(event: Int, index: Int, triggers: List>): Any? { + return when (Constants.TRG_TYPES[event]) { + Constants.TRG_VOID -> { + executeVoidTrigger(triggers[index][event]) + null + } + Constants.TRG_OBJECT -> executeObjectTrigger(triggers[index][event]) + else -> throw InconsistencyException("BAD TYPE" + Constants.TRG_TYPES[event]) + } + } + + /** + * Returns true if there is trigger associated with given event. + */ + internal fun hasTrigger(event: Int): Boolean = PIVOT_TABLE_Triggers[0][event] != null + // ---------------------------------------------------------------------- // Command // ---------------------------------------------------------------------- diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/DPivotTable.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/DPivotTable.kt index 025400cfd..93db594b1 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/DPivotTable.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/DPivotTable.kt @@ -56,7 +56,6 @@ class DPivotTable(private val pivotTable: VPivotTable) : DWindow(pivotTable), UP } override fun build() { - model.columns .forEach { pivotData.addColumn(it?.label, it?.javaClass) @@ -72,8 +71,10 @@ class DPivotTable(private val pivotTable: VPivotTable) : DWindow(pivotTable), UP } pivotOptions.setRows(*listeDimensions.toTypedArray()) + pivotOptions.setRenderer(pivotTable.pivottableType) + pivotOptions.setAggregator(pivotTable.aggregator.first, pivotTable.aggregator.second) val pivot = PivotTable(pivotData, pivotOptions, PivotTable.PivotMode.INTERACTIVE) add(pivot) } -} +} \ No newline at end of file diff --git a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/client/ClientP.kt b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/client/ClientP.kt index bde4793ec..4517c03f9 100644 --- a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/client/ClientP.kt +++ b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/client/ClientP.kt @@ -27,6 +27,7 @@ import org.kopi.galite.visual.domain.STRING import org.kopi.galite.visual.dsl.common.Icon import org.kopi.galite.visual.dsl.form.Key import org.kopi.galite.visual.dsl.pivotTable.PivotTable +import org.kopi.galite.visual.pivotTable.Constants /** * Client Report @@ -82,6 +83,11 @@ class ClientP : PivotTable(title = "Clients_Pivot_Table", locale = Locale.UK) { label = "Status" } + val init = trigger(INITPIVOTTABLE) { + pivotTableType = Constants.TABLE_BARCHART + aggregator = Pair(Constants.AVERAGE, ageClt.label!!) + } + val clients = Client.selectAll() init { diff --git a/galite-tests/src/test/kotlin/org/kopi/galite/tests/examples/DocumentationPivotTable.kt b/galite-tests/src/test/kotlin/org/kopi/galite/tests/examples/DocumentationPivotTable.kt index d4c92334e..609bbc1e8 100644 --- a/galite-tests/src/test/kotlin/org/kopi/galite/tests/examples/DocumentationPivotTable.kt +++ b/galite-tests/src/test/kotlin/org/kopi/galite/tests/examples/DocumentationPivotTable.kt @@ -30,20 +30,19 @@ class DocumentationPivotTable : PivotTable(title = "Test Pivot Table", locale = // test to upper Case format + align left val name = field(STRING(25)) { label = "Name" - help = "The name" } // test to lower Case format + align right - val lastName = nullableField(STRING(25)) { + val lastName = field(STRING(25)) { label = "last Name " } // test normal format + align center - val middleName = nullableField(STRING(25)) { + val middleName = field(STRING(25)) { label = "middleName" } - val age = nullableField(INT(25)) { + val age = field(INT(25)) { label = "age" } @@ -54,9 +53,9 @@ class DocumentationPivotTable : PivotTable(title = "Test Pivot Table", locale = testTable.forEach { result -> add { this[name] = result[TestTable.name] - this[lastName] = result[TestTable.lastName] - this[middleName] = result[TestTable.lastName] - this[age] = result[TestTable.age] + this[lastName] = result[TestTable.lastName]!! + this[middleName] = result[TestTable.lastName]!! + this[age] = result[TestTable.age]!! } } } From 1c64f0a3dbb1b2eca701ef29cf4cca40391796ec Mon Sep 17 00:00:00 2001 From: Super User Date: Tue, 31 Oct 2023 17:12:19 +0100 Subject: [PATCH 13/20] Pivot table : Add chart renderer implementation Pivot Table : Add help popup Pivot Table : Add Aggregator function --- .../visual/dsl/pivotTable/PivotTableField.kt | 6 +- .../galite/visual/pivotTable/Constants.kt | 13 +- .../galite/visual/pivotTable/MPivotTable.kt | 17 +++ .../visual/pivotTable/VHelpGenerator.kt | 115 ++++++++++++++++++ .../galite/visual/pivotTable/VPivotTable.kt | 37 ++++-- .../visual/pivotTable/VPivotTableColumn.kt | 8 +- .../ui/vaadin/pivotTable/DPivotTable.kt | 17 ++- .../kotlin/org/kopi/galite/demo/bill/BillP.kt | 8 +- .../org/kopi/galite/demo/client/ClientP.kt | 15 +++ 9 files changed, 213 insertions(+), 23 deletions(-) create mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VHelpGenerator.kt diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTableField.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTableField.kt index 64b9bd6e9..90ebe2836 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTableField.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTableField.kt @@ -30,7 +30,8 @@ class PivotTableField(override val domain: Domain, /** * Dimension values */ - var dimension: Boolean? = null + var dimensionRow: Boolean? = null + var dimensionColumn: Boolean? = null fun initField() { init() } @@ -40,7 +41,8 @@ class PivotTableField(override val domain: Domain, fun buildPivotTableColumn(): VPivotTableColumn { model = domain.buildPivotTableFieldModel(this).also { column -> column.label = label ?: "" - column.dimension = dimension + column.dimensionRow = dimensionRow + column.dimensionColumn = dimensionColumn } return model diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/Constants.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/Constants.kt index 0aae00d6f..b2e2420ff 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/Constants.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/Constants.kt @@ -34,6 +34,14 @@ interface Constants : Constants { const val TABLE_HEATMAP = "Heatmap" const val ROW_HEATMAP = "Row Heatmap" const val COL_HEATMAP = "Col Heatmap" + const val HORIZONTAL_BAR_CHART = "Horizontal Bar Chart" + const val HORIZONTAL_STACKED_BAR_CHART = "Horizontal Stacked Bar Chart" + const val BAR_CHART = "Bar Chart" + const val STACKED_BAR_CHART = "Stacked Bar Chart" + const val LINE_CHART = "Line Chart" + const val AREA_CHART = "Area Chart" + const val SCATTER_CHART = "Scatter Chart" + const val TSV_EXPORT = "TSV Export" // --------------------------------------------------------------------- // PIVOT TABLE Aggregator @@ -71,11 +79,6 @@ interface Constants : Constants { const val TRG_VOID = VConstants.TRG_VOID const val TRG_OBJECT = VConstants.TRG_OBJECT - // --------------------------------------------------------------------- - // PREDEFINED COMMANDS - // --------------------------------------------------------------------- - const val CMD_QUIT = 0 - // --------------------------------------------------------------------- // TRIGGER INFO // --------------------------------------------------------------------- diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/MPivotTable.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/MPivotTable.kt index ae129eac5..ce8c5076f 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/MPivotTable.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/MPivotTable.kt @@ -50,4 +50,21 @@ class MPivotTable : Serializable { throw VNoRowException(MessageCode.getMessage("VIS-00015")) } } + + // -------------------------------------------------------------------- + // MEMBER ACCESS + // -------------------------------------------------------------------- + /** + * Return a column definition + * + * @param column the index of the desired column + * @return the desired column + */ + fun getModelColumn(column: Int): VPivotTableColumn = columns[column]!! + /** + * Returns the number of model columns + * + * @return the number or columns to display + */ + fun getModelColumnCount(): Int = columns.size } \ No newline at end of file diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VHelpGenerator.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VHelpGenerator.kt new file mode 100644 index 000000000..e5241edc9 --- /dev/null +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VHelpGenerator.kt @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package org.kopi.galite.visual.pivotTable + +import java.io.BufferedWriter +import java.io.File +import java.io.FileOutputStream +import java.io.IOException +import java.io.OutputStreamWriter +import java.io.PrintWriter + +import org.kopi.galite.visual.base.Utils +import org.kopi.galite.visual.VCommand +import org.kopi.galite.visual.VHelpGenerator + +/** + * This class implements a pretty printer + */ +class VHelpGenerator : VHelpGenerator() { + // ---------------------------------------------------------------------- + // ACCESSORS + // ---------------------------------------------------------------------- + /** + * prints a compilation unit + */ + fun helpOnPivotTable(name: String, + commands: List, + model: MPivotTable, + help: String?): String? { + return try { + val file: File = Utils.getTempFile(name.replace("[:\\\\/*\"?|<>']".toRegex(), " "), "htm") + printer = PrintWriter(BufferedWriter(OutputStreamWriter(FileOutputStream(file), "UTF-8"))) + printer.println("") + printer.println("") + printer.println("
") + printer.println("$name") + printer.println("") + printer.println("") + printer.println("") + printer.println("") + printer.println("") + printer.println("") + printer.println("") + printer.println("

$name

") + if (help != null) { + printer.println("

$help

") + } + helpOnCommands(commands) + val columnCount: Int = model.getModelColumnCount() + printer.println("") + printer.println("") + printer.println("") + printer.println("") + printer.println("") + printer.println("
    
") + printer.println("
") + printer.println("
") + for (i in 0 until columnCount) { + val column: VPivotTableColumn = model.getModelColumn(i) + column.helpOnColumn(this) + } + printer.println("
") + printer.println("
") + printer.println("
") + printer.println("
") + printer.println("kopiLeft Services SARL, Tunis TN
") + printer.println("kopiRight Managed Solutions GmbH, Wien AT
") + val version = Utils.getVersion() + for (i in version.indices) { + printer.println("" + version[i] + "
") + } + printer.println("
") + printer.println("
") + printer.println("") + printer.println("") + printer.close() + file.path + } catch (e: IOException) { + System.err.println("IO ERROR $e") + null + } + } + + /** + * prints a compilation unit + */ + fun helpOnColumn(label: String?, + help: String?) { + if (label == null) { + return + } + printer.println("
") + printer.println("

$label

") + printer.println("
") + if (help != null) { + printer.println("

$help

") + } + } +} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VPivotTable.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VPivotTable.kt index 948373ff8..0b2562cc7 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VPivotTable.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VPivotTable.kt @@ -19,16 +19,12 @@ package org.kopi.galite.visual.pivotTable import org.kopi.galite.util.base.InconsistencyException -import org.kopi.galite.visual.ApplicationContext +import org.kopi.galite.visual.* import org.kopi.galite.visual.form.VConstants import org.kopi.galite.visual.l10n.LocalizationManager -import org.kopi.galite.visual.UIFactory -import org.kopi.galite.visual.UWindow -import org.kopi.galite.visual.VCommand -import org.kopi.galite.visual.VWindow -import org.kopi.galite.visual.WindowBuilder -import org.kopi.galite.visual.WindowController import org.kopi.galite.visual.dsl.common.Trigger +import java.io.File +import java.net.MalformedURLException /** * Represents a pivot table model. @@ -229,6 +225,33 @@ abstract class VPivotTable internal constructor() : VWindow(), VConstants { */ internal fun hasTrigger(event: Int): Boolean = PIVOT_TABLE_Triggers[0][event] != null + // ---------------------------------------------------------------------- + // HELP + // ---------------------------------------------------------------------- + + fun genHelp(): String? { + val surl = StringBuffer() + val fileName: String? = VHelpGenerator().helpOnPivotTable(pageTitle, + commands, + model, + help) + + return if (fileName == null) { + null + } else { + try { + surl.append(File(fileName).toURI().toURL().toString()) + } catch (mue: MalformedURLException) { + throw InconsistencyException(mue) + } + surl.toString() + } + } + + fun showHelp() { + VHelpViewer().showHelp(genHelp()) + } + // ---------------------------------------------------------------------- // Command // ---------------------------------------------------------------------- diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VPivotTableColumn.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VPivotTableColumn.kt index 0b8af8d3a..363e3a298 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VPivotTableColumn.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VPivotTableColumn.kt @@ -33,7 +33,9 @@ class VPivotTableColumn(val ident: String?) { // DATA MEMBERS // ---------------------------------------------------------------------- var label: String = "" - var dimension: Boolean? = null + var help: String? = null + var dimensionRow: Boolean? = null + var dimensionColumn: Boolean? = null // ---------------------------------------------------------------------- // LOCALIZATION @@ -50,4 +52,8 @@ class VPivotTableColumn(val ident: String?) { label = loc.getLabel() ?: "" } } + + fun helpOnColumn(help: VHelpGenerator) { + help.helpOnColumn(label, this.help) + } } diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/DPivotTable.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/DPivotTable.kt index 93db594b1..719195be5 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/DPivotTable.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/DPivotTable.kt @@ -34,7 +34,8 @@ class DPivotTable(private val pivotTable: VPivotTable) : DWindow(pivotTable), UP private val model: MPivotTable = pivotTable.model // pivot table model private var pivotData = PivotTable.PivotData() private var pivotOptions = PivotTable.PivotOptions() - private val listeDimensions = mutableListOf() + private val listeDimensionRows = mutableListOf() + private val listeDimensionColumns = mutableListOf() init { getModel()!!.setDisplay(this) @@ -59,8 +60,11 @@ class DPivotTable(private val pivotTable: VPivotTable) : DWindow(pivotTable), UP model.columns .forEach { pivotData.addColumn(it?.label, it?.javaClass) - if (it?.dimension == true) { - listeDimensions.add(it.label) + if (it?.dimensionRow == true) { + listeDimensionRows.add(it.label) + } + if (it?.dimensionColumn == true) { + listeDimensionColumns.add(it.label) } } @@ -70,9 +74,14 @@ class DPivotTable(private val pivotTable: VPivotTable) : DWindow(pivotTable), UP pivotData.addRow(*rows.toTypedArray()) } - pivotOptions.setRows(*listeDimensions.toTypedArray()) + pivotOptions.setRows(*listeDimensionRows.toTypedArray()) + pivotOptions.setCols(*listeDimensionColumns.toTypedArray()) pivotOptions.setRenderer(pivotTable.pivottableType) pivotOptions.setAggregator(pivotTable.aggregator.first, pivotTable.aggregator.second) + + if(listeDimensionRows.isNotEmpty() && listeDimensionColumns.isNotEmpty()) { + pivotOptions.setCharts(true) + } val pivot = PivotTable(pivotData, pivotOptions, PivotTable.PivotMode.INTERACTIVE) add(pivot) diff --git a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/bill/BillP.kt b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/bill/BillP.kt index a23a1514e..b1995d387 100644 --- a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/bill/BillP.kt +++ b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/bill/BillP.kt @@ -47,16 +47,16 @@ class BillP : PivotTable("Bills_Pivot_Table", locale = Locale.UK) { val numBill = field(INT(25)) { label = "Number" - dimension = true + dimensionRow = true } val addressBill = field(STRING(25)) { label = "Address" - dimension = true + dimensionRow = true } val dateBill = field(DATE) { label = "Date" - dimension = true + dimensionRow = true } val amountWithTaxes = field(DECIMAL(20, 10)) { @@ -65,7 +65,7 @@ class BillP : PivotTable("Bills_Pivot_Table", locale = Locale.UK) { val refCmd = field(INT(50)) { label = "Command reference" - dimension = true + dimensionRow = true } val bills = Bill.selectAll() diff --git a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/client/ClientP.kt b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/client/ClientP.kt index 4517c03f9..99737899a 100644 --- a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/client/ClientP.kt +++ b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/client/ClientP.kt @@ -49,38 +49,53 @@ class ClientP : PivotTable(title = "Clients_Pivot_Table", locale = Locale.UK) { val cmdQuit = command(item = quit) { model.close() } + val helpCmd = command(item = helpForm) { + model.showHelp() + } val firstName = field(STRING(25)) { label = "First Name" + help = "The client first name" + dimensionRow = true } val lastName = field(STRING(25)) { label = "Last Name" + help = "The client last name" + dimensionRow = true } val addressClt = field(STRING(50)) { label = "Address" + help = "The client address" } val ageClt = field(INT(2)) { label = "Age" + help = "The client age" } val countryClt = field(STRING(50)) { label = "Country" + help = "The client country" + dimensionColumn = true } val cityClt = field(STRING(50)) { label = "City" + help = "The client city" + dimensionColumn = true } val zipCodeClt = field(INT(2)) { label = "Zip code" + help = "The client zip code" } val activeClt = field(BOOL) { label = "Status" + help = "Is the client active?" } val init = trigger(INITPIVOTTABLE) { From 7cf10d73be74ca07727379c19731f32d5527e336 Mon Sep 17 00:00:00 2001 From: Super User Date: Fri, 3 Nov 2023 11:46:24 +0100 Subject: [PATCH 14/20] =?UTF-8?q?corriger=20le=20style=20du=20composante?= =?UTF-8?q?=20table=20pivot=20:=20pivottable.css=20Ajouter=20un=20message?= =?UTF-8?q?=20lors=20de=20la=20r=C3=A9g=C3=A9n=C3=A9ration=20du=20table=20?= =?UTF-8?q?pivot=20Corriger=20l'ordre=20des=20colonnes=20lors=20de=20la=20?= =?UTF-8?q?r=C3=A9g=C3=A9n=C3=A9ration=20du=20table=20pivot?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/kopi/galite/visual/form/VDictionaryForm.kt | 2 +- .../org/kopi/galite/visual/pivotTable/MPivotTable.kt | 2 +- .../galite/visual/ui/vaadin/pivotTable/DPivotTable.kt | 9 +-------- .../resources/frontend/styles/galite/common.css | 1 - .../resources/frontend/styles/galite/pivottable.css | 11 +++++++++-- .../org/kopi/galite/visual/VKMessages-ar_TN.xml | 1 + .../org/kopi/galite/visual/VKMessages-de_AT.xml | 1 + .../org/kopi/galite/visual/VKMessages-en_GB.xml | 1 + .../org/kopi/galite/visual/VKMessages-fr_FR.xml | 1 + 9 files changed, 16 insertions(+), 13 deletions(-) diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/form/VDictionaryForm.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/form/VDictionaryForm.kt index 64b3e6fc6..c810e4fd6 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/form/VDictionaryForm.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/form/VDictionaryForm.kt @@ -231,7 +231,7 @@ abstract class VDictionaryForm protected constructor(source: String? = null) : V fun createPivotTable(b: VBlock, reportBuilder: () -> VPivotTable) { b.validate() try { - setWaitInfo(Message.getMessage("report_generation")) + setWaitInfo(Message.getMessage("pivotTable_generation")) val report = reportBuilder() report.doNotModal() unsetWaitInfo() diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/MPivotTable.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/MPivotTable.kt index ce8c5076f..de46ca800 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/MPivotTable.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/MPivotTable.kt @@ -45,7 +45,7 @@ class MPivotTable : Serializable { */ internal fun build() { // build accessible columns - columns.sortBy { it?.ident } + columns.sortBy { it?.ident?.substringAfter("_")?.toInt() } if (userRows!!.size == 0) { throw VNoRowException(MessageCode.getMessage("VIS-00015")) } diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/DPivotTable.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/DPivotTable.kt index 719195be5..dcc641f4a 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/DPivotTable.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/DPivotTable.kt @@ -39,13 +39,6 @@ class DPivotTable(private val pivotTable: VPivotTable) : DWindow(pivotTable), UP init { getModel()!!.setDisplay(this) - setSizeFull() - element.style["display"] = "flex!important" - element.style["flex-direction"] = "column!important" - element.style["overflow"] = "auto!important" - element.style["position"] = "relative!important" - element.style["outline"] = "none!important" - element.style["z-index"] = "0!important" } //--------------------------------------------------- @@ -86,4 +79,4 @@ class DPivotTable(private val pivotTable: VPivotTable) : DWindow(pivotTable), UP add(pivot) } -} \ No newline at end of file +} diff --git a/galite-core/src/main/resources/META-INF/resources/frontend/styles/galite/common.css b/galite-core/src/main/resources/META-INF/resources/frontend/styles/galite/common.css index e605cd732..9a5820245 100644 --- a/galite-core/src/main/resources/META-INF/resources/frontend/styles/galite/common.css +++ b/galite-core/src/main/resources/META-INF/resources/frontend/styles/galite/common.css @@ -18,7 +18,6 @@ html, body, #main, #content, #actors { width: 100%; - height: 100%; display: inline-block; } diff --git a/galite-core/src/main/resources/META-INF/resources/frontend/styles/galite/pivottable.css b/galite-core/src/main/resources/META-INF/resources/frontend/styles/galite/pivottable.css index 1c1f6a234..6adf21106 100644 --- a/galite-core/src/main/resources/META-INF/resources/frontend/styles/galite/pivottable.css +++ b/galite-core/src/main/resources/META-INF/resources/frontend/styles/galite/pivottable.css @@ -16,7 +16,14 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -.pvtUi {color: #333;} +.pvtUi { + color: #333; + height: 785px; + width: 1920px; + overflow: auto; + display: flow; + padding-bottom: 10px; +} table.pvtTable { @@ -129,4 +136,4 @@ table.pvtTable tbody tr td { .pvtCheckContainer p{ margin: 5px; } -.pvtRendererArea {padding: 5px;} \ No newline at end of file +.pvtRendererArea {padding: 5px;} diff --git a/galite-core/src/main/resources/org/kopi/galite/visual/VKMessages-ar_TN.xml b/galite-core/src/main/resources/org/kopi/galite/visual/VKMessages-ar_TN.xml index 582beac09..f031aba9c 100755 --- a/galite-core/src/main/resources/org/kopi/galite/visual/VKMessages-ar_TN.xml +++ b/galite-core/src/main/resources/org/kopi/galite/visual/VKMessages-ar_TN.xml @@ -23,6 +23,7 @@ + diff --git a/galite-core/src/main/resources/org/kopi/galite/visual/VKMessages-de_AT.xml b/galite-core/src/main/resources/org/kopi/galite/visual/VKMessages-de_AT.xml index 5e46c7ab7..0c64ade6f 100644 --- a/galite-core/src/main/resources/org/kopi/galite/visual/VKMessages-de_AT.xml +++ b/galite-core/src/main/resources/org/kopi/galite/visual/VKMessages-de_AT.xml @@ -23,6 +23,7 @@ + diff --git a/galite-core/src/main/resources/org/kopi/galite/visual/VKMessages-en_GB.xml b/galite-core/src/main/resources/org/kopi/galite/visual/VKMessages-en_GB.xml index fa938c004..99e8161ae 100644 --- a/galite-core/src/main/resources/org/kopi/galite/visual/VKMessages-en_GB.xml +++ b/galite-core/src/main/resources/org/kopi/galite/visual/VKMessages-en_GB.xml @@ -23,6 +23,7 @@ + diff --git a/galite-core/src/main/resources/org/kopi/galite/visual/VKMessages-fr_FR.xml b/galite-core/src/main/resources/org/kopi/galite/visual/VKMessages-fr_FR.xml index fc4b306aa..9a60c9a1e 100644 --- a/galite-core/src/main/resources/org/kopi/galite/visual/VKMessages-fr_FR.xml +++ b/galite-core/src/main/resources/org/kopi/galite/visual/VKMessages-fr_FR.xml @@ -23,6 +23,7 @@ + From ea297b9c574f68d1f69dd768c6e465dcee13044c Mon Sep 17 00:00:00 2001 From: Super User Date: Mon, 6 Nov 2023 15:49:01 +0100 Subject: [PATCH 15/20] Add dimension and measure concepts --- build.gradle.kts | 2 +- .../org/kopi/galite/visual/domain/Domain.kt | 5 +- .../galite/visual/dsl/pivotTable/Dimension.kt | 53 +++++++ .../galite/visual/dsl/pivotTable/Measure.kt | 52 ++++++ .../visual/dsl/pivotTable/PivotTable.kt | 66 +++++--- .../visual/dsl/pivotTable/PivotTableField.kt | 27 +--- .../galite/visual/dsl/pivotTable/Position.kt | 23 +-- .../galite/visual/pivotTable/Constants.kt | 69 ++++---- .../galite/visual/pivotTable/MPivotTable.kt | 4 +- .../galite/visual/pivotTable/VPivotTable.kt | 22 ++- .../visual/pivotTable/VPivotTableColumn.kt | 5 +- .../ui/vaadin/pivotTable/DPivotTable.kt | 26 ++- .../org/kopi/galite/demo/bill/BillForm.kt | 5 - .../kotlin/org/kopi/galite/demo/bill/BillP.kt | 86 ---------- .../galite/demo/billproduct/BillProductP.kt | 6 +- .../org/kopi/galite/demo/client/ClientForm.kt | 2 - .../org/kopi/galite/demo/client/ClientP.kt | 27 ++-- .../kopi/galite/demo/provider/ProviderForm.kt | 5 - .../kopi/galite/demo/provider/ProviderP.kt | 72 --------- .../org/kopi/galite/demo/stock/StockForm.kt | 5 - .../org/kopi/galite/demo/stock/StockP.kt | 66 -------- .../org/kopi/galite/demo/taxRule/TaxRuleP.kt | 6 +- .../org/kopi/galite/tests/common/TestBase.kt | 26 --- .../tests/ui/swing/JApplicationTestBase.kt | 2 - .../tests/ui/vaadin/VApplicationTestBase.kt | 4 - .../org/kopi/galite/test/Menu-en_GB.xml | 1 - .../galite/tests/dsl/PivotTableDSLTests.kt | 96 ------------ .../galite/tests/examples/CommandsForm.kt | 8 - .../tests/examples/DocumentationPivotTable.kt | 63 -------- .../tests/examples/DocumentationReport.kt | 6 +- .../org/kopi/galite/tests/examples/Modules.kt | 2 - .../galite/tests/form/FormWithPivotTable.kt | 44 ------ .../tests/pivotTable/PivotTableTests.kt | 148 ------------------ 33 files changed, 266 insertions(+), 768 deletions(-) create mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/Dimension.kt create mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/Measure.kt rename galite-tests/src/test/kotlin/org/kopi/galite/tests/pivotTable/VRowTests.kt => galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/Position.kt (61%) delete mode 100644 galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/bill/BillP.kt delete mode 100644 galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/provider/ProviderP.kt delete mode 100644 galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/stock/StockP.kt delete mode 100644 galite-tests/src/test/kotlin/org/kopi/galite/tests/dsl/PivotTableDSLTests.kt delete mode 100644 galite-tests/src/test/kotlin/org/kopi/galite/tests/examples/DocumentationPivotTable.kt delete mode 100644 galite-tests/src/test/kotlin/org/kopi/galite/tests/form/FormWithPivotTable.kt delete mode 100644 galite-tests/src/test/kotlin/org/kopi/galite/tests/pivotTable/PivotTableTests.kt diff --git a/build.gradle.kts b/build.gradle.kts index f95916a7d..6bebd56a4 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -68,7 +68,7 @@ allprojects { apply(plugin = "maven-publish") apply(plugin = "signing") _java { - withJavadocJar() + //withJavadocJar() withSourcesJar() } diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/domain/Domain.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/domain/Domain.kt index c8c6f40ec..b802c90d2 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/domain/Domain.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/domain/Domain.kt @@ -75,6 +75,7 @@ import org.kopi.galite.type.Image import org.kopi.galite.type.Month import org.kopi.galite.type.Week import org.kopi.galite.visual.VColor +import org.kopi.galite.visual.dsl.pivotTable.Position /** * A domain is a data type with predefined list of allowed values. @@ -277,11 +278,11 @@ open class Domain(val width: Int? = null, /** * Builds the pivot table column model */ - open fun buildPivotTableFieldModel(field: org.kopi.galite.visual.dsl.pivotTable.PivotTableField<*>): org.kopi.galite.visual.pivotTable.VPivotTableColumn { + open fun buildPivotTableFieldModel(field: org.kopi.galite.visual.dsl.pivotTable.PivotTableField<*>, position: Position?): org.kopi.galite.visual.pivotTable.VPivotTableColumn { return with(field) { when (kClass) { Int::class, Long::class, String::class, BigDecimal::class, Boolean::class, org.joda.time.LocalDate::class, LocalDate::class, java.sql.Date::class, java.util.Date::class, Month::class, Week::class, org.joda.time.LocalTime::class, LocalTime::class, Instant::class, LocalDateTime::class, DateTime::class -> - org.kopi.galite.visual.pivotTable.VPivotTableColumn(ident) + org.kopi.galite.visual.pivotTable.VPivotTableColumn(ident, position) else -> throw java.lang.RuntimeException("Type ${kClass!!.qualifiedName} is not supported") } diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/Dimension.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/Dimension.kt new file mode 100644 index 000000000..e58673146 --- /dev/null +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/Dimension.kt @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +package org.kopi.galite.visual.dsl.pivotTable + +import org.kopi.galite.visual.domain.Domain +import org.kopi.galite.visual.dsl.common.LocalizationWriter +import org.kopi.galite.visual.pivotTable.VPivotTableColumn + +class Dimension(override val domain: Domain, + val init: Dimension.() -> Unit, + ident: String? = null, + val position: Position, + override val source: String?) : PivotTableField(domain, ident) { + + fun initField() { + init() + } + + lateinit var model: VPivotTableColumn + + fun buildPivotTableColumn(): VPivotTableColumn { + model = domain.buildPivotTableFieldModel(this, position).also { column -> + column.label = label ?: "" + } + + return model + } + + // ---------------------------------------------------------------------- + // XML LOCALIZATION GENERATION + // ---------------------------------------------------------------------- + /** + * Generates localization for the field in the xml file + */ + override fun genLocalization(writer: LocalizationWriter) { + (writer as PivotTableLocalizationWriter).genField(ident, label, help) + } +} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/Measure.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/Measure.kt new file mode 100644 index 000000000..9e66aac98 --- /dev/null +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/Measure.kt @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +package org.kopi.galite.visual.dsl.pivotTable + +import org.kopi.galite.visual.domain.Domain +import org.kopi.galite.visual.dsl.common.LocalizationWriter +import org.kopi.galite.visual.pivotTable.VPivotTableColumn + +class Measure(override val domain: Domain, + val init: Measure.() -> Unit, + ident: String? = null, + override val source: String?) : PivotTableField(domain, ident) { + + fun initField() { + init() + } + + lateinit var model: VPivotTableColumn + + fun buildPivotTableColumn(): VPivotTableColumn { + model = domain.buildPivotTableFieldModel(this, Position.MEASURE).also { column -> + column.label = label ?: "" + } + + return model + } + + // ---------------------------------------------------------------------- + // XML LOCALIZATION GENERATION + // ---------------------------------------------------------------------- + /** + * Generates localization for the field in the xml file + */ + override fun genLocalization(writer: LocalizationWriter) { + (writer as PivotTableLocalizationWriter).genField(ident, label, help) + } +} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTable.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTable.kt index 9aedba7d2..ec5513a0d 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTable.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTable.kt @@ -32,33 +32,40 @@ abstract class PivotTable(title: String, val help: String?, locale: Locale? = nu constructor(title: String, locale: Locale? = null) : this(title, null, locale) /** Pivot table's fields. */ - val fields = mutableListOf>() - - var positionfield = 0 + val dimensionListe = mutableListOf>() + val measureListe = mutableListOf>() /** Pivot table's data rows. */ val pivotTableRows = mutableListOf() - /** - * creates and returns a field. It uses [init] method to initialize the field. - * - * @param domain the domain of the field. - * @param init initialization method. - * @return a field. - */ - inline fun ?> field(domain: Domain, - noinline init: PivotTableField.() -> Unit): PivotTableField { + + inline fun ?> dimension(domain: Domain, + position: Position, + noinline init: Dimension.() -> Unit): Dimension { domain.kClass = T::class - val field = PivotTableField(domain, init, "ANM_${fields.size}", domain.source.ifEmpty { `access$sourceFile` }) + val dimension = Dimension(domain, init, "ANM_${dimensionListe.size}",position, domain.source.ifEmpty { `access$sourceFile` }) - field.initField() + dimension.init() - model.model.columns.add(positionfield, field.buildPivotTableColumn()) - fields.add(field) - positionfield ++ + model.model.columns.add(dimension.buildPivotTableColumn()) + dimensionListe.add(dimension) - return field + return dimension + } + + inline fun ?> measure(domain: Domain, + noinline init: Measure.() -> Unit): Measure { + domain.kClass = T::class + + val dimension = Measure(domain, init, "ANM_${measureListe.size}", domain.source.ifEmpty { `access$sourceFile` }) + + dimension.init() + + model.model.columns.add(dimension.buildPivotTableColumn()) + measureListe.add(dimension) + + return dimension } /** @@ -67,7 +74,7 @@ abstract class PivotTable(title: String, val help: String?, locale: Locale? = nu * @param init initializes the row with values. */ fun add(init: PivotTableRow.() -> Unit) { - val row = PivotTableRow(fields) + val row = PivotTableRow((dimensionListe + measureListe).toMutableList()) row.init() val list = row.addLine() @@ -78,7 +85,7 @@ abstract class PivotTable(title: String, val help: String?, locale: Locale? = nu } private fun PivotTableRow.addLine(): List { - return fields.map { field -> + return (dimensionListe + measureListe).toMutableList().map { field -> data[field] } } @@ -189,7 +196,7 @@ abstract class PivotTable(title: String, val help: String?, locale: Locale? = nu } fun genLocalization(writer: LocalizationWriter) { - (writer as PivotTableLocalizationWriter).genPivotTable(title, fields, menus, actors) + (writer as PivotTableLocalizationWriter).genPivotTable(title, (dimensionListe + measureListe).toMutableList(), menus, actors) } var pivotTableType: String @@ -204,13 +211,28 @@ abstract class PivotTable(title: String, val help: String?, locale: Locale? = nu model.setAggregator(value) } + var disabledRerenders: MutableList + get() = model.disabledRerenders + set(value) { + model.setDisabledRerenders(value) + } + + var interactive: Int + get() = model.interactive + set(value) { + model.setInteractive(value) + } + // ---------------------------------------------------------------------- // Pivot table MODEL // ---------------------------------------------------------------------- override val model: VPivotTable = object : VPivotTable() { override fun init() { - fields.forEach { + dimensionListe.forEach { + it.initField() + } + measureListe.forEach { it.initField() } } diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTableField.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTableField.kt index 90ebe2836..6f89ed685 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTableField.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTableField.kt @@ -20,33 +20,8 @@ package org.kopi.galite.visual.dsl.pivotTable import org.kopi.galite.visual.domain.Domain import org.kopi.galite.visual.dsl.common.LocalizationWriter import org.kopi.galite.visual.dsl.field.Field -import org.kopi.galite.visual.pivotTable.VPivotTableColumn -class PivotTableField(override val domain: Domain, - val init: PivotTableField.() -> Unit, - ident: String? = null, - override val source: String?) : Field(domain, ident) { - - /** - * Dimension values - */ - var dimensionRow: Boolean? = null - var dimensionColumn: Boolean? = null - fun initField() { - init() - } - - lateinit var model: VPivotTableColumn - - fun buildPivotTableColumn(): VPivotTableColumn { - model = domain.buildPivotTableFieldModel(this).also { column -> - column.label = label ?: "" - column.dimensionRow = dimensionRow - column.dimensionColumn = dimensionColumn - } - - return model - } +abstract class PivotTableField(override val domain: Domain, ident: String? = null) : Field(domain, ident) { // ---------------------------------------------------------------------- // XML LOCALIZATION GENERATION diff --git a/galite-tests/src/test/kotlin/org/kopi/galite/tests/pivotTable/VRowTests.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/Position.kt similarity index 61% rename from galite-tests/src/test/kotlin/org/kopi/galite/tests/pivotTable/VRowTests.kt rename to galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/Position.kt index cc0ac9483..4b161bdc5 100644 --- a/galite-tests/src/test/kotlin/org/kopi/galite/tests/pivotTable/VRowTests.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/Position.kt @@ -14,23 +14,12 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -package org.kopi.galite.tests.pivotTable +package org.kopi.galite.visual.dsl.pivotTable -import kotlin.test.assertEquals +import org.kopi.galite.visual.pivotTable.Constants -import org.junit.Test -import org.kopi.galite.tests.common.TestBase -import org.kopi.galite.visual.pivotTable.VPivotTableRow - -class VRowTests : TestBase() { - - val intData: Array = arrayOf(1, 2, 3, 4) - - @Test - fun vBaseRowIntTest() { - /**Base row containing integer data*/ - val vBaseRowIntTest = VPivotTableRow(intData) - - assertEquals(1, vBaseRowIntTest.getValueAt(0)) - } +enum class Position(val value: Int) { + MEASURE(Constants.POS_MEASURE), + DIMENSION_ROW(Constants.POS_DIMENSION_ROW), + DIMENSION_COL(Constants.POS_DIMENSION_COL), } diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/Constants.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/Constants.kt index b2e2420ff..64456f246 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/Constants.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/Constants.kt @@ -20,46 +20,55 @@ package org.kopi.galite.visual.pivotTable import org.kopi.galite.visual.form.VConstants import org.kopi.galite.visual.Constants +import org.vaadin.addons.componentfactory.PivotTable.Renderer +import org.vaadin.addons.componentfactory.PivotTable.Aggregator /** * Collects some constants for the pivot table implementation */ interface Constants : Constants { companion object { + // --------------------------------------------------------------------- + // PIVOT TABLE POSITION + // --------------------------------------------------------------------- + const val POS_MEASURE = 0 + const val POS_DIMENSION_ROW = 1 + const val POS_DIMENSION_COL = 2 + // --------------------------------------------------------------------- // PIVOT TABLE RENDERER // --------------------------------------------------------------------- - const val DEFAULT_RENDERER = "Table" - const val TABLE_BARCHART = "Table Barchart" - const val TABLE_HEATMAP = "Heatmap" - const val ROW_HEATMAP = "Row Heatmap" - const val COL_HEATMAP = "Col Heatmap" - const val HORIZONTAL_BAR_CHART = "Horizontal Bar Chart" - const val HORIZONTAL_STACKED_BAR_CHART = "Horizontal Stacked Bar Chart" - const val BAR_CHART = "Bar Chart" - const val STACKED_BAR_CHART = "Stacked Bar Chart" - const val LINE_CHART = "Line Chart" - const val AREA_CHART = "Area Chart" - const val SCATTER_CHART = "Scatter Chart" - const val TSV_EXPORT = "TSV Export" + const val DEFAULT_RENDERER = Renderer.TABLE + const val TABLE_BARCHART = Renderer.TABLE_BARCHART + const val TABLE_HEATMAP = Renderer.TABLE_HEATMAP + const val ROW_HEATMAP = Renderer.ROW_HEATMAP + const val COL_HEATMAP = Renderer.COL_HEATMAP + const val HORIZONTAL_BAR_CHART = Renderer.HORIZONTAL_BAR_CHART + const val HORIZONTAL_STACKED_BAR_CHART = Renderer.HORIZONTAL_STACKED_BAR_CHART + const val BAR_CHART = Renderer.BAR_CHART + const val STACKED_BAR_CHART = Renderer.STACKED_BAR_CHART + const val LINE_CHART = Renderer.LINE_CHART + const val AREA_CHART = Renderer.AREA_CHART + const val SCATTER_CHART = Renderer.SCATTER_CHART + const val TSV_EXPORT = Renderer.TSV_EXPORT // --------------------------------------------------------------------- // PIVOT TABLE Aggregator // --------------------------------------------------------------------- - const val DEFAULT_AGGREGATOR = "Count" + const val DEFAULT_AGGREGATOR = Aggregator.COUNT const val DEFAULT_AGGREGATE_COLUMN = "" - const val COUNT_UNIQUE_VALUES = "Count Unique Values" - const val LIST_UNIQUE_VALUES = "List Unique Values" - const val SUM = "Sum" - const val INTEGER_SUM = "Integer Sum" - const val AVERAGE = "Average" - const val MEDIAN = "Median" - const val SAMPLE_VARIANCE = "Sample Variance" - const val SAMPLE_STANDARD_DEVIATION = "Sample Standard Deviation" - const val MINIMUM = "Minimum" - const val MAXIMUM = "Maximum" - const val FIRST = "First" - const val LAST = "Last" + const val COUNT_UNIQUE_VALUES = Aggregator.COUNT_UNIQUE_VALUES + const val LIST_UNIQUE_VALUES = Aggregator.LIST_UNIQUE_VALUES + const val SUM = Aggregator.SUM + const val INTEGER_SUM = Aggregator.INTEGER_SUM + const val AVERAGE = Aggregator.AVERAGE + const val MEDIAN = Aggregator.MEDIAN + const val SAMPLE_VARIANCE = Aggregator.SAMPLE_VARIANCE + const val SAMPLE_STANDARD_DEVIATION = Aggregator.SAMPLE_STANDARD_DEVIATION + const val MINIMUM = Aggregator.MINIMUM + const val MAXIMUM = Aggregator.MAXIMUM + const val FIRST = Aggregator.FIRST + const val LAST = Aggregator.LAST const val SUM_OVER_SUM = "Sum Over Sum" const val UPPER_BOUND = "80% Upper Bound" const val LOWER_BOUND = "80% Lower Bound" @@ -70,6 +79,12 @@ interface Constants : Constants { const val COUNT_FRACTION_ROWS = "Count as Fraction of Rows" const val COUNT_FRACTION_COLUMNS = "Count as Fraction of Columns" + // --------------------------------------------------------------------- + // PIVOT TABLE MODE + // --------------------------------------------------------------------- + const val MODE_INTERACTIVE = 0 + const val MODE_NONINTERACTIVE = 1 + // --------------------------------------------------------------------- // TRIGGERED EVENTS // --------------------------------------------------------------------- @@ -93,4 +108,4 @@ interface Constants : Constants { TRG_VOID ) } -} \ No newline at end of file +} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/MPivotTable.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/MPivotTable.kt index de46ca800..aa42320f3 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/MPivotTable.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/MPivotTable.kt @@ -45,7 +45,7 @@ class MPivotTable : Serializable { */ internal fun build() { // build accessible columns - columns.sortBy { it?.ident?.substringAfter("_")?.toInt() } + if (userRows!!.size == 0) { throw VNoRowException(MessageCode.getMessage("VIS-00015")) } @@ -67,4 +67,4 @@ class MPivotTable : Serializable { * @return the number or columns to display */ fun getModelColumnCount(): Int = columns.size -} \ No newline at end of file +} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VPivotTable.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VPivotTable.kt index 0b2562cc7..58b961e8f 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VPivotTable.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VPivotTable.kt @@ -53,6 +53,8 @@ abstract class VPivotTable internal constructor() : VWindow(), VConstants { private var pageTitle = "" var pivottableType = Constants.DEFAULT_RENDERER // Default pivot table type var aggregator = Pair(Constants.DEFAULT_AGGREGATOR, Constants.DEFAULT_AGGREGATE_COLUMN) // default Aggregator + var disabledRerenders = mutableListOf() + var interactive = Constants.MODE_INTERACTIVE val PIVOT_TABLE_Triggers = listOf(arrayOfNulls(Constants.TRG_TYPES.size)) private val activeCommands = ArrayList() var help: String? = null @@ -80,13 +82,29 @@ abstract class VPivotTable internal constructor() : VWindow(), VConstants { } /** - * Sets the new type of this pivot table model. - * @param type The new pivot table type. + * Sets aggregation function of this pivot table model. + * @param aggregate The pivot table aggregation function. */ internal fun setAggregator(aggregate: Pair) { aggregator = aggregate } + /** + * Sets aggregation function of this pivot table model. + * @param aggregate The pivot table aggregation function. + */ + internal fun setDisabledRerenders(rerenders: MutableList) { + disabledRerenders = rerenders + } + + /** + * Sets the mode of this pivot table model. + * @param interactive The pivot table mode. + */ + internal fun setInteractive(mode: Int) { + interactive = mode + } + /** * initialise fields */ diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VPivotTableColumn.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VPivotTableColumn.kt index 363e3a298..4932d2e61 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VPivotTableColumn.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VPivotTableColumn.kt @@ -18,6 +18,7 @@ package org.kopi.galite.visual.pivotTable +import org.kopi.galite.visual.dsl.pivotTable.Position import org.kopi.galite.visual.l10n.FieldLocalizer import org.kopi.galite.visual.l10n.PivotTableLocalizer @@ -27,15 +28,13 @@ import org.kopi.galite.visual.l10n.PivotTableLocalizer * @param ident The identifier of the field * */ -class VPivotTableColumn(val ident: String?) { +class VPivotTableColumn(val ident: String?, val position: Position?) { // ---------------------------------------------------------------------- // DATA MEMBERS // ---------------------------------------------------------------------- var label: String = "" var help: String? = null - var dimensionRow: Boolean? = null - var dimensionColumn: Boolean? = null // ---------------------------------------------------------------------- // LOCALIZATION diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/DPivotTable.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/DPivotTable.kt index dcc641f4a..2b945772c 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/DPivotTable.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/DPivotTable.kt @@ -18,6 +18,7 @@ package org.kopi.galite.visual.ui.vaadin.pivotTable import com.vaadin.flow.component.dependency.CssImport +import org.kopi.galite.visual.dsl.pivotTable.Position import org.kopi.galite.visual.pivotTable.MPivotTable import org.kopi.galite.visual.pivotTable.UPivotTable import org.kopi.galite.visual.pivotTable.VPivotTable @@ -32,8 +33,8 @@ class DPivotTable(private val pivotTable: VPivotTable) : DWindow(pivotTable), UP // DATA MEMBERS //--------------------------------------------------- private val model: MPivotTable = pivotTable.model // pivot table model - private var pivotData = PivotTable.PivotData() - private var pivotOptions = PivotTable.PivotOptions() + private val pivotData = PivotTable.PivotData() + private val pivotOptions = PivotTable.PivotOptions() private val listeDimensionRows = mutableListOf() private val listeDimensionColumns = mutableListOf() @@ -53,10 +54,10 @@ class DPivotTable(private val pivotTable: VPivotTable) : DWindow(pivotTable), UP model.columns .forEach { pivotData.addColumn(it?.label, it?.javaClass) - if (it?.dimensionRow == true) { + if (it?.position == Position.DIMENSION_ROW) { listeDimensionRows.add(it.label) } - if (it?.dimensionColumn == true) { + if (it?.position == Position.DIMENSION_COL) { listeDimensionColumns.add(it.label) } } @@ -67,15 +68,30 @@ class DPivotTable(private val pivotTable: VPivotTable) : DWindow(pivotTable), UP pivotData.addRow(*rows.toTypedArray()) } + // Pivot table dimension pivotOptions.setRows(*listeDimensionRows.toTypedArray()) pivotOptions.setCols(*listeDimensionColumns.toTypedArray()) + + // Pivot table default renderer pivotOptions.setRenderer(pivotTable.pivottableType) + + // Pivot table aggregate function pivotOptions.setAggregator(pivotTable.aggregator.first, pivotTable.aggregator.second) + // Pivot table renderer if(listeDimensionRows.isNotEmpty() && listeDimensionColumns.isNotEmpty()) { pivotOptions.setCharts(true) } - val pivot = PivotTable(pivotData, pivotOptions, PivotTable.PivotMode.INTERACTIVE) + pivotOptions.setDisabledRenderers(*pivotTable.disabledRerenders.toTypedArray()) + + // Pivot table mode + val pivotMode = if(pivotTable.interactive == 0) { + PivotTable.PivotMode.INTERACTIVE + } else { + PivotTable.PivotMode.NONINTERACTIVE + } + + val pivot = PivotTable(pivotData, pivotOptions, pivotMode) add(pivot) } diff --git a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/bill/BillForm.kt b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/bill/BillForm.kt index f52611aea..1fd767dc0 100644 --- a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/bill/BillForm.kt +++ b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/bill/BillForm.kt @@ -42,11 +42,6 @@ class BillForm : DictionaryForm(title = "Bills", locale = Locale.UK) { BillR() } } - command(item = pivotTable) { - createPivotTable { - BillP() - } - } } class BlockBill : Block("Bills", 1, 1) { diff --git a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/bill/BillP.kt b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/bill/BillP.kt deleted file mode 100644 index b1995d387..000000000 --- a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/bill/BillP.kt +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.kopi.galite.demo.bill - -import java.util.Locale - -import org.jetbrains.exposed.sql.selectAll -import org.jetbrains.exposed.sql.transactions.transaction -import org.kopi.galite.demo.database.Bill -import org.kopi.galite.visual.domain.DATE -import org.kopi.galite.visual.domain.DECIMAL -import org.kopi.galite.visual.domain.INT -import org.kopi.galite.visual.domain.STRING -import org.kopi.galite.visual.dsl.common.Icon -import org.kopi.galite.visual.dsl.form.Key -import org.kopi.galite.visual.dsl.pivotTable.PivotTable - -/** - * Bill Report - */ -class BillP : PivotTable("Bills_Pivot_Table", locale = Locale.UK) { - - val file = menu("File") - - val quit = actor(menu = file, label = "Quit", help = "Close Report.", ident = "quit") { - key = Key.ESCAPE - icon = Icon.QUIT - } - - val cmdQuit = command(item = quit) { - model.close() - } - - val numBill = field(INT(25)) { - label = "Number" - dimensionRow = true - } - - val addressBill = field(STRING(25)) { - label = "Address" - dimensionRow = true - } - val dateBill = field(DATE) { - label = "Date" - dimensionRow = true - } - - val amountWithTaxes = field(DECIMAL(20, 10)) { - label = "Amount to pay" - } - - val refCmd = field(INT(50)) { - label = "Command reference" - dimensionRow = true - } - - val bills = Bill.selectAll() - - init { - transaction { - bills.forEach { result -> - add { - this[numBill] = result[Bill.numBill] - this[addressBill] = result[Bill.addressBill] - this[dateBill] = result[Bill.dateBill] - this[amountWithTaxes] = result[Bill.amountWithTaxes] - this[refCmd] = result[Bill.refCmd] - } - } - } - } -} diff --git a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/billproduct/BillProductP.kt b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/billproduct/BillProductP.kt index 59f97cceb..5ad5dac4a 100644 --- a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/billproduct/BillProductP.kt +++ b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/billproduct/BillProductP.kt @@ -30,15 +30,15 @@ import org.kopi.galite.visual.dsl.pivotTable.PivotTable */ class BillProductP : PivotTable("Bill Product Report", Locale.UK) { - val quantity = field(INT(25)) { + val quantity = measure(INT(25)) { label = "Quantity" } - val amount = field(DECIMAL(25, 10)) { + val amount = measure(DECIMAL(25, 10)) { label = "Amount before tax" } - val amountWithTaxes = field(DECIMAL(50, 10)) { + val amountWithTaxes = measure(DECIMAL(50, 10)) { label = "Amount all taxes included" } diff --git a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/client/ClientForm.kt b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/client/ClientForm.kt index 13bf212de..fd4a57eae 100644 --- a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/client/ClientForm.kt +++ b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/client/ClientForm.kt @@ -21,8 +21,6 @@ import java.util.Locale import org.jetbrains.exposed.sql.SqlExpressionBuilder import org.jetbrains.exposed.sql.stringLiteral import org.jetbrains.exposed.sql.transactions.transaction -import org.kopi.galite.demo.bill.BillP -import org.kopi.galite.demo.command.CommandR import org.kopi.galite.demo.database.Client import org.kopi.galite.demo.database.Product diff --git a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/client/ClientP.kt b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/client/ClientP.kt index 99737899a..7d477a454 100644 --- a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/client/ClientP.kt +++ b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/client/ClientP.kt @@ -27,6 +27,7 @@ import org.kopi.galite.visual.domain.STRING import org.kopi.galite.visual.dsl.common.Icon import org.kopi.galite.visual.dsl.form.Key import org.kopi.galite.visual.dsl.pivotTable.PivotTable +import org.kopi.galite.visual.dsl.pivotTable.Position import org.kopi.galite.visual.pivotTable.Constants /** @@ -54,53 +55,51 @@ class ClientP : PivotTable(title = "Clients_Pivot_Table", locale = Locale.UK) { } - val firstName = field(STRING(25)) { + val firstName = dimension(STRING(25), Position.DIMENSION_ROW) { label = "First Name" help = "The client first name" - dimensionRow = true } - val lastName = field(STRING(25)) { + val lastName = dimension(STRING(25), Position.DIMENSION_ROW) { label = "Last Name" help = "The client last name" - dimensionRow = true } - val addressClt = field(STRING(50)) { + val addressClt = dimension(STRING(50), Position.DIMENSION_ROW) { label = "Address" help = "The client address" } - val ageClt = field(INT(2)) { + val ageClt = dimension(INT(2), Position.DIMENSION_COL) { label = "Age" help = "The client age" } - val countryClt = field(STRING(50)) { + val countryClt = dimension(STRING(50), Position.DIMENSION_ROW) { label = "Country" help = "The client country" - dimensionColumn = true } - val cityClt = field(STRING(50)) { + val cityClt = dimension(STRING(50), Position.MEASURE) { label = "City" help = "The client city" - dimensionColumn = true } - val zipCodeClt = field(INT(2)) { + val zipCodeClt = measure(INT(2)) { label = "Zip code" help = "The client zip code" } - val activeClt = field(BOOL) { + val activeClt = measure(BOOL) { label = "Status" help = "Is the client active?" } val init = trigger(INITPIVOTTABLE) { - pivotTableType = Constants.TABLE_BARCHART - aggregator = Pair(Constants.AVERAGE, ageClt.label!!) + pivotTableType = Constants.DEFAULT_RENDERER + aggregator = Pair(Constants.SAMPLE_VARIANCE, Constants.DEFAULT_AGGREGATE_COLUMN) + disabledRerenders = mutableListOf(Constants.SCATTER_CHART, Constants.LINE_CHART, Constants.HORIZONTAL_BAR_CHART, Constants.HORIZONTAL_STACKED_BAR_CHART) + //interactive = Constants.MODE_NONINTERACTIVE } val clients = Client.selectAll() diff --git a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/provider/ProviderForm.kt b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/provider/ProviderForm.kt index 9653c107d..626b585d3 100644 --- a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/provider/ProviderForm.kt +++ b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/provider/ProviderForm.kt @@ -41,11 +41,6 @@ class ProviderForm : DictionaryForm(title = "Providers", locale = Locale.UK) { ProviderR() } } - command(item = pivotTable) { - createPivotTable { - ProviderP() - } - } } class BlockProvider : Block("Providers", 1, 1) { diff --git a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/provider/ProviderP.kt b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/provider/ProviderP.kt deleted file mode 100644 index af51ecd6b..000000000 --- a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/provider/ProviderP.kt +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.kopi.galite.demo.provider - -import java.util.Locale - -import org.jetbrains.exposed.sql.selectAll -import org.jetbrains.exposed.sql.transactions.transaction -import org.kopi.galite.demo.database.Provider -import org.kopi.galite.visual.domain.INT -import org.kopi.galite.visual.domain.STRING -import org.kopi.galite.visual.dsl.common.Icon -import org.kopi.galite.visual.dsl.form.Key -import org.kopi.galite.visual.dsl.pivotTable.PivotTable - -/** - * Provider Report - */ -class ProviderP : PivotTable(title = "Providers_Report", locale = Locale.UK) { - - val action = menu("Action") - - val nameProvider = field(STRING(50)) { - label = "Name" - } - - val tel = field(INT(25)) { - label = "Phone number" - } - - val description = field(STRING(255)) { - label = "Description" - } - - val address = field(STRING(70)) { - label = "Address" - } - - val zipCode = field(INT(50)) { - label = "Zip code" - } - - val providers = Provider.selectAll() - - init { - transaction { - providers.forEach { result -> - add { - this[nameProvider] = result[Provider.nameProvider] - this[description] = result[Provider.description] - this[tel] = result[Provider.tel] - this[zipCode] = result[Provider.zipCode] - this[address] = result[Provider.address] - } - } - } - } -} diff --git a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/stock/StockForm.kt b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/stock/StockForm.kt index 0a3e6a9b6..b0970527a 100644 --- a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/stock/StockForm.kt +++ b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/stock/StockForm.kt @@ -42,11 +42,6 @@ class StockForm : DictionaryForm(title = "Stocks", locale = Locale.UK) { StockR() } } - command(item = pivotTable) { - createPivotTable { - StockP() - } - } } class StockBlock : Block("Stock", 1, 1) { diff --git a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/stock/StockP.kt b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/stock/StockP.kt deleted file mode 100644 index fdd49a2d3..000000000 --- a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/stock/StockP.kt +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.kopi.galite.demo.stock - -import java.util.Locale - -import org.jetbrains.exposed.sql.JoinType -import org.jetbrains.exposed.sql.selectAll -import org.jetbrains.exposed.sql.transactions.transaction -import org.kopi.galite.demo.database.Product -import org.kopi.galite.demo.database.Provider -import org.kopi.galite.demo.database.Stock -import org.kopi.galite.visual.domain.INT -import org.kopi.galite.visual.domain.STRING -import org.kopi.galite.visual.dsl.common.Icon -import org.kopi.galite.visual.dsl.form.Key -import org.kopi.galite.visual.dsl.pivotTable.PivotTable - -/** - * Stock Report - */ -class StockP : PivotTable(title = "Stocks", locale = Locale.UK) { - - val action = menu("Action") - - val description = field(STRING(25)) { - label = "Description" - } - val nameProvider = field(STRING(25)) { - label = "Provider name" - } - val minAlert = field(INT(25)) { - label = "Min Alert" - } - - val stocks = Stock.join(Provider, JoinType.INNER, Stock.idStckProv, Provider.idProvider) - .join(Product, JoinType.INNER, Stock.idStckProv, Product.idPdt) - .slice(Stock.minAlert, Product.description, Provider.nameProvider) - .selectAll() - - init { - transaction { - stocks.forEach { result -> - add { - this[minAlert] = result[Stock.minAlert] - this[description] = result[Product.description] - this[nameProvider] = result[Provider.nameProvider] - } - } - } - } -} diff --git a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/taxRule/TaxRuleP.kt b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/taxRule/TaxRuleP.kt index f44dbba55..3968ea881 100644 --- a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/taxRule/TaxRuleP.kt +++ b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/taxRule/TaxRuleP.kt @@ -23,8 +23,6 @@ import org.jetbrains.exposed.sql.transactions.transaction import org.kopi.galite.demo.database.TaxRule import org.kopi.galite.visual.domain.INT import org.kopi.galite.visual.domain.STRING -import org.kopi.galite.visual.dsl.common.Icon -import org.kopi.galite.visual.dsl.form.Key import org.kopi.galite.visual.dsl.pivotTable.PivotTable /** @@ -34,11 +32,11 @@ class TaxRuleP : PivotTable(title = "TaxRules_Report", locale = Locale.UK) { val action = menu("Action") - val taxName = field(STRING(50)) { + val taxName = measure(STRING(50)) { label = "Name" } - val rate = field(INT(25)) { + val rate = measure(INT(25)) { label = "Rate in %" } diff --git a/galite-tests/src/main/kotlin/org/kopi/galite/tests/common/TestBase.kt b/galite-tests/src/main/kotlin/org/kopi/galite/tests/common/TestBase.kt index a8bb79f4a..923fbf3c6 100644 --- a/galite-tests/src/main/kotlin/org/kopi/galite/tests/common/TestBase.kt +++ b/galite-tests/src/main/kotlin/org/kopi/galite/tests/common/TestBase.kt @@ -24,11 +24,7 @@ import org.kopi.galite.visual.base.UComponent import org.kopi.galite.visual.chart.UChart import org.kopi.galite.visual.chart.VChart import org.kopi.galite.visual.dsl.chart.Chart -import org.kopi.galite.visual.dsl.pivotTable.PivotTable import org.kopi.galite.visual.dsl.report.Report -import org.kopi.galite.visual.pivotTable.MPivotTable -import org.kopi.galite.visual.pivotTable.UPivotTable -import org.kopi.galite.visual.pivotTable.VPivotTable import org.kopi.galite.visual.report.MReport import org.kopi.galite.visual.report.UReport import org.kopi.galite.visual.report.VReport @@ -50,8 +46,6 @@ open class TestBase { open fun getChartDisplay(model: VChart): UComponent? = null - open fun getPivotTableDisplay(model: VPivotTable): UComponent? = null - /** * Tests operation on a report. * @@ -92,26 +86,6 @@ open class TestBase { } } - /** - * Tests operation on a pivot table. - * - * @param pivotTable The pivot table to test - * @param operations operations to apply on the pivot table - */ - fun withPivotTable(pivotTable: T, operations: (T.(model: MPivotTable) -> Unit)? = null) { - val display = getPivotTableDisplay(pivotTable.model) - - //assertNotNull(display) - - pivotTable.model.setDisplay( - (display as UPivotTable) - ) - - if (operations != null) { - pivotTable.operations(pivotTable.model.model) - } - } - // ---------------------------------------------------------------------- // Testing extension methods // ---------------------------------------------------------------------- diff --git a/galite-tests/src/main/kotlin/org/kopi/galite/tests/ui/swing/JApplicationTestBase.kt b/galite-tests/src/main/kotlin/org/kopi/galite/tests/ui/swing/JApplicationTestBase.kt index 9393b3710..1b1e916b1 100644 --- a/galite-tests/src/main/kotlin/org/kopi/galite/tests/ui/swing/JApplicationTestBase.kt +++ b/galite-tests/src/main/kotlin/org/kopi/galite/tests/ui/swing/JApplicationTestBase.kt @@ -32,8 +32,6 @@ import org.kopi.galite.visual.ImageHandler import org.kopi.galite.visual.PropertyException import org.kopi.galite.visual.UIFactory import org.kopi.galite.visual.WindowController -import org.kopi.galite.visual.pivotTable.VPivotTable -import org.kopi.galite.visual.ui.vaadin.pivotTable.DPivotTable import org.kopi.vkopi.lib.ui.swing.chart.DChart import org.kopi.vkopi.lib.ui.swing.report.DReport import org.kopi.vkopi.lib.ui.swing.visual.JApplication diff --git a/galite-tests/src/main/kotlin/org/kopi/galite/tests/ui/vaadin/VApplicationTestBase.kt b/galite-tests/src/main/kotlin/org/kopi/galite/tests/ui/vaadin/VApplicationTestBase.kt index d1b11b236..857d4d7a3 100644 --- a/galite-tests/src/main/kotlin/org/kopi/galite/tests/ui/vaadin/VApplicationTestBase.kt +++ b/galite-tests/src/main/kotlin/org/kopi/galite/tests/ui/vaadin/VApplicationTestBase.kt @@ -42,8 +42,6 @@ import org.kopi.galite.visual.UIFactory import org.kopi.galite.visual.WindowController import com.vaadin.flow.router.Route -import org.kopi.galite.visual.pivotTable.VPivotTable -import org.kopi.galite.visual.ui.vaadin.pivotTable.DPivotTable /** * TestBase class for all tests. @@ -68,8 +66,6 @@ open class VApplicationTestBase : ApplicationTestBase() { override fun getChartDisplay(model: VChart): UComponent? = DChart(model).also { it.run() } - override fun getPivotTableDisplay(model: VPivotTable): UComponent? = DPivotTable(model).also { it.run() } - companion object { val applicationContext = VApplicationContext() val fileHandler = VFileHandler() diff --git a/galite-tests/src/main/resources/org/kopi/galite/test/Menu-en_GB.xml b/galite-tests/src/main/resources/org/kopi/galite/test/Menu-en_GB.xml index f496d3987..f8ee0e3e3 100644 --- a/galite-tests/src/main/resources/org/kopi/galite/test/Menu-en_GB.xml +++ b/galite-tests/src/main/resources/org/kopi/galite/test/Menu-en_GB.xml @@ -4,7 +4,6 @@ - diff --git a/galite-tests/src/test/kotlin/org/kopi/galite/tests/dsl/PivotTableDSLTests.kt b/galite-tests/src/test/kotlin/org/kopi/galite/tests/dsl/PivotTableDSLTests.kt deleted file mode 100644 index ad4b8f0fc..000000000 --- a/galite-tests/src/test/kotlin/org/kopi/galite/tests/dsl/PivotTableDSLTests.kt +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.kopi.galite.tests.dsl - -import java.util.Locale - -import kotlin.test.assertEquals - -import org.junit.Test -import org.kopi.galite.tests.ui.vaadin.VApplicationTestBase -import org.kopi.galite.visual.domain.INT -import org.kopi.galite.visual.domain.STRING -import org.kopi.galite.visual.dsl.pivotTable.PivotTable - -class PivotTableDSLTests : VApplicationTestBase() { - - @Test - fun `test generated model from a basic pivot table`() { - val pivotTable = BasicPivotTable() - val model = pivotTable.model - - assertEquals(pivotTable.locale, model.locale) - assertEquals(pivotTable.title, model.getTitle()) - assertEquals(pivotTable.help, model.help) - } - - @Test - fun `test pivot table fields`() { - val pivotTable = PivotTableWithData() - val pivotTableModel = pivotTable.model - - assertEquals(3, pivotTableModel.model.columns.size) - println(pivotTableModel.model.columns[0]!!.label) - println(pivotTableModel.model.columns[1]!!.label) - println(pivotTableModel.model.columns[2]!!.label) - assertEquals(pivotTable.firstName.label, pivotTableModel.model.columns[0]!!.label) - assertEquals(pivotTable.addressClt.label, pivotTableModel.model.columns[1]!!.label) - assertEquals(pivotTable.ageClt.label, pivotTableModel.model.columns[2]!!.label) - } -} - -class BasicPivotTable : PivotTable( - title = "Clients Pivot Table", - help = "This is a pivot table that contains information about clients", - locale = Locale.UK -) - -class PivotTableWithData : PivotTable(title = "Clients Pivot Table", locale = Locale.UK) { - - val firstName = field(STRING(25)) { - label = "First Name" - help = "The client first name" - } - - val addressClt = field(STRING(50)) { - label = "Address" - help = "The client address" - } - - val ageClt = field(INT(2)) { - label = "Age" - help = "The client age" - } - - init { - add { - this[firstName] = "client 1" - this[addressClt] = "Tunis" - this[ageClt] = 20 - } - add { - this[firstName] = "client 1" - this[addressClt] = "Bizerte" - this[ageClt] = 20 - } - add { - this[firstName] = "client 2" - this[addressClt] = "Ben Arous" - this[ageClt] = 30 - } - } -} diff --git a/galite-tests/src/test/kotlin/org/kopi/galite/tests/examples/CommandsForm.kt b/galite-tests/src/test/kotlin/org/kopi/galite/tests/examples/CommandsForm.kt index d7edc8219..ff392791c 100644 --- a/galite-tests/src/test/kotlin/org/kopi/galite/tests/examples/CommandsForm.kt +++ b/galite-tests/src/test/kotlin/org/kopi/galite/tests/examples/CommandsForm.kt @@ -71,14 +71,6 @@ class CommandsForm : DictionaryForm(title = "Commands Form", locale = Locale.UK) key = Key.F7 icon = Icon.DETAIL_VIEW } - val pivottable = actor( - menu = actionMenu, - label = "Pivot table", - help = " Pivot table", - ) { - key = Key.F8 - icon = Icon.REPORT - } val helpCmd = command(item = help) { showHelp() diff --git a/galite-tests/src/test/kotlin/org/kopi/galite/tests/examples/DocumentationPivotTable.kt b/galite-tests/src/test/kotlin/org/kopi/galite/tests/examples/DocumentationPivotTable.kt deleted file mode 100644 index 609bbc1e8..000000000 --- a/galite-tests/src/test/kotlin/org/kopi/galite/tests/examples/DocumentationPivotTable.kt +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.kopi.galite.tests.examples - -import java.util.Locale - -import org.jetbrains.exposed.sql.selectAll -import org.jetbrains.exposed.sql.transactions.transaction -import org.kopi.galite.visual.domain.INT -import org.kopi.galite.visual.domain.STRING -import org.kopi.galite.visual.dsl.pivotTable.PivotTable - -class DocumentationPivotTable : PivotTable(title = "Test Pivot Table", locale = Locale.UK) { - - - // test to upper Case format + align left - val name = field(STRING(25)) { - label = "Name" - } - - // test to lower Case format + align right - val lastName = field(STRING(25)) { - label = "last Name " - } - - // test normal format + align center - val middleName = field(STRING(25)) { - label = "middleName" - } - - val age = field(INT(25)) { - label = "age" - } - - val testTable = TestTable.selectAll() - - init { - transaction { - testTable.forEach { result -> - add { - this[name] = result[TestTable.name] - this[lastName] = result[TestTable.lastName]!! - this[middleName] = result[TestTable.lastName]!! - this[age] = result[TestTable.age]!! - } - } - } - } -} diff --git a/galite-tests/src/test/kotlin/org/kopi/galite/tests/examples/DocumentationReport.kt b/galite-tests/src/test/kotlin/org/kopi/galite/tests/examples/DocumentationReport.kt index 5b886b4e5..f615bd7af 100644 --- a/galite-tests/src/test/kotlin/org/kopi/galite/tests/examples/DocumentationReport.kt +++ b/galite-tests/src/test/kotlin/org/kopi/galite/tests/examples/DocumentationReport.kt @@ -42,11 +42,7 @@ class DocumentationReport : DictionaryForm(title = "Test Report Form", locale = DocumentationReportR() } } - command(item = pivotTable) { - createPivotTable { - DocumentationPivotTable() - } - } + } } } diff --git a/galite-tests/src/test/kotlin/org/kopi/galite/tests/examples/Modules.kt b/galite-tests/src/test/kotlin/org/kopi/galite/tests/examples/Modules.kt index b5faefb6c..12a555622 100644 --- a/galite-tests/src/test/kotlin/org/kopi/galite/tests/examples/Modules.kt +++ b/galite-tests/src/test/kotlin/org/kopi/galite/tests/examples/Modules.kt @@ -18,7 +18,6 @@ package org.kopi.galite.tests.examples import org.jetbrains.exposed.sql.transactions.transaction import org.kopi.galite.tests.database.insertIntoModule -import org.kopi.galite.tests.form.FormWithPivotTable import org.kopi.galite.tests.form.FormWithReport import org.kopi.galite.tests.localization.LocalizedForm import org.kopi.galite.tests.ui.vaadin.field.FormToTestFormPopUp @@ -31,7 +30,6 @@ fun initModules() { transaction { insertIntoModule("1000", "org/kopi/galite/test/Menu", 0) insertIntoModule("1001", "org/kopi/galite/test/Menu", 1, "1000", FormWithReport::class) - insertIntoModule("1002", "org/kopi/galite/test/Menu", 2, "1000", FormWithPivotTable::class) insertIntoModule("2000", "org/kopi/galite/test/Menu", 100) insertIntoModule("2001", "org/kopi/galite/test/Menu", 101, "2000", CommandsForm::class) insertIntoModule("2002", "org/kopi/galite/test/Menu", 102, "2000", FormExample::class) diff --git a/galite-tests/src/test/kotlin/org/kopi/galite/tests/form/FormWithPivotTable.kt b/galite-tests/src/test/kotlin/org/kopi/galite/tests/form/FormWithPivotTable.kt deleted file mode 100644 index d8c057c8a..000000000 --- a/galite-tests/src/test/kotlin/org/kopi/galite/tests/form/FormWithPivotTable.kt +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.kopi.galite.tests.form - -import java.util.Locale - -import org.kopi.galite.tests.desktop.runForm -import org.kopi.galite.tests.pivotTable.SimplePivotTable -import org.kopi.galite.tests.report.SimpleReport -import org.kopi.galite.visual.dsl.common.Icon -import org.kopi.galite.visual.dsl.form.DictionaryForm -import org.kopi.galite.visual.dsl.form.Key -import org.kopi.galite.visual.dsl.form.ReportSelectionForm - -class FormWithPivotTable : DictionaryForm(title = "SimplePivotTable", locale = Locale.UK) { - - val testPage = page("test page") - - val block = testPage.insertBlock(BlockSample) { - command(item = pivotTable) { - createPivotTable { - SimplePivotTable() - } - } - } -} - -fun main() { - runForm(FormWithPivotTable()) -} diff --git a/galite-tests/src/test/kotlin/org/kopi/galite/tests/pivotTable/PivotTableTests.kt b/galite-tests/src/test/kotlin/org/kopi/galite/tests/pivotTable/PivotTableTests.kt deleted file mode 100644 index d9fc767d3..000000000 --- a/galite-tests/src/test/kotlin/org/kopi/galite/tests/pivotTable/PivotTableTests.kt +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.kopi.galite.tests.pivotTable - -import java.io.File -import java.math.BigDecimal -import java.util.Locale - -import kotlin.test.assertEquals - -import org.jdom2.input.SAXBuilder -import org.junit.Test -import org.kopi.galite.tests.ui.vaadin.VApplicationTestBase -import org.kopi.galite.visual.domain.DECIMAL -import org.kopi.galite.visual.domain.INT -import org.kopi.galite.visual.domain.STRING -import org.kopi.galite.visual.dsl.pivotTable.PivotTable - -class PivotTableTests: VApplicationTestBase() { - - val SimplePivotTable = SimplePivotTable() - - /** - * Tests that fields has been registered in the pivot table. - */ - @Test - fun pivotTableFieldsTest() { - assertEquals(SimplePivotTable.fields[0], SimplePivotTable.name) - assertEquals(SimplePivotTable.fields[1], SimplePivotTable.age) - } - - /** - * Tests that fields has been registered in the pivot table. - */ - @Test - fun PivotTableDataTest() { - val rows = SimplePivotTable.getRowsForField(SimplePivotTable.name) - assertEquals(listOf("Sami", "Sofia", "Sofia"), rows) - - val firstRow = SimplePivotTable.getRow(0) - assertMapsEquals(mapOf(SimplePivotTable.name to "Sami", - SimplePivotTable.age to 22, - SimplePivotTable.profession to "Journalist", - SimplePivotTable.salary to BigDecimal("2000") - ), - firstRow) - - val secondRow = SimplePivotTable.getRow(1) - assertMapsEquals(mapOf(SimplePivotTable.name to "Sofia", - SimplePivotTable.age to 23, - SimplePivotTable.profession to "Dentist", - SimplePivotTable.salary to BigDecimal("2000.55")), - secondRow) - - val thirdRow = SimplePivotTable.getRow(2) - assertMapsEquals(mapOf(SimplePivotTable.name to "Sofia", - SimplePivotTable.age to 25, - SimplePivotTable.profession to "Baker", - SimplePivotTable.salary to BigDecimal("2000.55")), - thirdRow) - } - - /** - * Tests that fields localization is generated to the xml file - */ - @Test - fun fieldLocalizationTest() { - val builder = SAXBuilder() - val tempDir = createTempDir("galite", "") - tempDir.deleteOnExit() - - val sourceFilePath = SimplePivotTable.javaClass.classLoader.getResource("").path + - this.javaClass.`package`.name.replace(".", "/") + File.separatorChar - SimplePivotTable.genLocalization() - - val generatedFile = File("${sourceFilePath}/SimplePivotTable-${SimplePivotTable.locale}.xml") - assertEquals(true, generatedFile.exists()) - val document = builder.build(generatedFile) - - // Check that generated xml file contains fields localization - val rootElement = document.rootElement - val nameField = rootElement.children[0] - val ageField = rootElement.children[1] - assertEquals("pivotTable", rootElement.name) - assertEquals("SimplePivotTable", rootElement.getAttributeValue("title")) - assertEquals("ANM_0", nameField.getAttributeValue("ident")) - assertEquals("name", nameField.getAttributeValue("label")) - assertEquals("ANM_1", ageField.getAttributeValue("ident")) - assertEquals("age", ageField.getAttributeValue("label")) - } -} - -/** - * Simple Pivot table with two fields. - */ -class SimplePivotTable : PivotTable(title = "SimplePivotTable", locale = Locale.UK) { - - val name = field(STRING(20)) { - label = "name" - } - - val age = field(INT(3)) { - label = "age" - } - - val profession = field(STRING(20)) { - label = "profession" - } - - val salary = field(DECIMAL(width = 10, scale = 5)) { - label = "salary" - } - - init { - add { - this[name] = "Sami" - this[age] = 22 - this[profession] = "Journalist" - this[salary] = BigDecimal("2000") - } - add { - this[name] = "Sofia" - this[age] = 23 - this[profession] = "Dentist" - this[salary] = BigDecimal("2000.55") - } - add { - this[age] = 25 - this[profession] = "Baker" - this[name] = "Sofia" - this[salary] = BigDecimal("2000.55") - } - } -} From 1ec9e84ba64541aa764c67c5f8c0006a9301e0a6 Mon Sep 17 00:00:00 2001 From: Super User Date: Fri, 10 Nov 2023 15:06:45 +0100 Subject: [PATCH 16/20] Traitement des retours --- build.gradle.kts | 4 +- galite-core/build.gradle.kts | 3 + .../org/kopi/galite/visual/domain/Domain.kt | 62 ++++----------- .../galite/visual/dsl/form/DictionaryForm.kt | 4 + .../galite/visual/dsl/pivotTable/Dimension.kt | 15 +++- .../galite/visual/dsl/pivotTable/Measure.kt | 6 +- .../visual/dsl/pivotTable/PivotTable.kt | 78 +++++++------------ .../visual/dsl/pivotTable/PivotTableField.kt | 4 +- .../PivotTableLocalizationWriter.kt | 4 +- .../visual/dsl/pivotTable/PivotTableRow.kt | 3 +- .../galite/visual/dsl/pivotTable/Position.kt | 25 ------ .../galite/visual/form/VDictionaryForm.kt | 6 +- .../galite/visual/pivotTable/Constants.kt | 41 ++-------- .../galite/visual/pivotTable/MPivotTable.kt | 8 +- .../galite/visual/pivotTable/UPivotTable.kt | 4 +- .../visual/pivotTable/VHelpGenerator.kt | 10 +-- .../visual/pivotTable/VNoRowException.kt | 4 +- .../galite/visual/pivotTable/VPivotTable.kt | 19 ++--- .../visual/pivotTable/VPivotTableColumn.kt | 8 +- .../visual/pivotTable/VPivotTableRow.kt | 4 +- .../ui/vaadin/pivotTable/DPivotTable.kt | 40 +++++----- .../visual/ui/vaadin/visual/VUIFactory.kt | 9 ++- .../kopi/galite/visual/VKMessages-fr_FR.xml | 2 +- .../galite/visual/dsl/form/Form-fr_FR.xml | 2 +- galite-demo/galite-vaadin/build.gradle.kts | 3 + .../demo/billproduct/BillProductForm.kt | 1 - .../org/kopi/galite/demo/client/ClientP.kt | 27 ++++--- .../kopi/galite/demo/command/CommandForm.kt | 3 +- .../kopi/galite/demo/product/ProductForm.kt | 1 - .../kopi/galite/demo/provider/ProviderForm.kt | 1 - .../org/kopi/galite/demo/stock/StockForm.kt | 1 - .../kopi/galite/demo/taxRule/TaxRuleForm.kt | 1 - galite-tests/build.gradle.kts | 3 + .../tests/examples/DocumentationReport.kt | 5 +- 34 files changed, 160 insertions(+), 251 deletions(-) delete mode 100644 galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/Position.kt diff --git a/build.gradle.kts b/build.gradle.kts index 6bebd56a4..43f48a032 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -48,8 +48,6 @@ subprojects { dependencies { "implementation"(kotlin("stdlib")) "implementation"(kotlin("reflect")) - // Pivot Table dependency - "implementation"("org.vaadin.addons.componentfactory", "pivottable-flow", Versions.PIVOT_TABLE) } tasks.withType { @@ -68,7 +66,7 @@ allprojects { apply(plugin = "maven-publish") apply(plugin = "signing") _java { - //withJavadocJar() + withJavadocJar() withSourcesJar() } diff --git a/galite-core/build.gradle.kts b/galite-core/build.gradle.kts index ff9179c39..4f2ce38f4 100644 --- a/galite-core/build.gradle.kts +++ b/galite-core/build.gradle.kts @@ -82,6 +82,9 @@ dependencies { // Javax Activation dependency implementation("javax.activation", "activation", Versions.JAVAX_ACTIVATION) + + // Pivot Table dependency + implementation("org.vaadin.addons.componentfactory", "pivottable-flow", Versions.PIVOT_TABLE) } dependencyManagement { diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/domain/Domain.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/domain/Domain.kt index b802c90d2..498bf6388 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/domain/Domain.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/domain/Domain.kt @@ -27,55 +27,21 @@ import java.time.LocalTime import kotlin.reflect.KClass import org.joda.time.DateTime -import org.kopi.galite.visual.chart.VBooleanDimension -import org.kopi.galite.visual.chart.VColumnFormat -import org.kopi.galite.visual.chart.VDateDimension -import org.kopi.galite.visual.chart.VDimension -import org.kopi.galite.visual.chart.VDecimalDimension -import org.kopi.galite.visual.chart.VDecimalMeasure -import org.kopi.galite.visual.chart.VIntegerDimension -import org.kopi.galite.visual.chart.VIntegerMeasure -import org.kopi.galite.visual.chart.VMeasure -import org.kopi.galite.visual.chart.VMonthDimension -import org.kopi.galite.visual.chart.VStringDimension -import org.kopi.galite.visual.chart.VTimeDimension -import org.kopi.galite.visual.chart.VTimestampDimension -import org.kopi.galite.visual.chart.VWeekDimension +import org.kopi.galite.type.Image +import org.kopi.galite.type.Month +import org.kopi.galite.type.Week +import org.kopi.galite.visual.VColor +import org.kopi.galite.visual.chart.* import org.kopi.galite.visual.dsl.chart.ChartDimension import org.kopi.galite.visual.dsl.chart.ChartMeasure import org.kopi.galite.visual.dsl.common.LocalizationWriter import org.kopi.galite.visual.dsl.form.FormField import org.kopi.galite.visual.dsl.report.ReportField -import org.kopi.galite.visual.form.VBooleanField -import org.kopi.galite.visual.form.VConstants -import org.kopi.galite.visual.form.VDateField -import org.kopi.galite.visual.form.VField -import org.kopi.galite.visual.form.VDecimalField -import org.kopi.galite.visual.form.VImageField -import org.kopi.galite.visual.form.VIntegerField -import org.kopi.galite.visual.form.VMonthField -import org.kopi.galite.visual.form.VStringField -import org.kopi.galite.visual.form.VTextField -import org.kopi.galite.visual.form.VTimeField -import org.kopi.galite.visual.form.VTimestampField -import org.kopi.galite.visual.form.VWeekField -import org.kopi.galite.visual.report.VBooleanColumn -import org.kopi.galite.visual.report.VCalculateColumn -import org.kopi.galite.visual.report.VCellFormat -import org.kopi.galite.visual.report.VDateColumn -import org.kopi.galite.visual.report.VDecimalColumn -import org.kopi.galite.visual.report.VIntegerColumn -import org.kopi.galite.visual.report.VMonthColumn -import org.kopi.galite.visual.report.VReportColumn -import org.kopi.galite.visual.report.VStringColumn -import org.kopi.galite.visual.report.VTimeColumn -import org.kopi.galite.visual.report.VTimestampColumn -import org.kopi.galite.visual.report.VWeekColumn -import org.kopi.galite.type.Image -import org.kopi.galite.type.Month -import org.kopi.galite.type.Week -import org.kopi.galite.visual.VColor -import org.kopi.galite.visual.dsl.pivotTable.Position +import org.kopi.galite.visual.form.* +import org.kopi.galite.visual.report.* +import org.kopi.galite.visual.dsl.pivotTable.Dimension +import org.kopi.galite.visual.dsl.pivotTable.PivotTableField +import org.kopi.galite.visual.pivotTable.VPivotTableColumn /** * A domain is a data type with predefined list of allowed values. @@ -278,11 +244,13 @@ open class Domain(val width: Int? = null, /** * Builds the pivot table column model */ - open fun buildPivotTableFieldModel(field: org.kopi.galite.visual.dsl.pivotTable.PivotTableField<*>, position: Position?): org.kopi.galite.visual.pivotTable.VPivotTableColumn { + open fun buildPivotTableFieldModel(field: PivotTableField<*>, position: Dimension.Position?): VPivotTableColumn { return with(field) { when (kClass) { - Int::class, Long::class, String::class, BigDecimal::class, Boolean::class, org.joda.time.LocalDate::class, LocalDate::class, java.sql.Date::class, java.util.Date::class, Month::class, Week::class, org.joda.time.LocalTime::class, LocalTime::class, Instant::class, LocalDateTime::class, DateTime::class -> - org.kopi.galite.visual.pivotTable.VPivotTableColumn(ident, position) + Int::class, Long::class, String::class, BigDecimal::class, Boolean::class, org.joda.time.LocalDate::class, + LocalDate::class, java.sql.Date::class, java.util.Date::class, Month::class, Week::class, org.joda.time.LocalTime::class, + LocalTime::class, Instant::class, LocalDateTime::class, DateTime::class -> + VPivotTableColumn(ident, position) else -> throw java.lang.RuntimeException("Type ${kClass!!.qualifiedName} is not supported") } diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/form/DictionaryForm.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/form/DictionaryForm.kt index 316448fd1..375cf08c9 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/form/DictionaryForm.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/form/DictionaryForm.kt @@ -124,6 +124,10 @@ abstract class DictionaryForm(title: String, locale: Locale? = null) : Form(titl VDynamicReport.createDynamicReport(this.block) } + /** + * create a pivot table for this form + */ + protected fun Block.createPivotTable(reportbuilder: () -> PivotTable) { model.createPivotTable(block) { reportbuilder().model diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/Dimension.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/Dimension.kt index e58673146..44c305324 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/Dimension.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/Dimension.kt @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN - * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT + * Copyright (c) 2013-2023 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2023 kopiRight Managed Solutions GmbH, Wien AT * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -19,6 +19,7 @@ package org.kopi.galite.visual.dsl.pivotTable import org.kopi.galite.visual.domain.Domain import org.kopi.galite.visual.dsl.common.LocalizationWriter +import org.kopi.galite.visual.pivotTable.Constants import org.kopi.galite.visual.pivotTable.VPivotTableColumn class Dimension(override val domain: Domain, @@ -50,4 +51,14 @@ class Dimension(override val domain: Domain, override fun genLocalization(writer: LocalizationWriter) { (writer as PivotTableLocalizationWriter).genField(ident, label, help) } + + // ---------------------------------------------------------------------- + // POSITION CLASS + // ---------------------------------------------------------------------- + + enum class Position(val value: Int) { + NONE(Constants.DIMENSION_NO_POSITION), + ROW(Constants.DIMENSION_ROW), + COLUMN(Constants.DIMENSION_COLUMN), + } } diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/Measure.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/Measure.kt index 9e66aac98..8f8e48964 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/Measure.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/Measure.kt @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN - * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT + * Copyright (c) 2013-2023 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2023 kopiRight Managed Solutions GmbH, Wien AT * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -33,7 +33,7 @@ class Measure(override val domain: Domain, lateinit var model: VPivotTableColumn fun buildPivotTableColumn(): VPivotTableColumn { - model = domain.buildPivotTableFieldModel(this, Position.MEASURE).also { column -> + model = domain.buildPivotTableFieldModel(this, Dimension.Position.NONE).also { column -> column.label = label ?: "" } diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTable.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTable.kt index ec5513a0d..c2bc6b1ab 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTable.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTable.kt @@ -1,5 +1,6 @@ /* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN + * Copyright (c) 2013-2023 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2023 kopiRight Managed Solutions GmbH, Wien AT * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -32,40 +33,34 @@ abstract class PivotTable(title: String, val help: String?, locale: Locale? = nu constructor(title: String, locale: Locale? = null) : this(title, null, locale) /** Pivot table's fields. */ - val dimensionListe = mutableListOf>() - val measureListe = mutableListOf>() + val dimensions = mutableListOf>() + val measures = mutableListOf>() /** Pivot table's data rows. */ - val pivotTableRows = mutableListOf() + val rows = mutableListOf() inline fun ?> dimension(domain: Domain, - position: Position, + position: Dimension.Position, noinline init: Dimension.() -> Unit): Dimension { domain.kClass = T::class - - val dimension = Dimension(domain, init, "ANM_${dimensionListe.size}",position, domain.source.ifEmpty { `access$sourceFile` }) - + val dimension = Dimension(domain, init, "ANM_${(dimensions + measures).size}", position, domain.source.ifEmpty { `access$sourceFile` }) dimension.init() - model.model.columns.add(dimension.buildPivotTableColumn()) - dimensionListe.add(dimension) + dimensions.add(dimension) return dimension } inline fun ?> measure(domain: Domain, - noinline init: Measure.() -> Unit): Measure { + noinline init: Measure.() -> Unit): Measure { domain.kClass = T::class + val measure = Measure(domain, init, "ANM_${(dimensions + measures).size}", domain.source.ifEmpty { `access$sourceFile` }) + measure.init() + model.model.columns.add(measure.buildPivotTableColumn()) + measures.add(measure) - val dimension = Measure(domain, init, "ANM_${measureListe.size}", domain.source.ifEmpty { `access$sourceFile` }) - - dimension.init() - - model.model.columns.add(dimension.buildPivotTableColumn()) - measureListe.add(dimension) - - return dimension + return measure } /** @@ -74,18 +69,17 @@ abstract class PivotTable(title: String, val help: String?, locale: Locale? = nu * @param init initializes the row with values. */ fun add(init: PivotTableRow.() -> Unit) { - val row = PivotTableRow((dimensionListe + measureListe).toMutableList()) + val row = PivotTableRow((dimensions + measures).toMutableList()) row.init() val list = row.addLine() - // Last null value is added for the separator column - model.model.addLine((list + listOf(null)).toTypedArray()) + model.model.addLine(list.toTypedArray()) - pivotTableRows.add(row) + rows.add(row) } private fun PivotTableRow.addLine(): List { - return (dimensionListe + measureListe).toMutableList().map { field -> + return (dimensions + measures).toMutableList().map { field -> data[field] } } @@ -101,7 +95,7 @@ abstract class PivotTable(title: String, val help: String?, locale: Locale? = nu val pivotTableAction = Action(null, method) val trigger = FormTrigger(event, pivotTableAction) - triggers.add(trigger) + triggers.add(FormTrigger(event, Action(null, method))) // PIVOT TABLE TRIGGERS triggers.forEach { trigger -> @@ -131,31 +125,19 @@ abstract class PivotTable(title: String, val help: String?, locale: Locale? = nu * * @param rowNumber the index of the desired row. */ - fun getRow(rowNumber: Int): MutableMap, Any?> = pivotTableRows[rowNumber].data + fun getRow(rowNumber: Int): MutableMap, Any?> = rows[rowNumber].data /** * Returns rows of data for a specific [field]. * * @param field the field. */ - fun getRowsForField(field: PivotTableField<*>) = pivotTableRows.map { it.data[field] } - /** - * Adds default Pivot table commands - */ - open val pivotTableCommands = false + fun getRowsForField(field: PivotTableField<*>) = rows.map { it.data[field] } fun setMenu() { model.setMenu() } - // ---------------------------------------------------------------------- - // Command - // ---------------------------------------------------------------------- - - fun addDefaultPivotTableCommands() { - model.addDefaultPivotTableCommands() - } - /////////////////////////////////////////////////////////////////////////// // PIVOT TABLE TRIGGERS EVENTS /////////////////////////////////////////////////////////////////////////// @@ -171,7 +153,7 @@ abstract class PivotTable(title: String, val help: String?, locale: Locale? = nu * Executed at pivot table initialization. */ - val INITPIVOTTABLE = PivotTableTriggerEvent(Constants.TRG_INIT) + val INIT = PivotTableTriggerEvent(Constants.TRG_INIT) // ---------------------------------------------------------------------- // XML LOCALIZATION GENERATION @@ -196,13 +178,13 @@ abstract class PivotTable(title: String, val help: String?, locale: Locale? = nu } fun genLocalization(writer: LocalizationWriter) { - (writer as PivotTableLocalizationWriter).genPivotTable(title, (dimensionListe + measureListe).toMutableList(), menus, actors) + (writer as PivotTableLocalizationWriter).genPivotTable(title, (dimensions + measures).toMutableList(), menus, actors) } - var pivotTableType: String - get() = model.pivottableType + var defaultRenderer: String + get() = model.defaultRenderer set(value) { - model.setType(value) + model.setDefaultRenderer(value) } var aggregator: Pair @@ -229,10 +211,10 @@ abstract class PivotTable(title: String, val help: String?, locale: Locale? = nu override val model: VPivotTable = object : VPivotTable() { override fun init() { - dimensionListe.forEach { + dimensions.forEach { it.initField() } - measureListe.forEach { + measures.forEach { it.initField() } } @@ -245,10 +227,6 @@ abstract class PivotTable(title: String, val help: String?, locale: Locale? = nu model.setPageTitle(title) model.help = help model.source = sourceFile - - if (pivotTableCommands) { - addDefaultPivotTableCommands() - } } @PublishedApi diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTableField.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTableField.kt index 6f89ed685..c9d1fad0b 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTableField.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTableField.kt @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN - * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT + * Copyright (c) 2013-2023 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2023 kopiRight Managed Solutions GmbH, Wien AT * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTableLocalizationWriter.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTableLocalizationWriter.kt index d9ffd9477..f345466c9 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTableLocalizationWriter.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTableLocalizationWriter.kt @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN - * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT + * Copyright (c) 2013-2023 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2023 kopiRight Managed Solutions GmbH, Wien AT * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTableRow.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTableRow.kt index 612a1ca2e..a8f8c5063 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTableRow.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTableRow.kt @@ -1,5 +1,6 @@ /* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN + * Copyright (c) 2013-2023 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2023 kopiRight Managed Solutions GmbH, Wien AT * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/Position.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/Position.kt deleted file mode 100644 index 4b161bdc5..000000000 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/Position.kt +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.kopi.galite.visual.dsl.pivotTable - -import org.kopi.galite.visual.pivotTable.Constants - -enum class Position(val value: Int) { - MEASURE(Constants.POS_MEASURE), - DIMENSION_ROW(Constants.POS_DIMENSION_ROW), - DIMENSION_COL(Constants.POS_DIMENSION_COL), -} diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/form/VDictionaryForm.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/form/VDictionaryForm.kt index c810e4fd6..cdc1dbe3c 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/form/VDictionaryForm.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/form/VDictionaryForm.kt @@ -228,12 +228,12 @@ abstract class VDictionaryForm protected constructor(source: String? = null) : V /** * Implements interface for COMMAND CreatePivotTable */ - fun createPivotTable(b: VBlock, reportBuilder: () -> VPivotTable) { + fun createPivotTable(b: VBlock, pivotTableBuilder: () -> VPivotTable) { b.validate() try { setWaitInfo(Message.getMessage("pivotTable_generation")) - val report = reportBuilder() - report.doNotModal() + val pivotTable = pivotTableBuilder() + pivotTable.doNotModal() unsetWaitInfo() } catch (e: VNoRowException) { unsetWaitInfo() diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/Constants.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/Constants.kt index 64456f246..21f245951 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/Constants.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/Constants.kt @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN - * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT + * Copyright (c) 2013-2023 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2023 kopiRight Managed Solutions GmbH, Wien AT * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -31,44 +31,13 @@ interface Constants : Constants { // --------------------------------------------------------------------- // PIVOT TABLE POSITION // --------------------------------------------------------------------- - const val POS_MEASURE = 0 - const val POS_DIMENSION_ROW = 1 - const val POS_DIMENSION_COL = 2 - - // --------------------------------------------------------------------- - // PIVOT TABLE RENDERER - // --------------------------------------------------------------------- - const val DEFAULT_RENDERER = Renderer.TABLE - const val TABLE_BARCHART = Renderer.TABLE_BARCHART - const val TABLE_HEATMAP = Renderer.TABLE_HEATMAP - const val ROW_HEATMAP = Renderer.ROW_HEATMAP - const val COL_HEATMAP = Renderer.COL_HEATMAP - const val HORIZONTAL_BAR_CHART = Renderer.HORIZONTAL_BAR_CHART - const val HORIZONTAL_STACKED_BAR_CHART = Renderer.HORIZONTAL_STACKED_BAR_CHART - const val BAR_CHART = Renderer.BAR_CHART - const val STACKED_BAR_CHART = Renderer.STACKED_BAR_CHART - const val LINE_CHART = Renderer.LINE_CHART - const val AREA_CHART = Renderer.AREA_CHART - const val SCATTER_CHART = Renderer.SCATTER_CHART - const val TSV_EXPORT = Renderer.TSV_EXPORT + const val DIMENSION_NO_POSITION = 0 + const val DIMENSION_ROW = 1 + const val DIMENSION_COLUMN = 2 // --------------------------------------------------------------------- // PIVOT TABLE Aggregator // --------------------------------------------------------------------- - const val DEFAULT_AGGREGATOR = Aggregator.COUNT - const val DEFAULT_AGGREGATE_COLUMN = "" - const val COUNT_UNIQUE_VALUES = Aggregator.COUNT_UNIQUE_VALUES - const val LIST_UNIQUE_VALUES = Aggregator.LIST_UNIQUE_VALUES - const val SUM = Aggregator.SUM - const val INTEGER_SUM = Aggregator.INTEGER_SUM - const val AVERAGE = Aggregator.AVERAGE - const val MEDIAN = Aggregator.MEDIAN - const val SAMPLE_VARIANCE = Aggregator.SAMPLE_VARIANCE - const val SAMPLE_STANDARD_DEVIATION = Aggregator.SAMPLE_STANDARD_DEVIATION - const val MINIMUM = Aggregator.MINIMUM - const val MAXIMUM = Aggregator.MAXIMUM - const val FIRST = Aggregator.FIRST - const val LAST = Aggregator.LAST const val SUM_OVER_SUM = "Sum Over Sum" const val UPPER_BOUND = "80% Upper Bound" const val LOWER_BOUND = "80% Lower Bound" diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/MPivotTable.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/MPivotTable.kt index aa42320f3..564a2c26b 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/MPivotTable.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/MPivotTable.kt @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN - * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT + * Copyright (c) 2013-2023 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2023 kopiRight Managed Solutions GmbH, Wien AT * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -30,9 +30,9 @@ class MPivotTable : Serializable { // Columns contains all columns defined by the user var columns = mutableListOf() // array of column definitions - // Baserows contains data give by the request of the user - internal var userRows: ArrayList? = ArrayList(500) + internal var userRows: ArrayList? = ArrayList() + /** * Add a row to the list of rows defined by the user */ diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/UPivotTable.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/UPivotTable.kt index 811452fd7..2179e7f7e 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/UPivotTable.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/UPivotTable.kt @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN - * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT + * Copyright (c) 2013-2023 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2023 kopiRight Managed Solutions GmbH, Wien AT * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VHelpGenerator.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VHelpGenerator.kt index e5241edc9..199adbd2c 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VHelpGenerator.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VHelpGenerator.kt @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN - * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT + * Copyright (c) 2013-2023 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2023 kopiRight Managed Solutions GmbH, Wien AT * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -40,9 +40,9 @@ class VHelpGenerator : VHelpGenerator() { * prints a compilation unit */ fun helpOnPivotTable(name: String, - commands: List, - model: MPivotTable, - help: String?): String? { + commands: List, + model: MPivotTable, + help: String?): String? { return try { val file: File = Utils.getTempFile(name.replace("[:\\\\/*\"?|<>']".toRegex(), " "), "htm") printer = PrintWriter(BufferedWriter(OutputStreamWriter(FileOutputStream(file), "UTF-8"))) diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VNoRowException.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VNoRowException.kt index e713a0d4f..3af64bb46 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VNoRowException.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VNoRowException.kt @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN - * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT + * Copyright (c) 2013-2023 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2023 kopiRight Managed Solutions GmbH, Wien AT * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VPivotTable.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VPivotTable.kt index 58b961e8f..0081b0299 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VPivotTable.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VPivotTable.kt @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN - * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT + * Copyright (c) 2013-2023 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2023 kopiRight Managed Solutions GmbH, Wien AT * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -18,13 +18,15 @@ package org.kopi.galite.visual.pivotTable +import java.io.File +import java.net.MalformedURLException + import org.kopi.galite.util.base.InconsistencyException import org.kopi.galite.visual.* import org.kopi.galite.visual.form.VConstants import org.kopi.galite.visual.l10n.LocalizationManager import org.kopi.galite.visual.dsl.common.Trigger -import java.io.File -import java.net.MalformedURLException +import org.vaadin.addons.componentfactory.PivotTable.* /** * Represents a pivot table model. @@ -51,8 +53,8 @@ abstract class VPivotTable internal constructor() : VWindow(), VConstants { val model: MPivotTable = MPivotTable() private var built = false private var pageTitle = "" - var pivottableType = Constants.DEFAULT_RENDERER // Default pivot table type - var aggregator = Pair(Constants.DEFAULT_AGGREGATOR, Constants.DEFAULT_AGGREGATE_COLUMN) // default Aggregator + var defaultRenderer = Renderer.TABLE // Default pivot table type + var aggregator = Pair(Aggregator.COUNT, "") // default Aggregator var disabledRerenders = mutableListOf() var interactive = Constants.MODE_INTERACTIVE val PIVOT_TABLE_Triggers = listOf(arrayOfNulls(Constants.TRG_TYPES.size)) @@ -64,7 +66,6 @@ abstract class VPivotTable internal constructor() : VWindow(), VConstants { /** * Close window */ - @Deprecated("call method in display; model must not be closed") fun close() { getDisplay()!!.closeWindow() } @@ -77,8 +78,8 @@ abstract class VPivotTable internal constructor() : VWindow(), VConstants { * Sets the new type of this pivot table model. * @param type The new pivot table type. */ - internal fun setType(type: String) { - pivottableType = type + internal fun setDefaultRenderer(renderer: String) { + defaultRenderer = renderer } /** diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VPivotTableColumn.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VPivotTableColumn.kt index 4932d2e61..404f605af 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VPivotTableColumn.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VPivotTableColumn.kt @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN - * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT + * Copyright (c) 2013-2023 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2023 kopiRight Managed Solutions GmbH, Wien AT * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -18,7 +18,7 @@ package org.kopi.galite.visual.pivotTable -import org.kopi.galite.visual.dsl.pivotTable.Position +import org.kopi.galite.visual.dsl.pivotTable.Dimension import org.kopi.galite.visual.l10n.FieldLocalizer import org.kopi.galite.visual.l10n.PivotTableLocalizer @@ -28,7 +28,7 @@ import org.kopi.galite.visual.l10n.PivotTableLocalizer * @param ident The identifier of the field * */ -class VPivotTableColumn(val ident: String?, val position: Position?) { +class VPivotTableColumn(val ident: String?, val position: Dimension.Position?) { // ---------------------------------------------------------------------- // DATA MEMBERS diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VPivotTableRow.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VPivotTableRow.kt index 12b739d30..c18dacb58 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VPivotTableRow.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VPivotTableRow.kt @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN - * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT + * Copyright (c) 2013-2023 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2023 kopiRight Managed Solutions GmbH, Wien AT * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/DPivotTable.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/DPivotTable.kt index 2b945772c..9a29e0eec 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/DPivotTable.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/DPivotTable.kt @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN - * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT + * Copyright (c) 2013-2023 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2023 kopiRight Managed Solutions GmbH, Wien AT * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -18,7 +18,7 @@ package org.kopi.galite.visual.ui.vaadin.pivotTable import com.vaadin.flow.component.dependency.CssImport -import org.kopi.galite.visual.dsl.pivotTable.Position +import org.kopi.galite.visual.dsl.pivotTable.Dimension.Position import org.kopi.galite.visual.pivotTable.MPivotTable import org.kopi.galite.visual.pivotTable.UPivotTable import org.kopi.galite.visual.pivotTable.VPivotTable @@ -35,8 +35,8 @@ class DPivotTable(private val pivotTable: VPivotTable) : DWindow(pivotTable), UP private val model: MPivotTable = pivotTable.model // pivot table model private val pivotData = PivotTable.PivotData() private val pivotOptions = PivotTable.PivotOptions() - private val listeDimensionRows = mutableListOf() - private val listeDimensionColumns = mutableListOf() + private val rows = mutableListOf() + private val columns = mutableListOf() init { getModel()!!.setDisplay(this) @@ -51,41 +51,39 @@ class DPivotTable(private val pivotTable: VPivotTable) : DWindow(pivotTable), UP } override fun build() { - model.columns - .forEach { - pivotData.addColumn(it?.label, it?.javaClass) - if (it?.position == Position.DIMENSION_ROW) { - listeDimensionRows.add(it.label) - } - if (it?.position == Position.DIMENSION_COL) { - listeDimensionColumns.add(it.label) - } + model.columns.forEach { + pivotData.addColumn(it?.label, it?.javaClass) + if (it?.position == Position.ROW) { + rows.add(it.label) } + if (it?.position == Position.COLUMN) { + columns.add(it.label) + } + } model.userRows ?.flatMap { it.data.filterNotNull() } ?.chunked(model.columns.count()) { rows -> - pivotData.addRow(*rows.toTypedArray()) - } + pivotData.addRow(*rows.toTypedArray())} // Pivot table dimension - pivotOptions.setRows(*listeDimensionRows.toTypedArray()) - pivotOptions.setCols(*listeDimensionColumns.toTypedArray()) + pivotOptions.setRows(*rows.toTypedArray()) + pivotOptions.setCols(*columns.toTypedArray()) // Pivot table default renderer - pivotOptions.setRenderer(pivotTable.pivottableType) + pivotOptions.setRenderer(pivotTable.defaultRenderer) // Pivot table aggregate function pivotOptions.setAggregator(pivotTable.aggregator.first, pivotTable.aggregator.second) // Pivot table renderer - if(listeDimensionRows.isNotEmpty() && listeDimensionColumns.isNotEmpty()) { + if(rows.isNotEmpty() && columns.isNotEmpty()) { pivotOptions.setCharts(true) } pivotOptions.setDisabledRenderers(*pivotTable.disabledRerenders.toTypedArray()) // Pivot table mode - val pivotMode = if(pivotTable.interactive == 0) { + val pivotMode = if (pivotTable.interactive == 0) { PivotTable.PivotMode.INTERACTIVE } else { PivotTable.PivotMode.NONINTERACTIVE diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/visual/VUIFactory.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/visual/VUIFactory.kt index 9357c8eba..ecb86fdc4 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/visual/VUIFactory.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/visual/VUIFactory.kt @@ -21,11 +21,13 @@ import org.kopi.galite.visual.base.UComponent import org.kopi.galite.visual.chart.VChart import org.kopi.galite.visual.form.VForm import org.kopi.galite.visual.form.VListDialog +import org.kopi.galite.visual.pivotTable.VPivotTable import org.kopi.galite.visual.preview.VPreviewWindow import org.kopi.galite.visual.report.VReport import org.kopi.galite.visual.ui.vaadin.chart.DChart import org.kopi.galite.visual.ui.vaadin.form.DForm import org.kopi.galite.visual.ui.vaadin.form.DListDialog +import org.kopi.galite.visual.ui.vaadin.pivotTable.DPivotTable import org.kopi.galite.visual.ui.vaadin.preview.DPreviewWindow import org.kopi.galite.visual.ui.vaadin.report.DReport import org.kopi.galite.visual.UIFactory @@ -33,7 +35,6 @@ import org.kopi.galite.visual.VHelpViewer import org.kopi.galite.visual.VItemTree import org.kopi.galite.visual.VMenuTree import org.kopi.galite.visual.VModel -import org.kopi.galite.visual.pivotTable.VPivotTable /** * The `VUIFactory` is a vaadin implementation of the [UIFactory]. @@ -153,13 +154,13 @@ class VUIFactory : UIFactory() { internal fun createListDialog(model: VListDialog): DListDialog { return DListDialog(model) } + /** * Creates the [DPivotTable] from a given model. * @param model The pivot table model * @return The [DPivotTable] view. */ - - internal fun createPivotTable(model: VPivotTable): org.kopi.galite.visual.ui.vaadin.pivotTable.DPivotTable { - return org.kopi.galite.visual.ui.vaadin.pivotTable.DPivotTable(model) + internal fun createPivotTable(model: VPivotTable): DPivotTable { + return DPivotTable(model) } } diff --git a/galite-core/src/main/resources/org/kopi/galite/visual/VKMessages-fr_FR.xml b/galite-core/src/main/resources/org/kopi/galite/visual/VKMessages-fr_FR.xml index 9a60c9a1e..985474f70 100644 --- a/galite-core/src/main/resources/org/kopi/galite/visual/VKMessages-fr_FR.xml +++ b/galite-core/src/main/resources/org/kopi/galite/visual/VKMessages-fr_FR.xml @@ -23,7 +23,7 @@ - + diff --git a/galite-core/src/main/resources/org/kopi/galite/visual/dsl/form/Form-fr_FR.xml b/galite-core/src/main/resources/org/kopi/galite/visual/dsl/form/Form-fr_FR.xml index c2b990f2f..d70ab13ad 100644 --- a/galite-core/src/main/resources/org/kopi/galite/visual/dsl/form/Form-fr_FR.xml +++ b/galite-core/src/main/resources/org/kopi/galite/visual/dsl/form/Form-fr_FR.xml @@ -29,7 +29,7 @@ - + diff --git a/galite-demo/galite-vaadin/build.gradle.kts b/galite-demo/galite-vaadin/build.gradle.kts index ef2bfc027..773eca40c 100644 --- a/galite-demo/galite-vaadin/build.gradle.kts +++ b/galite-demo/galite-vaadin/build.gradle.kts @@ -57,6 +57,9 @@ dependencies { // EnhancedDialog dependency testImplementation("com.vaadin.componentfactory", "enhanced-dialog", Versions.ENHANCED_DIALOG) + + // Pivot Table dependency + implementation("org.vaadin.addons.componentfactory", "pivottable-flow", Versions.PIVOT_TABLE) } tasks { diff --git a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/billproduct/BillProductForm.kt b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/billproduct/BillProductForm.kt index 220031430..cea7600cc 100644 --- a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/billproduct/BillProductForm.kt +++ b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/billproduct/BillProductForm.kt @@ -16,7 +16,6 @@ */ package org.kopi.galite.demo.billproduct -import org.kopi.galite.demo.command.CommandR import java.util.Locale import org.kopi.galite.demo.database.Bill diff --git a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/client/ClientP.kt b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/client/ClientP.kt index 7d477a454..16559b7e5 100644 --- a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/client/ClientP.kt +++ b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/client/ClientP.kt @@ -16,6 +16,8 @@ */ package org.kopi.galite.demo.client +import org.jetbrains.exposed.sql.JoinType +import org.jetbrains.exposed.sql.alias import java.util.Locale import org.jetbrains.exposed.sql.selectAll @@ -26,9 +28,10 @@ import org.kopi.galite.visual.domain.INT import org.kopi.galite.visual.domain.STRING import org.kopi.galite.visual.dsl.common.Icon import org.kopi.galite.visual.dsl.form.Key +import org.kopi.galite.visual.dsl.pivotTable.Dimension.Position import org.kopi.galite.visual.dsl.pivotTable.PivotTable -import org.kopi.galite.visual.dsl.pivotTable.Position -import org.kopi.galite.visual.pivotTable.Constants +import org.vaadin.addons.componentfactory.PivotTable.Aggregator +import org.vaadin.addons.componentfactory.PivotTable.Renderer /** * Client Report @@ -55,32 +58,32 @@ class ClientP : PivotTable(title = "Clients_Pivot_Table", locale = Locale.UK) { } - val firstName = dimension(STRING(25), Position.DIMENSION_ROW) { + val firstName = dimension(STRING(25), Position.ROW) { label = "First Name" help = "The client first name" } - val lastName = dimension(STRING(25), Position.DIMENSION_ROW) { + val lastName = dimension(STRING(25), Position.ROW) { label = "Last Name" help = "The client last name" } - val addressClt = dimension(STRING(50), Position.DIMENSION_ROW) { + val addressClt = dimension(STRING(50), Position.ROW) { label = "Address" help = "The client address" } - val ageClt = dimension(INT(2), Position.DIMENSION_COL) { + val ageClt = dimension(INT(2), Position.COLUMN) { label = "Age" help = "The client age" } - val countryClt = dimension(STRING(50), Position.DIMENSION_ROW) { + val countryClt = dimension(STRING(50), Position.ROW) { label = "Country" help = "The client country" } - val cityClt = dimension(STRING(50), Position.MEASURE) { + val cityClt = dimension(STRING(50), Position.NONE) { label = "City" help = "The client city" } @@ -95,10 +98,10 @@ class ClientP : PivotTable(title = "Clients_Pivot_Table", locale = Locale.UK) { help = "Is the client active?" } - val init = trigger(INITPIVOTTABLE) { - pivotTableType = Constants.DEFAULT_RENDERER - aggregator = Pair(Constants.SAMPLE_VARIANCE, Constants.DEFAULT_AGGREGATE_COLUMN) - disabledRerenders = mutableListOf(Constants.SCATTER_CHART, Constants.LINE_CHART, Constants.HORIZONTAL_BAR_CHART, Constants.HORIZONTAL_STACKED_BAR_CHART) + val init = trigger(INIT) { + defaultRenderer = Renderer.TABLE + aggregator = Pair(Aggregator.SAMPLE_VARIANCE, "") + disabledRerenders = mutableListOf(Renderer.SCATTER_CHART, Renderer.LINE_CHART, Renderer.HORIZONTAL_BAR_CHART, Renderer.HORIZONTAL_STACKED_BAR_CHART) //interactive = Constants.MODE_NONINTERACTIVE } diff --git a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/command/CommandForm.kt b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/command/CommandForm.kt index 0e97e948d..7e6a921d7 100644 --- a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/command/CommandForm.kt +++ b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/command/CommandForm.kt @@ -50,7 +50,6 @@ class CommandForm : DictionaryForm(title = "Commands", locale = Locale.UK) { } } - command(item = list) { recursiveQuery() } @@ -125,4 +124,4 @@ class CommandForm : DictionaryForm(title = "Commands", locale = Locale.UK) { fun main() { runForm(form = CommandForm::class) -} +} \ No newline at end of file diff --git a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/product/ProductForm.kt b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/product/ProductForm.kt index fbedc6617..be5ec81e0 100644 --- a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/product/ProductForm.kt +++ b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/product/ProductForm.kt @@ -16,7 +16,6 @@ */ package org.kopi.galite.demo.product -import org.kopi.galite.demo.command.CommandR import java.util.Locale import org.kopi.galite.demo.database.Product diff --git a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/provider/ProviderForm.kt b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/provider/ProviderForm.kt index 626b585d3..15a45af12 100644 --- a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/provider/ProviderForm.kt +++ b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/provider/ProviderForm.kt @@ -16,7 +16,6 @@ */ package org.kopi.galite.demo.provider -import org.kopi.galite.demo.command.CommandR import java.util.Locale import org.kopi.galite.demo.database.Provider diff --git a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/stock/StockForm.kt b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/stock/StockForm.kt index b0970527a..712d57937 100644 --- a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/stock/StockForm.kt +++ b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/stock/StockForm.kt @@ -16,7 +16,6 @@ */ package org.kopi.galite.demo.stock -import org.kopi.galite.demo.command.CommandR import java.util.Locale import org.kopi.galite.demo.database.Product diff --git a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/taxRule/TaxRuleForm.kt b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/taxRule/TaxRuleForm.kt index 831e9263c..633200c18 100644 --- a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/taxRule/TaxRuleForm.kt +++ b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/taxRule/TaxRuleForm.kt @@ -16,7 +16,6 @@ */ package org.kopi.galite.demo.taxRule -import org.kopi.galite.demo.command.CommandR import java.util.Locale import org.kopi.galite.demo.database.TaxRule diff --git a/galite-tests/build.gradle.kts b/galite-tests/build.gradle.kts index f2e0c610c..537cfb20e 100644 --- a/galite-tests/build.gradle.kts +++ b/galite-tests/build.gradle.kts @@ -65,6 +65,9 @@ dependencies { // Vaadin addons dependency testImplementation("com.vaadin.componentfactory", "enhanced-dialog", Versions.ENHANCED_DIALOG) testImplementation("org.vaadin.stefan", "fullcalendar2", Versions.FULL_CALENDAR) + + // Pivot Table dependency + implementation("org.vaadin.addons.componentfactory", "pivottable-flow", Versions.PIVOT_TABLE) } tasks { diff --git a/galite-tests/src/test/kotlin/org/kopi/galite/tests/examples/DocumentationReport.kt b/galite-tests/src/test/kotlin/org/kopi/galite/tests/examples/DocumentationReport.kt index f615bd7af..997326bb6 100644 --- a/galite-tests/src/test/kotlin/org/kopi/galite/tests/examples/DocumentationReport.kt +++ b/galite-tests/src/test/kotlin/org/kopi/galite/tests/examples/DocumentationReport.kt @@ -21,9 +21,9 @@ import java.util.Locale import org.kopi.galite.tests.desktop.runForm import org.kopi.galite.visual.domain.INT import org.kopi.galite.visual.dsl.form.Block -import org.kopi.galite.visual.dsl.form.DictionaryForm +import org.kopi.galite.visual.dsl.form.ReportSelectionForm -class DocumentationReport : DictionaryForm(title = "Test Report Form", locale = Locale.UK) { +class DocumentationReport : ReportSelectionForm(title = "Test Report Form", locale = Locale.UK) { //Menus Definition @@ -42,7 +42,6 @@ class DocumentationReport : DictionaryForm(title = "Test Report Form", locale = DocumentationReportR() } } - } } } From 06f4f0a7df662ba6c3f3d33a5fbaab364d4570fd Mon Sep 17 00:00:00 2001 From: Super User Date: Mon, 13 Nov 2023 11:06:23 +0100 Subject: [PATCH 17/20] Rename packages : pivotTable to pivottable --- .../kotlin/org/kopi/galite/visual/domain/Domain.kt | 6 +++--- .../org/kopi/galite/visual/dsl/form/DictionaryForm.kt | 2 +- .../visual/dsl/{pivotTable => pivottable}/Dimension.kt | 6 +++--- .../visual/dsl/{pivotTable => pivottable}/Measure.kt | 4 ++-- .../dsl/{pivotTable => pivottable}/PivotTable.kt | 6 +++--- .../dsl/{pivotTable => pivottable}/PivotTableField.kt | 2 +- .../PivotTableLocalizationWriter.kt | 5 ++++- .../dsl/{pivotTable => pivottable}/PivotTableRow.kt | 2 +- .../org/kopi/galite/visual/form/VDictionaryForm.kt | 3 +-- .../visual/{pivotTable => pivottable}/Constants.kt | 2 +- .../visual/{pivotTable => pivottable}/MPivotTable.kt | 2 +- .../visual/{pivotTable => pivottable}/UPivotTable.kt | 2 +- .../{pivotTable => pivottable}/VHelpGenerator.kt | 2 +- .../{pivotTable => pivottable}/VNoRowException.kt | 2 +- .../visual/{pivotTable => pivottable}/VPivotTable.kt | 2 +- .../{pivotTable => pivottable}/VPivotTableColumn.kt | 4 ++-- .../{pivotTable => pivottable}/VPivotTableRow.kt | 2 +- .../vaadin/{pivotTable => pivottable}/DPivotTable.kt | 10 +++++----- .../kopi/galite/visual/ui/vaadin/visual/VUIFactory.kt | 4 ++-- .../org/kopi/galite/demo/billproduct/BillProductP.kt | 2 +- .../main/kotlin/org/kopi/galite/demo/client/ClientP.kt | 4 ++-- .../kotlin/org/kopi/galite/demo/taxRule/TaxRuleP.kt | 2 +- 22 files changed, 39 insertions(+), 37 deletions(-) rename galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/{pivotTable => pivottable}/Dimension.kt (93%) rename galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/{pivotTable => pivottable}/Measure.kt (94%) rename galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/{pivotTable => pivottable}/PivotTable.kt (97%) rename galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/{pivotTable => pivottable}/PivotTableField.kt (96%) rename galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/{pivotTable => pivottable}/PivotTableLocalizationWriter.kt (94%) rename galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/{pivotTable => pivottable}/PivotTableRow.kt (98%) rename galite-core/src/main/kotlin/org/kopi/galite/visual/{pivotTable => pivottable}/Constants.kt (98%) rename galite-core/src/main/kotlin/org/kopi/galite/visual/{pivotTable => pivottable}/MPivotTable.kt (98%) rename galite-core/src/main/kotlin/org/kopi/galite/visual/{pivotTable => pivottable}/UPivotTable.kt (95%) rename galite-core/src/main/kotlin/org/kopi/galite/visual/{pivotTable => pivottable}/VHelpGenerator.kt (99%) rename galite-core/src/main/kotlin/org/kopi/galite/visual/{pivotTable => pivottable}/VNoRowException.kt (96%) rename galite-core/src/main/kotlin/org/kopi/galite/visual/{pivotTable => pivottable}/VPivotTable.kt (99%) rename galite-core/src/main/kotlin/org/kopi/galite/visual/{pivotTable => pivottable}/VPivotTableColumn.kt (95%) rename galite-core/src/main/kotlin/org/kopi/galite/visual/{pivotTable => pivottable}/VPivotTableRow.kt (96%) rename galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/{pivotTable => pivottable}/DPivotTable.kt (91%) diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/domain/Domain.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/domain/Domain.kt index 498bf6388..c12200c2e 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/domain/Domain.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/domain/Domain.kt @@ -39,9 +39,9 @@ import org.kopi.galite.visual.dsl.form.FormField import org.kopi.galite.visual.dsl.report.ReportField import org.kopi.galite.visual.form.* import org.kopi.galite.visual.report.* -import org.kopi.galite.visual.dsl.pivotTable.Dimension -import org.kopi.galite.visual.dsl.pivotTable.PivotTableField -import org.kopi.galite.visual.pivotTable.VPivotTableColumn +import org.kopi.galite.visual.dsl.pivottable.Dimension +import org.kopi.galite.visual.dsl.pivottable.PivotTableField +import org.kopi.galite.visual.pivottable.VPivotTableColumn /** * A domain is a data type with predefined list of allowed values. diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/form/DictionaryForm.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/form/DictionaryForm.kt index 375cf08c9..c28a89363 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/form/DictionaryForm.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/form/DictionaryForm.kt @@ -21,7 +21,7 @@ import java.util.Locale import org.kopi.galite.visual.ApplicationContext import org.kopi.galite.visual.VException import org.kopi.galite.visual.cross.VDynamicReport -import org.kopi.galite.visual.dsl.pivotTable.PivotTable +import org.kopi.galite.visual.dsl.pivottable.PivotTable import org.kopi.galite.visual.dsl.report.Report import org.kopi.galite.visual.form.VDictionaryForm diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/Dimension.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivottable/Dimension.kt similarity index 93% rename from galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/Dimension.kt rename to galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivottable/Dimension.kt index 44c305324..4fbcfb876 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/Dimension.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivottable/Dimension.kt @@ -15,12 +15,12 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -package org.kopi.galite.visual.dsl.pivotTable +package org.kopi.galite.visual.dsl.pivottable import org.kopi.galite.visual.domain.Domain import org.kopi.galite.visual.dsl.common.LocalizationWriter -import org.kopi.galite.visual.pivotTable.Constants -import org.kopi.galite.visual.pivotTable.VPivotTableColumn +import org.kopi.galite.visual.pivottable.Constants +import org.kopi.galite.visual.pivottable.VPivotTableColumn class Dimension(override val domain: Domain, val init: Dimension.() -> Unit, diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/Measure.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivottable/Measure.kt similarity index 94% rename from galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/Measure.kt rename to galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivottable/Measure.kt index 8f8e48964..049d34e25 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/Measure.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivottable/Measure.kt @@ -15,11 +15,11 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -package org.kopi.galite.visual.dsl.pivotTable +package org.kopi.galite.visual.dsl.pivottable import org.kopi.galite.visual.domain.Domain import org.kopi.galite.visual.dsl.common.LocalizationWriter -import org.kopi.galite.visual.pivotTable.VPivotTableColumn +import org.kopi.galite.visual.pivottable.VPivotTableColumn class Measure(override val domain: Domain, val init: Measure.() -> Unit, diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTable.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivottable/PivotTable.kt similarity index 97% rename from galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTable.kt rename to galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivottable/PivotTable.kt index c2bc6b1ab..06f9f79c8 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTable.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivottable/PivotTable.kt @@ -16,7 +16,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -package org.kopi.galite.visual.dsl.pivotTable +package org.kopi.galite.visual.dsl.pivottable import java.io.IOException import java.util.Locale @@ -25,8 +25,8 @@ import org.kopi.galite.visual.ApplicationContext import org.kopi.galite.visual.domain.Domain import org.kopi.galite.visual.dsl.common.* import org.kopi.galite.visual.form.VConstants -import org.kopi.galite.visual.pivotTable.Constants -import org.kopi.galite.visual.pivotTable.VPivotTable +import org.kopi.galite.visual.pivottable.Constants +import org.kopi.galite.visual.pivottable.VPivotTable abstract class PivotTable(title: String, val help: String?, locale: Locale? = null) : Window(title, locale) { diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTableField.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivottable/PivotTableField.kt similarity index 96% rename from galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTableField.kt rename to galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivottable/PivotTableField.kt index c9d1fad0b..0e9902f74 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTableField.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivottable/PivotTableField.kt @@ -15,7 +15,7 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -package org.kopi.galite.visual.dsl.pivotTable +package org.kopi.galite.visual.dsl.pivottable import org.kopi.galite.visual.domain.Domain import org.kopi.galite.visual.dsl.common.LocalizationWriter diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTableLocalizationWriter.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivottable/PivotTableLocalizationWriter.kt similarity index 94% rename from galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTableLocalizationWriter.kt rename to galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivottable/PivotTableLocalizationWriter.kt index f345466c9..bed81cc27 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTableLocalizationWriter.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivottable/PivotTableLocalizationWriter.kt @@ -15,7 +15,7 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -package org.kopi.galite.visual.dsl.pivotTable +package org.kopi.galite.visual.dsl.pivottable import org.jdom2.Element import org.kopi.galite.visual.dsl.common.Actor @@ -58,6 +58,9 @@ class PivotTableLocalizationWriter : LocalizationWriter() { if (label != null) { self.setAttribute("label", label) } + if (help != null) { + self.setAttribute("help", help) + } peekNode(null).addContent(self) } diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTableRow.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivottable/PivotTableRow.kt similarity index 98% rename from galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTableRow.kt rename to galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivottable/PivotTableRow.kt index a8f8c5063..89e111b37 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivotTable/PivotTableRow.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivottable/PivotTableRow.kt @@ -16,7 +16,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -package org.kopi.galite.visual.dsl.pivotTable +package org.kopi.galite.visual.dsl.pivottable import org.jetbrains.exposed.sql.statements.api.ExposedBlob import org.kopi.galite.type.Month diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/form/VDictionaryForm.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/form/VDictionaryForm.kt index cdc1dbe3c..7b280d911 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/form/VDictionaryForm.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/form/VDictionaryForm.kt @@ -23,10 +23,9 @@ import org.kopi.galite.visual.MessageCode import org.kopi.galite.visual.VExecFailedException import org.kopi.galite.visual.VRuntimeException -import org.kopi.galite.visual.cross.VReportSelectionForm import org.kopi.galite.visual.form.VConstants.Companion.MOD_UPDATE import org.kopi.galite.visual.fullcalendar.VFullCalendarBlock -import org.kopi.galite.visual.pivotTable.VPivotTable +import org.kopi.galite.visual.pivottable.VPivotTable import org.kopi.galite.visual.report.VNoRowException import org.kopi.galite.visual.report.VReport diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/Constants.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivottable/Constants.kt similarity index 98% rename from galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/Constants.kt rename to galite-core/src/main/kotlin/org/kopi/galite/visual/pivottable/Constants.kt index 21f245951..c231dfef6 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/Constants.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivottable/Constants.kt @@ -16,7 +16,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -package org.kopi.galite.visual.pivotTable +package org.kopi.galite.visual.pivottable import org.kopi.galite.visual.form.VConstants import org.kopi.galite.visual.Constants diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/MPivotTable.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivottable/MPivotTable.kt similarity index 98% rename from galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/MPivotTable.kt rename to galite-core/src/main/kotlin/org/kopi/galite/visual/pivottable/MPivotTable.kt index 564a2c26b..1d0e81ad9 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/MPivotTable.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivottable/MPivotTable.kt @@ -16,7 +16,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -package org.kopi.galite.visual.pivotTable +package org.kopi.galite.visual.pivottable import java.io.Serializable diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/UPivotTable.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivottable/UPivotTable.kt similarity index 95% rename from galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/UPivotTable.kt rename to galite-core/src/main/kotlin/org/kopi/galite/visual/pivottable/UPivotTable.kt index 2179e7f7e..cefb9551a 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/UPivotTable.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivottable/UPivotTable.kt @@ -16,7 +16,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -package org.kopi.galite.visual.pivotTable +package org.kopi.galite.visual.pivottable import org.kopi.galite.visual.UWindow diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VHelpGenerator.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivottable/VHelpGenerator.kt similarity index 99% rename from galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VHelpGenerator.kt rename to galite-core/src/main/kotlin/org/kopi/galite/visual/pivottable/VHelpGenerator.kt index 199adbd2c..847bc8340 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VHelpGenerator.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivottable/VHelpGenerator.kt @@ -16,7 +16,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -package org.kopi.galite.visual.pivotTable +package org.kopi.galite.visual.pivottable import java.io.BufferedWriter import java.io.File diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VNoRowException.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivottable/VNoRowException.kt similarity index 96% rename from galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VNoRowException.kt rename to galite-core/src/main/kotlin/org/kopi/galite/visual/pivottable/VNoRowException.kt index 3af64bb46..e4f0f66ed 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VNoRowException.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivottable/VNoRowException.kt @@ -16,7 +16,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -package org.kopi.galite.visual.pivotTable +package org.kopi.galite.visual.pivottable import org.kopi.galite.visual.VRuntimeException diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VPivotTable.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivottable/VPivotTable.kt similarity index 99% rename from galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VPivotTable.kt rename to galite-core/src/main/kotlin/org/kopi/galite/visual/pivottable/VPivotTable.kt index 0081b0299..a1af4f1af 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VPivotTable.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivottable/VPivotTable.kt @@ -16,7 +16,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -package org.kopi.galite.visual.pivotTable +package org.kopi.galite.visual.pivottable import java.io.File import java.net.MalformedURLException diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VPivotTableColumn.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivottable/VPivotTableColumn.kt similarity index 95% rename from galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VPivotTableColumn.kt rename to galite-core/src/main/kotlin/org/kopi/galite/visual/pivottable/VPivotTableColumn.kt index 404f605af..9dd0a165a 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VPivotTableColumn.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivottable/VPivotTableColumn.kt @@ -16,9 +16,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -package org.kopi.galite.visual.pivotTable +package org.kopi.galite.visual.pivottable -import org.kopi.galite.visual.dsl.pivotTable.Dimension +import org.kopi.galite.visual.dsl.pivottable.Dimension import org.kopi.galite.visual.l10n.FieldLocalizer import org.kopi.galite.visual.l10n.PivotTableLocalizer diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VPivotTableRow.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivottable/VPivotTableRow.kt similarity index 96% rename from galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VPivotTableRow.kt rename to galite-core/src/main/kotlin/org/kopi/galite/visual/pivottable/VPivotTableRow.kt index c18dacb58..fb1d02c35 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivotTable/VPivotTableRow.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivottable/VPivotTableRow.kt @@ -16,7 +16,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -package org.kopi.galite.visual.pivotTable +package org.kopi.galite.visual.pivottable import javax.swing.tree.DefaultMutableTreeNode diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/DPivotTable.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivottable/DPivotTable.kt similarity index 91% rename from galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/DPivotTable.kt rename to galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivottable/DPivotTable.kt index 9a29e0eec..53c2d5b15 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivotTable/DPivotTable.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivottable/DPivotTable.kt @@ -15,13 +15,13 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -package org.kopi.galite.visual.ui.vaadin.pivotTable +package org.kopi.galite.visual.ui.vaadin.pivottable import com.vaadin.flow.component.dependency.CssImport -import org.kopi.galite.visual.dsl.pivotTable.Dimension.Position -import org.kopi.galite.visual.pivotTable.MPivotTable -import org.kopi.galite.visual.pivotTable.UPivotTable -import org.kopi.galite.visual.pivotTable.VPivotTable +import org.kopi.galite.visual.dsl.pivottable.Dimension.Position +import org.kopi.galite.visual.pivottable.MPivotTable +import org.kopi.galite.visual.pivottable.UPivotTable +import org.kopi.galite.visual.pivottable.VPivotTable import org.kopi.galite.visual.ui.vaadin.visual.DWindow import org.vaadin.addons.componentfactory.PivotTable diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/visual/VUIFactory.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/visual/VUIFactory.kt index ecb86fdc4..2208b5943 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/visual/VUIFactory.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/visual/VUIFactory.kt @@ -21,13 +21,13 @@ import org.kopi.galite.visual.base.UComponent import org.kopi.galite.visual.chart.VChart import org.kopi.galite.visual.form.VForm import org.kopi.galite.visual.form.VListDialog -import org.kopi.galite.visual.pivotTable.VPivotTable +import org.kopi.galite.visual.pivottable.VPivotTable import org.kopi.galite.visual.preview.VPreviewWindow import org.kopi.galite.visual.report.VReport import org.kopi.galite.visual.ui.vaadin.chart.DChart import org.kopi.galite.visual.ui.vaadin.form.DForm import org.kopi.galite.visual.ui.vaadin.form.DListDialog -import org.kopi.galite.visual.ui.vaadin.pivotTable.DPivotTable +import org.kopi.galite.visual.ui.vaadin.pivottable.DPivotTable import org.kopi.galite.visual.ui.vaadin.preview.DPreviewWindow import org.kopi.galite.visual.ui.vaadin.report.DReport import org.kopi.galite.visual.UIFactory diff --git a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/billproduct/BillProductP.kt b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/billproduct/BillProductP.kt index 5ad5dac4a..2c3f1619c 100644 --- a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/billproduct/BillProductP.kt +++ b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/billproduct/BillProductP.kt @@ -23,7 +23,7 @@ import org.jetbrains.exposed.sql.transactions.transaction import org.kopi.galite.demo.database.BillProduct import org.kopi.galite.visual.domain.DECIMAL import org.kopi.galite.visual.domain.INT -import org.kopi.galite.visual.dsl.pivotTable.PivotTable +import org.kopi.galite.visual.dsl.pivottable.PivotTable /** * Products Bill Report diff --git a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/client/ClientP.kt b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/client/ClientP.kt index 16559b7e5..9eb0816f2 100644 --- a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/client/ClientP.kt +++ b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/client/ClientP.kt @@ -28,8 +28,8 @@ import org.kopi.galite.visual.domain.INT import org.kopi.galite.visual.domain.STRING import org.kopi.galite.visual.dsl.common.Icon import org.kopi.galite.visual.dsl.form.Key -import org.kopi.galite.visual.dsl.pivotTable.Dimension.Position -import org.kopi.galite.visual.dsl.pivotTable.PivotTable +import org.kopi.galite.visual.dsl.pivottable.Dimension.Position +import org.kopi.galite.visual.dsl.pivottable.PivotTable import org.vaadin.addons.componentfactory.PivotTable.Aggregator import org.vaadin.addons.componentfactory.PivotTable.Renderer diff --git a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/taxRule/TaxRuleP.kt b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/taxRule/TaxRuleP.kt index 3968ea881..fe6951c01 100644 --- a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/taxRule/TaxRuleP.kt +++ b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/taxRule/TaxRuleP.kt @@ -23,7 +23,7 @@ import org.jetbrains.exposed.sql.transactions.transaction import org.kopi.galite.demo.database.TaxRule import org.kopi.galite.visual.domain.INT import org.kopi.galite.visual.domain.STRING -import org.kopi.galite.visual.dsl.pivotTable.PivotTable +import org.kopi.galite.visual.dsl.pivottable.PivotTable /** * Tax Rules Report From 2925b384b3ff82e321f58d3784fb7f80dd6f27a1 Mon Sep 17 00:00:00 2001 From: Super User Date: Wed, 15 Nov 2023 11:38:41 +0100 Subject: [PATCH 18/20] Add a new pivot table exemple : ProductP --- .../kopi/galite/demo/database/Migration.kt | 13 +- .../org/kopi/galite/demo/database/Tables.kt | 2 +- .../kopi/galite/demo/product/ProductForm.kt | 5 + .../org/kopi/galite/demo/product/ProductP.kt | 113 ++++++++++++++++++ 4 files changed, 128 insertions(+), 5 deletions(-) create mode 100644 galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/product/ProductP.kt diff --git a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/database/Migration.kt b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/database/Migration.kt index 339189321..6805ef8c7 100644 --- a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/database/Migration.kt +++ b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/database/Migration.kt @@ -253,10 +253,15 @@ fun addClient(id: Int, } fun addProducts() { - addProduct(0, "description Product 0", 1, "tax 1", "Men", "Supplier 0", BigDecimal("263")) - addProduct(1, "description Product 1", 2, "tax 2", "Men","Supplier 0", BigDecimal("314")) - addProduct(2, "description Product 2", 3, "tax 2", "Women","Supplier 0", BigDecimal("180")) - addProduct(3, "description Product 3", 1, "tax 3", "Children","Supplier 0", BigDecimal("65")) + for (i in 0..499) { + val description = "description Product $i" + val category = (1..5).random() + val tax = "tax $category" + val gender = listOf("Men", "Women", "Children").random() + val supplier = listOf("Supplier 0", "Supplier 1", "Supplier 2").random() + val price = (50..500).random().toBigDecimal() + addProduct(i, description, category, tax, gender, supplier, price) + } } fun addSales() { diff --git a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/database/Tables.kt b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/database/Tables.kt index 5a28482e9..63b1df1b5 100644 --- a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/database/Tables.kt +++ b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/database/Tables.kt @@ -127,4 +127,4 @@ object TaxRule : Table("TAX_RULE") { override val primaryKey = PrimaryKey(idTaxe) } -val TASKId = Sequence("TASKId") +val TASKId = Sequence("TASKId") \ No newline at end of file diff --git a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/product/ProductForm.kt b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/product/ProductForm.kt index be5ec81e0..a826e7968 100644 --- a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/product/ProductForm.kt +++ b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/product/ProductForm.kt @@ -81,6 +81,11 @@ class ProductForm : DictionaryForm(title = "Products", locale = Locale.UK) { ProductR() } } + command(item = pivotTable) { + createPivotTable { + ProductP() + } + } } } diff --git a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/product/ProductP.kt b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/product/ProductP.kt new file mode 100644 index 000000000..b317eaec8 --- /dev/null +++ b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/product/ProductP.kt @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2013-2023 kopiLeft Services SARL, Tunis TN + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +package org.kopi.galite.demo.product + +import java.util.Locale + +import org.jetbrains.exposed.sql.selectAll +import org.jetbrains.exposed.sql.transactions.transaction +import org.kopi.galite.demo.database.Product +import org.kopi.galite.visual.domain.DECIMAL +import org.kopi.galite.visual.domain.STRING +import org.kopi.galite.visual.dsl.common.Icon +import org.kopi.galite.visual.dsl.form.Key +import org.kopi.galite.visual.dsl.pivottable.PivotTable +import org.kopi.galite.visual.dsl.pivottable.Dimension.Position + +/** + * Product Report + */ +class ProductP : PivotTable(title = "Products", locale = Locale.UK) { + + val action = menu("Action") + + val quit = actor(menu = action, label = "Quit", help = "Quit", ident = "quit") { + key = Key.F1 + icon = Icon.QUIT + } + + val cmdQuit = command(item = quit) { + model.close() + } + + val category = dimension(STRING(10), Position.ROW) { + label = "Category" + help = "The product category" + } + + val department = dimension(STRING(20), Position.COLUMN) { + label = "Department" + help = "The product department" + } + + val supplier = dimension(STRING(20), Position.COLUMN) { + label = "Supplier" + help = "The supplier" + } + + val taxName = dimension(STRING(10), Position.COLUMN) { + label = "Tax" + help = "The product tax name" + } + + val price = measure(DECIMAL(10, 5)) { + label = "Price" + help = "The product unit price excluding VAT" + } + + val products = Product.selectAll() + + init { + transaction { + products.forEach { result -> + add { + this[department] = result[Product.department] + this[supplier] = result[Product.supplier] + this[category] = decoderCategory(result[Product.category]) + this[taxName] = decoderTaxe(result[Product.taxName]) + this[price] = result[Product.price] + } + } + } + } + fun decoderCategory(category: Int) : String { + var result: String + when (category) { + 1 -> result= "shoes" + 2 -> result = "shirts" + 3 -> result = "glasses" + 4 -> result = "pullovers" + 5 -> result = "jeans" + else -> result = "inconnu" + } + return result + } + + fun decoderTaxe(taxe: String) : String { + var result: String + when (taxe) { + "tax 0" -> result= "0%" + "tax 1" -> result= "19%" + "tax 2" -> result = "9%" + "tax 3" -> result = "13%" + "tax 4" -> result = "22%" + "tax 5" -> result = "11%" + else -> result = "inconnu" + } + return result + } +} From 11b1b00fe61b4303f5383a719ae9276bb5667490 Mon Sep 17 00:00:00 2001 From: Super User Date: Wed, 15 Nov 2023 12:08:22 +0100 Subject: [PATCH 19/20] Modify the identification of a field in the pivot table --- .../visual/dsl/pivottable/PivotTable.kt | 4 +- .../org/kopi/galite/demo/product/ProductP.kt | 8 +-- .../kopi/galite/demo/taxRule/TaxRuleForm.kt | 5 -- .../org/kopi/galite/demo/taxRule/TaxRuleP.kt | 55 ------------------- .../org/kopi/galite/demo/bill/BillP-fr_FR.xml | 16 ------ .../demo/billproduct/BillProductP-fr_FR.xml | 6 +- .../kopi/galite/demo/client/ClientP-fr_FR.xml | 16 +++--- .../galite/demo/product/ProductP-fr_FR.xml | 13 +++++ .../galite/demo/provider/ProviderP-fr_FR.xml | 16 ------ .../kopi/galite/demo/stock/StockP-fr_FR.xml | 14 ----- .../galite/demo/taxRule/TaxRuleP-fr_FR.xml | 13 ----- 11 files changed, 30 insertions(+), 136 deletions(-) delete mode 100644 galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/taxRule/TaxRuleP.kt delete mode 100644 galite-demo/galite-vaadin/src/main/resources/org/kopi/galite/demo/bill/BillP-fr_FR.xml create mode 100644 galite-demo/galite-vaadin/src/main/resources/org/kopi/galite/demo/product/ProductP-fr_FR.xml delete mode 100644 galite-demo/galite-vaadin/src/main/resources/org/kopi/galite/demo/provider/ProviderP-fr_FR.xml delete mode 100644 galite-demo/galite-vaadin/src/main/resources/org/kopi/galite/demo/stock/StockP-fr_FR.xml delete mode 100644 galite-demo/galite-vaadin/src/main/resources/org/kopi/galite/demo/taxRule/TaxRuleP-fr_FR.xml diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivottable/PivotTable.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivottable/PivotTable.kt index 06f9f79c8..ba49aa53d 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivottable/PivotTable.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivottable/PivotTable.kt @@ -44,7 +44,7 @@ abstract class PivotTable(title: String, val help: String?, locale: Locale? = nu position: Dimension.Position, noinline init: Dimension.() -> Unit): Dimension { domain.kClass = T::class - val dimension = Dimension(domain, init, "ANM_${(dimensions + measures).size}", position, domain.source.ifEmpty { `access$sourceFile` }) + val dimension = Dimension(domain, init, "DIMENSION_${dimensions.size}", position, domain.source.ifEmpty { `access$sourceFile` }) dimension.init() model.model.columns.add(dimension.buildPivotTableColumn()) dimensions.add(dimension) @@ -55,7 +55,7 @@ abstract class PivotTable(title: String, val help: String?, locale: Locale? = nu inline fun ?> measure(domain: Domain, noinline init: Measure.() -> Unit): Measure { domain.kClass = T::class - val measure = Measure(domain, init, "ANM_${(dimensions + measures).size}", domain.source.ifEmpty { `access$sourceFile` }) + val measure = Measure(domain, init, "MEASURE_${measures.size}", domain.source.ifEmpty { `access$sourceFile` }) measure.init() model.model.columns.add(measure.buildPivotTableColumn()) measures.add(measure) diff --git a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/product/ProductP.kt b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/product/ProductP.kt index b317eaec8..92d60e764 100644 --- a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/product/ProductP.kt +++ b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/product/ProductP.kt @@ -77,14 +77,14 @@ class ProductP : PivotTable(title = "Products", locale = Locale.UK) { add { this[department] = result[Product.department] this[supplier] = result[Product.supplier] - this[category] = decoderCategory(result[Product.category]) - this[taxName] = decoderTaxe(result[Product.taxName]) + this[category] = décoderCategory(result[Product.category]) + this[taxName] = décoderTaxe(result[Product.taxName]) this[price] = result[Product.price] } } } } - fun decoderCategory(category: Int) : String { + fun décoderCategory(category: Int) : String { var result: String when (category) { 1 -> result= "shoes" @@ -97,7 +97,7 @@ class ProductP : PivotTable(title = "Products", locale = Locale.UK) { return result } - fun decoderTaxe(taxe: String) : String { + fun décoderTaxe(taxe: String) : String { var result: String when (taxe) { "tax 0" -> result= "0%" diff --git a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/taxRule/TaxRuleForm.kt b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/taxRule/TaxRuleForm.kt index 633200c18..c3538d295 100644 --- a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/taxRule/TaxRuleForm.kt +++ b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/taxRule/TaxRuleForm.kt @@ -93,11 +93,6 @@ class TaxRuleForm : DictionaryForm(title = "TaxRules", locale = Locale.UK) { TaxRuleR() } } - command(item = pivotTable) { - createPivotTable { - TaxRuleP() - } - } command(item = save) { saveBlock() diff --git a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/taxRule/TaxRuleP.kt b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/taxRule/TaxRuleP.kt deleted file mode 100644 index fe6951c01..000000000 --- a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/taxRule/TaxRuleP.kt +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.kopi.galite.demo.taxRule - -import java.util.Locale - -import org.jetbrains.exposed.sql.selectAll -import org.jetbrains.exposed.sql.transactions.transaction -import org.kopi.galite.demo.database.TaxRule -import org.kopi.galite.visual.domain.INT -import org.kopi.galite.visual.domain.STRING -import org.kopi.galite.visual.dsl.pivottable.PivotTable - -/** - * Tax Rules Report - */ -class TaxRuleP : PivotTable(title = "TaxRules_Report", locale = Locale.UK) { - - val action = menu("Action") - - val taxName = measure(STRING(50)) { - label = "Name" - } - - val rate = measure(INT(25)) { - label = "Rate in %" - } - - val taxRules = TaxRule.selectAll() - - init { - transaction { - taxRules.forEach { result -> - add { - this[taxName] = result[TaxRule.taxName] - this[rate] = result[TaxRule.rate] - } - } - } - } -} diff --git a/galite-demo/galite-vaadin/src/main/resources/org/kopi/galite/demo/bill/BillP-fr_FR.xml b/galite-demo/galite-vaadin/src/main/resources/org/kopi/galite/demo/bill/BillP-fr_FR.xml deleted file mode 100644 index b0da03e14..000000000 --- a/galite-demo/galite-vaadin/src/main/resources/org/kopi/galite/demo/bill/BillP-fr_FR.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/galite-demo/galite-vaadin/src/main/resources/org/kopi/galite/demo/billproduct/BillProductP-fr_FR.xml b/galite-demo/galite-vaadin/src/main/resources/org/kopi/galite/demo/billproduct/BillProductP-fr_FR.xml index c37cf8c43..da8a3f99c 100644 --- a/galite-demo/galite-vaadin/src/main/resources/org/kopi/galite/demo/billproduct/BillProductP-fr_FR.xml +++ b/galite-demo/galite-vaadin/src/main/resources/org/kopi/galite/demo/billproduct/BillProductP-fr_FR.xml @@ -7,8 +7,8 @@ - - - + + + diff --git a/galite-demo/galite-vaadin/src/main/resources/org/kopi/galite/demo/client/ClientP-fr_FR.xml b/galite-demo/galite-vaadin/src/main/resources/org/kopi/galite/demo/client/ClientP-fr_FR.xml index 10f28601f..a0a5898ce 100644 --- a/galite-demo/galite-vaadin/src/main/resources/org/kopi/galite/demo/client/ClientP-fr_FR.xml +++ b/galite-demo/galite-vaadin/src/main/resources/org/kopi/galite/demo/client/ClientP-fr_FR.xml @@ -7,13 +7,13 @@ - - - - - - - - + + + + + + + + diff --git a/galite-demo/galite-vaadin/src/main/resources/org/kopi/galite/demo/product/ProductP-fr_FR.xml b/galite-demo/galite-vaadin/src/main/resources/org/kopi/galite/demo/product/ProductP-fr_FR.xml new file mode 100644 index 000000000..a7d963d44 --- /dev/null +++ b/galite-demo/galite-vaadin/src/main/resources/org/kopi/galite/demo/product/ProductP-fr_FR.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/galite-demo/galite-vaadin/src/main/resources/org/kopi/galite/demo/provider/ProviderP-fr_FR.xml b/galite-demo/galite-vaadin/src/main/resources/org/kopi/galite/demo/provider/ProviderP-fr_FR.xml deleted file mode 100644 index 525893471..000000000 --- a/galite-demo/galite-vaadin/src/main/resources/org/kopi/galite/demo/provider/ProviderP-fr_FR.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/galite-demo/galite-vaadin/src/main/resources/org/kopi/galite/demo/stock/StockP-fr_FR.xml b/galite-demo/galite-vaadin/src/main/resources/org/kopi/galite/demo/stock/StockP-fr_FR.xml deleted file mode 100644 index 8d94a47e7..000000000 --- a/galite-demo/galite-vaadin/src/main/resources/org/kopi/galite/demo/stock/StockP-fr_FR.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/galite-demo/galite-vaadin/src/main/resources/org/kopi/galite/demo/taxRule/TaxRuleP-fr_FR.xml b/galite-demo/galite-vaadin/src/main/resources/org/kopi/galite/demo/taxRule/TaxRuleP-fr_FR.xml deleted file mode 100644 index 1f8a0b03f..000000000 --- a/galite-demo/galite-vaadin/src/main/resources/org/kopi/galite/demo/taxRule/TaxRuleP-fr_FR.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - From 5ee987afc6d9a4a43b23503a3ee9f37cdd76663a Mon Sep 17 00:00:00 2001 From: Super User Date: Fri, 24 Nov 2023 11:57:50 +0100 Subject: [PATCH 20/20] Traitement des retours --- .../galite/visual/dsl/pivottable/Dimension.kt | 6 +- .../visual/dsl/pivottable/PivotTable.kt | 2 - .../galite/visual/l10n/PivotTableLocalizer.kt | 4 +- .../galite/visual/pivottable/Constants.kt | 2 - .../galite/visual/pivottable/VPivotTable.kt | 6 +- .../visual/pivottable/VPivotTableColumn.kt | 3 +- .../ui/vaadin/pivottable/DPivotTable.kt | 8 +-- .../demo/billproduct/BillProductForm.kt | 5 -- .../galite/demo/billproduct/BillProductP.kt | 58 ------------------- .../org/kopi/galite/demo/client/ClientP.kt | 50 +++++++++++----- .../kopi/galite/demo/database/Migration.kt | 7 ++- .../demo/billproduct/BillProductP-fr_FR.xml | 14 ----- .../kopi/galite/demo/client/ClientP-fr_FR.xml | 12 ++-- .../galite/tests/ui/vaadin/form/FormTests.kt | 2 +- 14 files changed, 61 insertions(+), 118 deletions(-) delete mode 100644 galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/billproduct/BillProductP.kt delete mode 100644 galite-demo/galite-vaadin/src/main/resources/org/kopi/galite/demo/billproduct/BillProductP-fr_FR.xml diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivottable/Dimension.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivottable/Dimension.kt index 4fbcfb876..dda64655d 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivottable/Dimension.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivottable/Dimension.kt @@ -57,8 +57,8 @@ class Dimension(override val domain: Domain, // ---------------------------------------------------------------------- enum class Position(val value: Int) { - NONE(Constants.DIMENSION_NO_POSITION), - ROW(Constants.DIMENSION_ROW), - COLUMN(Constants.DIMENSION_COLUMN), + NONE(Constants.DIMENSION_NO_POSITION), + ROW(Constants.DIMENSION_ROW), + COLUMN(Constants.DIMENSION_COLUMN) } } diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivottable/PivotTable.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivottable/PivotTable.kt index ba49aa53d..246cd760d 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivottable/PivotTable.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/dsl/pivottable/PivotTable.kt @@ -96,10 +96,8 @@ abstract class PivotTable(title: String, val help: String?, locale: Locale? = nu val trigger = FormTrigger(event, pivotTableAction) triggers.add(FormTrigger(event, Action(null, method))) - // PIVOT TABLE TRIGGERS triggers.forEach { trigger -> - for (i in VConstants.TRG_TYPES.indices) { if (trigger.events shr i and 1 > 0) { model.PIVOT_TABLE_Triggers[0][i] = trigger diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/l10n/PivotTableLocalizer.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/l10n/PivotTableLocalizer.kt index 555aa02e1..b52e60a7b 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/l10n/PivotTableLocalizer.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/l10n/PivotTableLocalizer.kt @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN - * Copyright (c) 1990-2022 kopiRight Managed Solutions GmbH, Wien AT + * Copyright (c) 2013-2023 kopiLeft Services SARL, Tunis TN + * Copyright (c) 1990-2023 kopiRight Managed Solutions GmbH, Wien AT * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivottable/Constants.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivottable/Constants.kt index c231dfef6..af70dfd31 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivottable/Constants.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivottable/Constants.kt @@ -20,8 +20,6 @@ package org.kopi.galite.visual.pivottable import org.kopi.galite.visual.form.VConstants import org.kopi.galite.visual.Constants -import org.vaadin.addons.componentfactory.PivotTable.Renderer -import org.vaadin.addons.componentfactory.PivotTable.Aggregator /** * Collects some constants for the pivot table implementation diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivottable/VPivotTable.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivottable/VPivotTable.kt index a1af4f1af..d4819a0f9 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivottable/VPivotTable.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivottable/VPivotTable.kt @@ -21,12 +21,13 @@ package org.kopi.galite.visual.pivottable import java.io.File import java.net.MalformedURLException +import org.vaadin.addons.componentfactory.PivotTable.* + import org.kopi.galite.util.base.InconsistencyException import org.kopi.galite.visual.* import org.kopi.galite.visual.form.VConstants import org.kopi.galite.visual.l10n.LocalizationManager import org.kopi.galite.visual.dsl.common.Trigger -import org.vaadin.addons.componentfactory.PivotTable.* /** * Represents a pivot table model. @@ -39,8 +40,7 @@ abstract class VPivotTable internal constructor() : VWindow(), VConstants { org.kopi.galite.visual.Constants.MDL_PIVOT_TABLE, object : WindowBuilder { override fun createWindow(model: VWindow): UWindow { - return UIFactory.uiFactory.createView( - model) as UPivotTable + return UIFactory.uiFactory.createView(model) as UPivotTable } } ) diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivottable/VPivotTableColumn.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivottable/VPivotTableColumn.kt index 9dd0a165a..27e826d9d 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/pivottable/VPivotTableColumn.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/pivottable/VPivotTableColumn.kt @@ -24,9 +24,8 @@ import org.kopi.galite.visual.l10n.PivotTableLocalizer /** * Represents a pivot table column description - * * @param ident The identifier of the field - * + * @param position The position of the dimension field */ class VPivotTableColumn(val ident: String?, val position: Dimension.Position?) { diff --git a/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivottable/DPivotTable.kt b/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivottable/DPivotTable.kt index 53c2d5b15..96c924ca1 100644 --- a/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivottable/DPivotTable.kt +++ b/galite-core/src/main/kotlin/org/kopi/galite/visual/ui/vaadin/pivottable/DPivotTable.kt @@ -17,15 +17,15 @@ */ package org.kopi.galite.visual.ui.vaadin.pivottable +import org.vaadin.addons.componentfactory.PivotTable import com.vaadin.flow.component.dependency.CssImport + import org.kopi.galite.visual.dsl.pivottable.Dimension.Position import org.kopi.galite.visual.pivottable.MPivotTable import org.kopi.galite.visual.pivottable.UPivotTable import org.kopi.galite.visual.pivottable.VPivotTable import org.kopi.galite.visual.ui.vaadin.visual.DWindow -import org.vaadin.addons.componentfactory.PivotTable - @CssImport("./styles/galite/pivottable.css") class DPivotTable(private val pivotTable: VPivotTable) : DWindow(pivotTable), UPivotTable { @@ -62,9 +62,9 @@ class DPivotTable(private val pivotTable: VPivotTable) : DWindow(pivotTable), UP } model.userRows - ?.flatMap { it.data.filterNotNull() } + ?.flatMap { it.data.asIterable() } ?.chunked(model.columns.count()) { rows -> - pivotData.addRow(*rows.toTypedArray())} + pivotData.addRow(*rows.map { it ?: "" }.toTypedArray())} // Pivot table dimension pivotOptions.setRows(*rows.toTypedArray()) diff --git a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/billproduct/BillProductForm.kt b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/billproduct/BillProductForm.kt index cea7600cc..64ec0d33e 100644 --- a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/billproduct/BillProductForm.kt +++ b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/billproduct/BillProductForm.kt @@ -41,11 +41,6 @@ class BillProductForm : DictionaryForm("Bill products", Locale.UK) { BillProductR() } } - command(item = pivotTable) { - createPivotTable { - BillProductP() - } - } } class BlockBillProduct : Block("bill product", 1, 1) { diff --git a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/billproduct/BillProductP.kt b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/billproduct/BillProductP.kt deleted file mode 100644 index 2c3f1619c..000000000 --- a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/billproduct/BillProductP.kt +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2013-2022 kopiLeft Services SARL, Tunis TN - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.kopi.galite.demo.billproduct - -import java.util.Locale - -import org.jetbrains.exposed.sql.selectAll -import org.jetbrains.exposed.sql.transactions.transaction -import org.kopi.galite.demo.database.BillProduct -import org.kopi.galite.visual.domain.DECIMAL -import org.kopi.galite.visual.domain.INT -import org.kopi.galite.visual.dsl.pivottable.PivotTable - -/** - * Products Bill Report - */ -class BillProductP : PivotTable("Bill Product Report", Locale.UK) { - - val quantity = measure(INT(25)) { - label = "Quantity" - } - - val amount = measure(DECIMAL(25, 10)) { - label = "Amount before tax" - - } - val amountWithTaxes = measure(DECIMAL(50, 10)) { - label = "Amount all taxes included" - } - - val billProducts = BillProduct.selectAll() - - init { - transaction { - billProducts.forEach { result -> - add { - this[quantity] = result[BillProduct.quantity] - this[amount] = result[BillProduct.amount] - this[amountWithTaxes] = result[BillProduct.amountWithTaxes] - } - } - } - } -} diff --git a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/client/ClientP.kt b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/client/ClientP.kt index 9eb0816f2..3aa1e4a2d 100644 --- a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/client/ClientP.kt +++ b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/client/ClientP.kt @@ -16,22 +16,26 @@ */ package org.kopi.galite.demo.client -import org.jetbrains.exposed.sql.JoinType -import org.jetbrains.exposed.sql.alias import java.util.Locale +import org.jetbrains.exposed.sql.JoinType import org.jetbrains.exposed.sql.selectAll import org.jetbrains.exposed.sql.transactions.transaction + +import org.vaadin.addons.componentfactory.PivotTable.Renderer + import org.kopi.galite.demo.database.Client +import org.kopi.galite.demo.database.Product +import org.kopi.galite.demo.database.Purchase import org.kopi.galite.visual.domain.BOOL +import org.kopi.galite.visual.domain.DECIMAL import org.kopi.galite.visual.domain.INT import org.kopi.galite.visual.domain.STRING import org.kopi.galite.visual.dsl.common.Icon import org.kopi.galite.visual.dsl.form.Key import org.kopi.galite.visual.dsl.pivottable.Dimension.Position import org.kopi.galite.visual.dsl.pivottable.PivotTable -import org.vaadin.addons.componentfactory.PivotTable.Aggregator -import org.vaadin.addons.componentfactory.PivotTable.Renderer +import org.kopi.galite.visual.pivottable.Constants /** * Client Report @@ -68,48 +72,60 @@ class ClientP : PivotTable(title = "Clients_Pivot_Table", locale = Locale.UK) { help = "The client last name" } - val addressClt = dimension(STRING(50), Position.ROW) { + val countryClt = dimension(STRING(50), Position.COLUMN) { + label = "Country" + help = "The client country" + } + + val addressClt = dimension(STRING(50), Position.COLUMN) { label = "Address" help = "The client address" } - val ageClt = dimension(INT(2), Position.COLUMN) { + val ageClt = dimension(INT(2), Position.NONE) { label = "Age" help = "The client age" } - val countryClt = dimension(STRING(50), Position.ROW) { - label = "Country" - help = "The client country" - } - val cityClt = dimension(STRING(50), Position.NONE) { label = "City" help = "The client city" } - val zipCodeClt = measure(INT(2)) { + val zipCodeClt = dimension(INT(2), Position.NONE) { label = "Zip code" help = "The client zip code" } - val activeClt = measure(BOOL) { + val activeClt = dimension(BOOL, Position.NONE) { label = "Status" help = "Is the client active?" } + val quantity = measure(INT(10)) { + label = "Quantity" + help = "Product quantity" + } + + val price = measure(DECIMAL(9,3)) { + label = "Price" + help = "Product price" + } + val init = trigger(INIT) { defaultRenderer = Renderer.TABLE - aggregator = Pair(Aggregator.SAMPLE_VARIANCE, "") + aggregator = Pair(Constants.COUNT_FRACTION_COLUMNS, "") disabledRerenders = mutableListOf(Renderer.SCATTER_CHART, Renderer.LINE_CHART, Renderer.HORIZONTAL_BAR_CHART, Renderer.HORIZONTAL_STACKED_BAR_CHART) //interactive = Constants.MODE_NONINTERACTIVE } - val clients = Client.selectAll() + val purchase = Client.join(Purchase, JoinType.LEFT) { Purchase.idClt eq Client.idClt} + .join(Product, JoinType.LEFT) { Purchase.idPdt eq Product.idPdt } + .selectAll() init { transaction { - clients.forEach { result -> + purchase.forEach { result -> add { this[firstName] = result[Client.firstNameClt] this[lastName] = result[Client.lastNameClt] @@ -119,6 +135,8 @@ class ClientP : PivotTable(title = "Clients_Pivot_Table", locale = Locale.UK) { this[cityClt] = result[Client.cityClt] this[zipCodeClt] = result[Client.zipCodeClt] this[activeClt] = result[Client.activeClt] + this[quantity] = result[Purchase.quantity] + this[price] = result[Product.price] } } } diff --git a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/database/Migration.kt b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/database/Migration.kt index 6805ef8c7..b915efef4 100644 --- a/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/database/Migration.kt +++ b/galite-demo/galite-vaadin/src/main/kotlin/org/kopi/galite/demo/database/Migration.kt @@ -253,7 +253,12 @@ fun addClient(id: Int, } fun addProducts() { - for (i in 0..499) { + // That data is used in automated tests + addProduct(0, "description Product 0", 1, "tax 1", "Men", "Supplier 0", BigDecimal("263")) + addProduct(1, "description Product 1", 2, "tax 2", "Men","Supplier 0", BigDecimal("314")) + addProduct(2, "description Product 2", 3, "tax 2", "Women","Supplier 0", BigDecimal("180")) + addProduct(3, "description Product 3", 1, "tax 3", "Children","Supplier 0", BigDecimal("65")) + for (i in 4..499) { val description = "description Product $i" val category = (1..5).random() val tax = "tax $category" diff --git a/galite-demo/galite-vaadin/src/main/resources/org/kopi/galite/demo/billproduct/BillProductP-fr_FR.xml b/galite-demo/galite-vaadin/src/main/resources/org/kopi/galite/demo/billproduct/BillProductP-fr_FR.xml deleted file mode 100644 index da8a3f99c..000000000 --- a/galite-demo/galite-vaadin/src/main/resources/org/kopi/galite/demo/billproduct/BillProductP-fr_FR.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/galite-demo/galite-vaadin/src/main/resources/org/kopi/galite/demo/client/ClientP-fr_FR.xml b/galite-demo/galite-vaadin/src/main/resources/org/kopi/galite/demo/client/ClientP-fr_FR.xml index a0a5898ce..cf1d16026 100644 --- a/galite-demo/galite-vaadin/src/main/resources/org/kopi/galite/demo/client/ClientP-fr_FR.xml +++ b/galite-demo/galite-vaadin/src/main/resources/org/kopi/galite/demo/client/ClientP-fr_FR.xml @@ -9,11 +9,13 @@ - - - + + + - - + + + + diff --git a/galite-demo/galite-vaadin/src/test/kotlin/org/kopi/galite/tests/ui/vaadin/form/FormTests.kt b/galite-demo/galite-vaadin/src/test/kotlin/org/kopi/galite/tests/ui/vaadin/form/FormTests.kt index 688ff5252..bb684d253 100644 --- a/galite-demo/galite-vaadin/src/test/kotlin/org/kopi/galite/tests/ui/vaadin/form/FormTests.kt +++ b/galite-demo/galite-vaadin/src/test/kotlin/org/kopi/galite/tests/ui/vaadin/form/FormTests.kt @@ -110,7 +110,7 @@ class FormTests: GaliteVUITestBase() { arrayOf("3", "description Product 3", "3", "65,00000") ) - data.forEachIndexed { index, row -> + data.take(4).forEachIndexed { index, row -> block.grid.expectRow(index, *row) } }