[Editor] Make Query Result View table editable
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
package com.bartlomiejpluta.base.editor.database.component
|
||||
|
||||
import com.bartlomiejpluta.base.editor.database.model.data.DataField
|
||||
import com.bartlomiejpluta.base.editor.database.model.data.DataRecord
|
||||
import com.bartlomiejpluta.base.editor.database.model.data.Operation
|
||||
import javafx.scene.control.TableCell
|
||||
import javafx.util.StringConverter
|
||||
|
||||
class DataFieldStringConverter : StringConverter<DataField>() {
|
||||
lateinit var cell: TableCell<DataRecord, DataField>
|
||||
|
||||
override fun toString(item: DataField?): String = cell.item?.value ?: ""
|
||||
|
||||
override fun fromString(string: String?): DataField = cell.item.apply {
|
||||
if (record.operation == Operation.DO_NOTHING) {
|
||||
record.operation = Operation.UPDATE
|
||||
}
|
||||
|
||||
value = string
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.bartlomiejpluta.base.editor.database.component
|
||||
|
||||
import com.bartlomiejpluta.base.editor.database.model.data.DataRecord
|
||||
import com.bartlomiejpluta.base.editor.database.model.data.Operation
|
||||
import javafx.beans.binding.Bindings
|
||||
import javafx.scene.control.TableRow
|
||||
|
||||
class DataRecordRow : TableRow<DataRecord>() {
|
||||
override fun updateItem(item: DataRecord?, empty: Boolean) {
|
||||
super.updateItem(item, empty)
|
||||
when {
|
||||
empty || item == null -> {
|
||||
text = null
|
||||
graphic = null
|
||||
styleProperty().unbind()
|
||||
style = ""
|
||||
}
|
||||
|
||||
else -> {
|
||||
styleProperty().bind(
|
||||
Bindings.createStringBinding({
|
||||
when (item.operation) {
|
||||
Operation.INSERT -> "-fx-background-color: $INSERT_BG;"
|
||||
Operation.UPDATE -> "-fx-background-color: $UPDATE_BG;"
|
||||
Operation.DELETE -> "-fx-background-color: $DELETE_BG;"
|
||||
else -> ""
|
||||
}
|
||||
}, item.operationProperty)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val INSERT_BG = "#00AA00"
|
||||
private const val INSERT_FG = "#FFFFFF"
|
||||
|
||||
private const val UPDATE_BG = "#AABB00"
|
||||
private const val UPDATE_FG = "#FFFFFF"
|
||||
|
||||
private const val DELETE_BG = "#FF0000"
|
||||
private const val DELETE_FG = "#FFFFFF"
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
package com.bartlomiejpluta.base.editor.database.component
|
||||
|
||||
import com.bartlomiejpluta.base.editor.database.model.data.DataField
|
||||
import com.bartlomiejpluta.base.editor.database.model.data.DataRecord
|
||||
import javafx.scene.control.TableCell
|
||||
|
||||
class QueryFieldCell : TableCell<DataRecord, DataField>() {
|
||||
|
||||
override fun updateItem(item: DataField?, empty: Boolean) {
|
||||
super.updateItem(item, empty)
|
||||
|
||||
when {
|
||||
empty || item == null -> {
|
||||
text = null
|
||||
graphic = null
|
||||
}
|
||||
|
||||
else -> {
|
||||
text = item.value
|
||||
graphic = null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,8 +12,8 @@ import java.sql.SQLException
|
||||
class DatabaseController : Controller() {
|
||||
private val databaseService: DatabaseService by di()
|
||||
|
||||
fun execute(statement: String, name: String = ""): Query? = try {
|
||||
databaseService.execute(statement, name)
|
||||
fun execute(statement: String, name: String, table: String? = null): Query? = try {
|
||||
databaseService.execute(statement, name, table)
|
||||
} catch (e: SQLException) {
|
||||
sqlErrorAlert(e)
|
||||
null
|
||||
|
||||
@@ -5,6 +5,8 @@ import tornadofx.getValue
|
||||
import tornadofx.setValue
|
||||
|
||||
class DataField(value: String?) {
|
||||
lateinit var record: DataRecord
|
||||
|
||||
val valueProperty = SimpleStringProperty(value)
|
||||
var value by valueProperty
|
||||
}
|
||||
@@ -1,3 +1,18 @@
|
||||
package com.bartlomiejpluta.base.editor.database.model.data
|
||||
|
||||
class DataRecord(val fields: Map<String, DataField>, val operation: Operation = Operation.DO_NOTHING)
|
||||
import tornadofx.getValue
|
||||
import tornadofx.setValue
|
||||
import tornadofx.toProperty
|
||||
import kotlin.collections.Map
|
||||
import kotlin.collections.component1
|
||||
import kotlin.collections.component2
|
||||
import kotlin.collections.forEach
|
||||
|
||||
class DataRecord(val fields: Map<String, DataField>, operation: Operation = Operation.DO_NOTHING) {
|
||||
val operationProperty = operation.toProperty()
|
||||
var operation by operationProperty
|
||||
|
||||
init {
|
||||
fields.forEach { (_, field) -> field.record = this }
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,21 @@
|
||||
package com.bartlomiejpluta.base.editor.database.model.data
|
||||
|
||||
import javafx.beans.property.SimpleListProperty
|
||||
import javafx.beans.property.SimpleStringProperty
|
||||
import javafx.collections.ObservableList
|
||||
import tornadofx.getValue
|
||||
import tornadofx.toProperty
|
||||
|
||||
class Query(name: String, query: String, columns: ObservableList<String>, data: ObservableList<DataRecord>) {
|
||||
class Query(
|
||||
name: String,
|
||||
query: String,
|
||||
columns: ObservableList<String>,
|
||||
data: ObservableList<DataRecord>,
|
||||
table: String? = null
|
||||
) {
|
||||
val tableProperty = SimpleStringProperty(table)
|
||||
val table by tableProperty
|
||||
|
||||
val nameProperty = name.toProperty()
|
||||
val name by nameProperty
|
||||
|
||||
|
||||
@@ -9,5 +9,5 @@ interface DatabaseService {
|
||||
|
||||
fun <T> run(op: Connection.() -> T): T?
|
||||
|
||||
fun execute(statement: String, name: String = ""): Query?
|
||||
fun execute(statement: String, name: String, table: String? = null): Query?
|
||||
}
|
||||
@@ -49,7 +49,7 @@ class H2DatabaseService : DatabaseService {
|
||||
return projectContext.project?.database?.connection?.use(op)
|
||||
}
|
||||
|
||||
override fun execute(statement: String, name: String): Query? = run {
|
||||
override fun execute(statement: String, name: String, table: String?): Query? = run {
|
||||
val stmt = prepareStatement(statement).apply { execute() }
|
||||
val results = stmt.resultSet
|
||||
val metadata = stmt.metaData
|
||||
@@ -66,13 +66,14 @@ class H2DatabaseService : DatabaseService {
|
||||
val record = mutableMapOf<String, DataField>()
|
||||
|
||||
for (i in 1..metadata.columnCount) {
|
||||
record[metadata.getColumnLabel(i)] = DataField(results.getObject(i)?.toString())
|
||||
val field = DataField(results.getObject(i)?.toString())
|
||||
record[metadata.getColumnLabel(i)] = field
|
||||
}
|
||||
|
||||
data += DataRecord(record)
|
||||
}
|
||||
|
||||
return@run Query(name, statement, columns, data)
|
||||
return@run Query(name, statement, columns, data, table)
|
||||
}
|
||||
|
||||
return@run null
|
||||
|
||||
@@ -35,7 +35,7 @@ class TablesListView : View() {
|
||||
val selected = selectionModel?.selectedItem?.value
|
||||
if (event.clickCount == 2 && selected is SchemaTable) {
|
||||
databaseController
|
||||
.execute("SELECT * FROM ${selected.name}", selected.name)
|
||||
.execute("SELECT * FROM ${selected.name}", selected.name, selected.name)
|
||||
?.let(mainController::openQuery)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,14 @@
|
||||
package com.bartlomiejpluta.base.editor.database.view.query
|
||||
|
||||
import com.bartlomiejpluta.base.editor.database.component.DataFieldStringConverter
|
||||
import com.bartlomiejpluta.base.editor.database.component.DataRecordRow
|
||||
import com.bartlomiejpluta.base.editor.database.controller.DatabaseController
|
||||
import com.bartlomiejpluta.base.editor.database.model.data.DataField
|
||||
import com.bartlomiejpluta.base.editor.database.model.data.DataRecord
|
||||
import com.bartlomiejpluta.base.editor.database.model.data.Operation
|
||||
import com.bartlomiejpluta.base.editor.database.viewmodel.QueryVM
|
||||
import javafx.scene.control.TableColumn
|
||||
import javafx.scene.control.cell.TextFieldTableCell
|
||||
import org.kordamp.ikonli.javafx.FontIcon
|
||||
import tornadofx.*
|
||||
|
||||
@@ -11,7 +16,11 @@ class QueryResultView : View() {
|
||||
private val databaseController: DatabaseController by di()
|
||||
private val queryVM = find<QueryVM>()
|
||||
|
||||
private val table = tableview(queryVM.dataProperty)
|
||||
private val table = tableview(queryVM.dataProperty) {
|
||||
editableProperty().bind(queryVM.tableProperty.isNotNull)
|
||||
|
||||
setRowFactory { DataRecordRow() }
|
||||
}
|
||||
|
||||
init {
|
||||
updateColumns()
|
||||
@@ -24,9 +33,16 @@ class QueryResultView : View() {
|
||||
private fun updateColumns() {
|
||||
table.columns.clear()
|
||||
queryVM.columns.map { column ->
|
||||
TableColumn<DataRecord, String>(column).apply {
|
||||
TableColumn<DataRecord, DataField>(column).apply {
|
||||
setCellFactory { column ->
|
||||
val converter = DataFieldStringConverter()
|
||||
val cell = TextFieldTableCell.forTableColumn<DataRecord, DataField>(converter).call(column)
|
||||
converter.cell = cell
|
||||
cell
|
||||
}
|
||||
|
||||
setCellValueFactory {
|
||||
it.value.fields[column]!!.valueProperty
|
||||
it.value.fields[column]!!.toProperty()
|
||||
}
|
||||
}
|
||||
}.let(table.columns::addAll)
|
||||
@@ -36,17 +52,39 @@ class QueryResultView : View() {
|
||||
top = toolbar {
|
||||
button(graphic = FontIcon("fa-refresh")) {
|
||||
action {
|
||||
databaseController.execute(queryVM.query, queryVM.name)?.let {
|
||||
databaseController.execute(queryVM.query, queryVM.name, queryVM.table)?.let {
|
||||
queryVM.item = it
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
button(graphic = FontIcon("fa-plus")) {
|
||||
enableWhen(queryVM.tableProperty.isNotNull)
|
||||
|
||||
action {
|
||||
queryVM.item?.addEmptyRecord()
|
||||
}
|
||||
}
|
||||
|
||||
button(graphic = FontIcon("fa-minus")) {
|
||||
enableWhen(queryVM.tableProperty.isNotNull)
|
||||
|
||||
action {
|
||||
val selected = table.selectionModel.selectedItem
|
||||
when (selected.operation) {
|
||||
Operation.INSERT -> table.items.remove(selected)
|
||||
else -> selected.operation = Operation.DELETE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
button(graphic = FontIcon("fa-check")) {
|
||||
enableWhen(queryVM.tableProperty.isNotNull)
|
||||
|
||||
action {
|
||||
println(queryVM.data.size)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
center = table
|
||||
|
||||
@@ -5,6 +5,9 @@ import tornadofx.ItemViewModel
|
||||
import tornadofx.getValue
|
||||
|
||||
class QueryVM(query: Query) : ItemViewModel<Query>(query) {
|
||||
val tableProperty = bind(Query::tableProperty)
|
||||
val table by tableProperty
|
||||
|
||||
val nameProperty = bind(Query::nameProperty)
|
||||
val name by nameProperty
|
||||
|
||||
|
||||
Reference in New Issue
Block a user