How to automatically sort JavaFX tableview when adding a new row to it? - sorting

I have a TableView that shows program names (String) and times (LocalDateTime). When I open it, it is automatically sorted by time.
But when I click to the new button, add a new item to the row, the new item is the first item in the table. After clicking on the column name of time, it still doesn't put it in its place (it's either the first or last item).
I'm trying to write here all the codes relating to it.
programTable = new TableView<>();
programTable.setEditable(true);
ObservableList<Program> programs = weddingScriptController.getPrograms();
SortedList<Program> sortedData = new SortedList<>(programs);
sortedData.comparatorProperty().bind(programTable.comparatorProperty());
Button newButton = new Button("Új");
newButton.setOnAction(e -> {
ProgramCreateWindow window = new ProgramCreateWindow();
window.display(programs);
});
//other stuff
TableColumn<Program, String> nameCol = new TableColumn<>("Név");
nameCol.setCellValueFactory(new PropertyValueFactory<Program, String>("name"));
TableColumn<Program, LocalDateTime> defaultTimeCol = new TableColumn<>("Idő");
defaultTimeCol.setCellValueFactory(new PropertyValueFactory<Program, LocalDateTime>("defaultTime"));
defaultTimeCol.setCellFactory(TextFieldTableCell.forTableColumn(new ProgramDateTimeStringConverter()));
defaultTimeCol.setSortType(TableColumn.SortType.ASCENDING);
//other stuff
programTable.setItems(sortedData);
programTable.getSortOrder().add(defaultTimeCol);
programTable.sort();
I've tried deleting that sorted list, and using the programs list, but it doesn't solve the problem.
programTable.setItems(programs);
I've also tried giving that function the sortedList, but it gets error when trying to add the new item to it.
window.display(sortedList);
What should I use to make this new item sorting work?
I know that it may be a dumb question, but I don't get it how it works, what am I doing right, what am I doing wrong.

Related

How to set focus and open the grid cell editor of a newly inserted row in vaadin 8 grid?

Is it possible to focus and open the grid cell editor directly after inserting a new row? I have searched a while but I didn't find anything helpful.
I am inserting rows with
grid.setItems(theListWithItems);
After the insertion the editor is closed and I have to double click the row to edit it.
I want the editor opens immediately after inserting the new row.
Any help is highly apreciated.
Thanks in advance
Since Vaadin 8.2 you can now call editRow() on the grid editor
grid.getEditor().editRow(theListWithItems.size() -1);
to open the editor for the newly inserted item. But there is no focus on it, you still have to click (once, no doubleclick) into the column that you wish to edit.
However, the row is not focused only by calling editRow(). To focus a certain column I have not found a simple function for it, but I have found a way to do it nevertheless:
Each column needs a defined Editor-Component (i.e. a TextField). For the column that you want to be initially focused, define a memberfield so it can be accessed when you add a new item. Then - after you call editRow() - you can call focus() on that Editor-Component.
private TextField fooEditorTextField = new TextField();
private createGrid(){
// create your grid as usual
// define Editor components for grid
grid.getEditor().setEnabled(true);
grid.getColumn("Foo").setEditorComponent(fooEditorTextField );
grid.getColumn("Bar").setEditorComponent(new TextField());
}
private void addNewItemToGrid(){
MyItem newItem = new MyItem();
theListWithItems.add(newItem);
grid.setItems(theListWithItems);
// open editor for new Item
grid.getEditor().editRow(theListWithItems.size() -1);
// Focus the "Foo" column in the editor of the new item
fooEditorTextField.focus();
}

RCP e4 programmatically create Toolbar with HandledToolItem in Part

I'm having a problem regarding the HandledToolItem in my MToolbar.
When pressing a button the application should create a new Part with a Toolbar and one HandledToolItem. The problem is that the HandledToolItem is always greyed out and I don't know why yet.
final MPart mPart = modelService.createModelElement(MPart.class);
mPart.setLabel("Test");
mPart.setElementId("newid");
mPart.setContributionURI("bundleclass://something");
mPart.setCloseable(true);
// create Toolbar
final MToolBar mBar = modelService.createModelElement(MToolBar.class);
mPart.setToolbar(mBar);
// create HanledToolItem
final MHandledToolItem mItem = modelService.createModelElement(MHandledToolItem.class);
mBar.getChildren().add(mItem);
// create Handle and Command
final MHandler toolHandler = modelService.createModelElement(MHandler.class);
final MCommand toolCommand = modelService.createModelElement(MCommand.class);
toolCommand.setElementId("dsadsadsa");
toolHandler.setCommand(toolCommand);
toolHandler.setContributionURI("bundleclass://something");
mItem.setIconURI("platform:/plugin/RCPCAN/icons/icon_con_scroll_lock.png");
mItem.setTooltip("Lock Table Scrollbar");
mItem.setCommand(toolCommand);
mItem.setEnabled(true);
// show part
partService.showPart(mPart, PartState.ACTIVATE);
You must add any handler you create to the list of handlers for the application or component:
#Inject
MApplication app;
...
app.getHandlers().add(handler);
Similarly commands must be added to the getCommands list.
Note: It is much easier to use a 'PartDescriptor' in your Application.e4xmi containing the design of the part. You can then just call
partService.showPart("part descriptor id", PartState.ACTIVATE);
without needing to create anything in your code.
If you want to create multiple copies of a part use:
MPart newPart = partService.createPart("part descriptor id");
partService.showPart(newPart, PartState.ACTIVATE);

Constant values in DataGridVIew

I have a DataGridView with 3 columns.
I need the first two columns remain constant, These columns always have to be the same and the user will not be able to enter a different value to these.
The values for the two first columns of the DGV are in textBox1 and textBox2.
I need that when the user is going to add a new row in the DGV the first two columns automatically fill with these constant values and set the focus to the third column.
Thanks in advance
If you don't want the user to edit the first two columns, just set their ReadOnly property to true:
this.dataGridView1.Columns[0].ReadOnly = true;
As for your other criteria, first set the following property to limit control of when a new row is added (ex. click of a button):
this.dataGridView1.AllowUserToAddRows = false;
Then create your own method to add new rows when needed:
private void AddNewRow()
{
DataGridViewRow row = new DataGridViewRow();
row.CreateCells(this.dataGridView1);
row.Cells[0].Value = this.textBox1.Text;
row.Cells[1].Value = this.textBox2.Text;
this.dataGridView1.CurrentCell = row.Cells[2];
this.dataGridView1.BeginEdit(true);
}
Technically, you could do this when AllowUserToAddRows == true by handling the DataGridView.RowsAdded event and the above code slightly modified, but you'll get an annoying behavior where as soon as you enter one character into the new row, 3rd column, another new row is added and the editing cell loses focus (probably before you actually entered anything useful).

Programatically updating underlying data in Slickgrid

I have 6 textboxes at the top of the screen that update an entire column(one textbox per column) based on any changes. I was selecting the columns based on their class (.l#). Here is the code (issues to follow):
function UpdateField() {
var ctrl = this;
var id = parseInt(ctrl.id.replace("item", ""), 10) - 1;
var bound = [".l1", ".l7", ".l8", ".l9"];
var fields = $(bound[id]);
for (var i = 0; i < fields.length; i++)
{
fields[i].innerHTML = $(ctrl).val();
}
};
which is bound to the keyup event for the text areas. Issues are:
1) initially fields.length was -1 as I didn't want to put data in the "add new
row" section at the bottom. However, when running it, I noticed the
final "real" record wasn't being populated. Also, when stepping through, I
noticed that the "new row" field was before the "last row" field.
2) when doing it this way, it is purely superficial: if I double click the field,
the real data hasn't been changed.
so in the grand scheme of things, I know that I was doing it wrong. I'm assuming it involves updating the data and then forcing a render, but I'm not certain.
Figured out how to do it. Modified the original code this way:
function UpdateField() {
var ctrl = this;
var id = parseInt(ctrl.id.replace("item", ""), 10) - 1;
var bound = ['title1', 'title2', 'title3', 'title4'];
var field = bound[id];
for (var i = 0; i < dataView.getLength(); i++)
{
var item = dataView.getItem(i);
item[field] = $(ctrl).val();
dataView.updateItem(i, item);
}
grid.invalidate();
};
I have 6 textboxes (item1-item6) that "bind" to fields in the sense that if I change data in a textbox, it updates all of the rows and any new rows added also have this data.
Parts where the two issues can be explained this way:
1) to work around that, though still it would be a presentational fix and not a real updating of the underlying data, one could force it to ignore if it had the active class attached. Extra work, and not in the "real" direction one is going for (masking the field).
2) It was pretty obvious with the original implementation (though it was all I could figure out via Chrome Dev Tools that I could modify at the time) that it was merely updating a div's content and not actually interacting with the data underneath. Would look nice, and perhaps one could just pull data from the item1-item6 boxes in place of the column if it is submitted, but if someone attempts to modify the cell, they'll be looking at the real data again.

Blackberry invalidate field not causing a repaint

I'm writing a Blackberry app. I have a custom list field where I can select an item in the list which pushes the edit screen onto the stack. I edit the item and save, and when I pop that screen off so I am back on my list screen, I want to view the update I just made reflected in the list. I have done this on other screens which just had LabelFields and it worked fine. However, with the list screen, calling invalidate() seems to do nothing. I know the value has saved correctly through print lines, and I see the paint() method in the listfield is getting called. But the only way I can get the list field to update is to delete it from the screen and re-add it. That seems wrong. What am I doing wrong?
public class ListTasksScreen extends MainScreen{
private TaskList tasks;
private CustomListField taskListField;
public ListTasksScreen (TaskList tasks){
super();
this.tasks = tasks;
Vector incompleteTasks = tasks.getIncompleteTasks();
taskListField = new CustomListField(incompleteTasks, tasks);
add(taskListField);
}
public void updateTaskList(TaskList t)
{
Vector incompleteTasks = t.getIncompleteTasks();
taskListField= new TaskListField(incompletetTasks, t);
//I just want to call taskListField.invalidate() here.
//the only thing that seems to work is deleting taskListField
//and re-adding
this.delete(taskListField);
add(taskListField);
}
}
Is there a typo in your code above? in the updateTaskList method you do:
taskListField= new TaskListField(incompletetTasks, t);
should it be:
taskListField= new CustomListField(incompletetTasks, t);
Anyway, I think the reason you are having problems is because when you update your task list you are actually creating a new CustomListField object. When you first do add(taskListField) you are passing a reference to the field to the screen, so it has its own reference. When you call taskListField= new CustomListField(incompletetTasks, t); you are only updating your own reference, not the one in the screen. So if you call invalidate the screen will repaint using the original reference, which must be using references to the original versions of incompleteTasks and tasks too.
The reason it works the other way is because you are actually removing the old reference and adding the new one, so the screen now knows of the updated data.
What you should do is add a method to your CustomListField that allows you to update the task list object. Then when you call that method on the existing reference to taskListField and then call invalidate, your paint method should now use the new values when it calls drawListRow in the callback.
to add item and update list:
add item to array/vector of list items
perform insert new row (listField.insert(listField.getSize());)

Resources