Skip to content
This repository has been archived by the owner on Sep 28, 2024. It is now read-only.

Streamlining CellFactories #67

Closed
thomasnield opened this issue Apr 3, 2016 · 27 comments
Closed

Streamlining CellFactories #67

thomasnield opened this issue Apr 3, 2016 · 27 comments

Comments

@thomasnield
Copy link
Collaborator

I wonder if there is opportunity to improve the cell factories for TableView and other data controls.

For instance, setting a mutable column in TableView to use a ComboBoxTableCell feels like it could be streamlined.

column("CATEGORY", ParsedTransaction::categoryProperty).apply {
    cellFactory = ComboBoxTableCell.forTableColumn(Category.all)
    setOnEditCommit {
        it.tableView.items[it.tablePosition.row].category = it.newValue
    }
}

It really should be just as easy as giving a List<R> or an ObservableList<R> for a given TableColumn<T,R> and the ComboBox just plugs in automagically.

column("CATEGORY", ParsedTransaction::categoryProperty).apply {
        applyComboBox(Category.all)
}
@thomasnield
Copy link
Collaborator Author

Here are the Cell Factories for TableView:

  • CheckBoxTableCell
  • ChoiceBoxTableCell
  • ComboBoxTableCell
  • ProgressBarTableCell
  • TextFieldTableCell

I'm sure there are other cell factories for other data controls.

@thomasnield
Copy link
Collaborator Author

By the way, how exactly do I properly bind the CheckBoxTableCell to a given Property? The value does not persist when I scroll and it sometimes is just downright random, which I believe means the state is not being bound at all to the Property.

column("CONFLICTED", ParsedTransaction::conflictProperty).apply {
    cellFactory = CheckBoxTableCell.forTableColumn(this)

    setOnEditCommit {
        it.tableView.items[it.tablePosition.row].conflict = it.newValue
    }
}

@edvin
Copy link
Owner

edvin commented Apr 3, 2016

That's a good idea. It should be possible to add a function that will be called on commit as well, for example to automatically save changes etc.

@thomasnield
Copy link
Collaborator Author

Yes, and literally just seconds before you I just posted an issue I was having with CheckBoxTableCell and the value not reflecting the model at all. This could be made more intuitive so people like me don't make mistakes or get confused : )

@edvin
Copy link
Owner

edvin commented Apr 3, 2016

I think the default behavior is to cancel the commit when you just leave focus from the cell, which is counter to what users expect. Is this what you're experiencing?

@thomasnield
Copy link
Collaborator Author

Maybe, although the values are being pushed from the model and not the user inputs. Let me see if I can post an SSCCE later, which we can also use for testing when we make these factories.

@edvin
Copy link
Owner

edvin commented Apr 3, 2016

Great! My experience is that you only need to do what you listed above, unless you want to override the default behavior of cancelling the edit on focus lost.

@edvin
Copy link
Owner

edvin commented Apr 3, 2016

I've started working on an implementation here in the meantime :)

@edvin
Copy link
Owner

edvin commented Apr 3, 2016

Initial suggestion for makeComboBox with support for optional operation after commit:

fun <S, T> TableColumn<S, T>.makeComboBox(items: ObservableList<T>, afterCommit: (TableColumn.CellEditEvent<S, T>.() -> Unit)? = null): TableColumn<S, T> {
    cellFactory = ComboBoxTableCell.forTableColumn(items)
    setOnEditCommit {
        val property = it.tableColumn.getCellObservableValue(it.rowValue) as ObjectProperty<T>
        property.value = it.newValue
        afterCommit?.invoke(it)
    }
    return this
}

@thomasnield
Copy link
Collaborator Author

Excellent! Just played with it and this is exactly what I was looking for.

@edvin
Copy link
Owner

edvin commented Apr 3, 2016

Commited makeComboBox, makeTextField, makeChoiceBox, makeProgressBar and makeCheckbox now :) I will test more tomorrow and look for a solution for the cancel behavior you ran into!

edvin pushed a commit that referenced this issue Apr 3, 2016
…`makeChoiceBox`, `makeProgressBar` and `makeCheckbox` (#67)
@thomasnield
Copy link
Collaborator Author

Awesome, I'll test it with my application today.

@edvin
Copy link
Owner

edvin commented Apr 3, 2016

Great! Let me know how it works, or if you can identify the problem you saw as well!

@edvin
Copy link
Owner

edvin commented Apr 4, 2016

I think I got the names wrong. make might suggest that we create a new column, while we actually just change the cellFactory. This "clashes" with `makeIndexColumn" which actually creates a column. Suggestions for better names for these methods?

@thomasnield
Copy link
Collaborator Author

Maybe use or apply?

@edvin
Copy link
Owner

edvin commented Apr 4, 2016

useComboBox, applyComboBox, asComboBox, toComboBox. Many options!

@thomasnield
Copy link
Collaborator Author

Hahaha, I'm biased towards use but I'll leave it up to you. Do you think we can apply a DatePicker one too?

@edvin
Copy link
Owner

edvin commented Apr 4, 2016

use it is then! I'll make the change :) DatePicker is a bigger undertaking, we'd have to create a TableCellColumn with editing support. That's an UI component, which currently TornadoFX has none of. I can created it in tornadofx-controls and add special support for it. I was thinking of integrating them because of the Form support in tornadofx-controls anyway. That would be an optional dependency then.

@edvin
Copy link
Owner

edvin commented Apr 5, 2016

Just crated a DatePickerTableCell @thomasnield: https://github.com/edvin/tornadofx-controls/releases/tag/v1.0.4

I will add TornadoFX Controls as an optional dependency and support useDatePicker for TableColumn.

@edvin
Copy link
Owner

edvin commented Apr 5, 2016

About naming.. We already have TableColumn.makeEditable which actually does kind of the same thing as these functions. We need to make sure the API stays clean when we introduce these new functions. Not sure about that right approach.

@thomasnield
Copy link
Collaborator Author

I need to look again at your controls project as I think I need it for some things. And thanks for the DatePicker!

So you're saying makeXXX is not an ideal naming convention?

@thomasnield
Copy link
Collaborator Author

I think there's some interesting behaviors with CheckBoxTableCell and read-only properties, such as Bindings. I don't think it has to do with TornadoFX but JavaFX in general. It works find when I give it SimpleXXXProperty types, but it doesn't reflect values from read-only types. Therefore I wouldn't worry about CheckBoxTableCell.

@edvin
Copy link
Owner

edvin commented Apr 5, 2016

Sometimes it's nice to be able to show checkboxes that are not editable for boolean properties, I'll see if I can get it working! I little short on time today, but I'll fix it tomorrow :) Nice catch!

@edvin
Copy link
Owner

edvin commented Apr 5, 2016

Oh, and yeah, there is something with the naming that seems off to me. I'll discuss with a couple of colleagues tomorrow to try to get some ideas and report back. Hoping to land these features and maybe do a release before the weekend. Have a few other functions I'd like to get in as well :)

@thomasnield
Copy link
Collaborator Author

Awesome, I'll let you know if I have any ideas. Sorry I've been busy this past two days, I'll see if I can allocate some time to ponder this too.

edvin pushed a commit that referenced this issue Apr 13, 2016
@edvin
Copy link
Owner

edvin commented Apr 13, 2016

Just renamed the functions like we talked about :) I will close this now, the CheckBoxTableCell is really a JavaFX issue, so I won't use any more time on it now.

@edvin edvin closed this as completed Apr 13, 2016
@thomasnield
Copy link
Collaborator Author

Agreed. Awesome.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

2 participants