Skip to content

Commit

Permalink
fix null pointer exception caused by using javafx VirtualFlow (#15, #17
Browse files Browse the repository at this point in the history
…, #18)

Former-commit-id: be46786
  • Loading branch information
andrescv committed Feb 16, 2019
1 parent c6f8a9d commit a17c922
Show file tree
Hide file tree
Showing 2 changed files with 124 additions and 17 deletions.
100 changes: 100 additions & 0 deletions V-Sim/src/vsim/gui/components/TableViewExt.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*
Copyright (C) 2018-2019 Andres Castellanos
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>
*/

package vsim.gui.components;

import java.util.LinkedHashSet;
import javafx.scene.control.TableRow;
import javafx.scene.control.TableView;
import javafx.util.Callback;


/**
* Extra calls for TableView which would have been nice to see in JavaFx TableView
*/
public class TableViewExt<T> {

/** table view to extend */
private final TableView<T> tableView;
/** table view rows */
private LinkedHashSet<TableRow<T>> rows = new LinkedHashSet<>();
/** table view first index */
private int firstIndex;
/** table view last index */
private int lastIndex;

/**
* Initializes a new table view extension.
*
* @param tableView table view to extend
*/
public TableViewExt(TableView<T> tableView) {
this.tableView = tableView;
// Callback to monitor row creation and to identify visible screen rows
final Callback<TableView<T>, TableRow<T>> rf = tableView.getRowFactory();
// modify row factory
final Callback<TableView<T>, TableRow<T>> modifiedRowFactory = param -> {
TableRow<T> r = rf != null ? rf.call(param) : new TableRow<T>();
// Save row, this implementation relies on JaxaFX re-using TableRow efficiently
rows.add(r);
return r;
};
tableView.setRowFactory(modifiedRowFactory);
}

/** recomputes table view first visible and last visible cells indexes */
private void recomputeVisibleIndexes() {
firstIndex = -1;
lastIndex = -1;
// Work out which of the rows are visible
double tblViewHeight = tableView.getHeight();
double headerHeight = tableView.lookup(".column-header-background").getBoundsInLocal().getHeight();
double viewPortHeight = tblViewHeight - headerHeight;
for (TableRow<T> r : rows) {
double minY = r.getBoundsInParent().getMinY();
double maxY = r.getBoundsInParent().getMaxY();
boolean hidden = (maxY < 0) || (minY > viewPortHeight);
if (!hidden) {
if (firstIndex < 0 || r.getIndex() < firstIndex)
firstIndex = r.getIndex();
if (lastIndex < 0 || r.getIndex() > lastIndex)
lastIndex = r.getIndex();
}
}
}

/**
* Find the first row in the table view which is visible on the display.
*
* @return -1 if none visible or the index of the first visible row (wholly or fully)
*/
public int getFirstVisibleIndex() {
recomputeVisibleIndexes();
return firstIndex;
}

/**
* Find the last row in the table view which is visible on the display.
*
* @return -1 if none visible or the index of the last visible row (wholly or fully)
*/
public int getLastVisibleIndex() {
recomputeVisibleIndexes();
return lastIndex;
}

}
41 changes: 24 additions & 17 deletions V-Sim/src/vsim/gui/controllers/SimulatorController.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,14 @@
import javafx.util.Callback;
import com.jfoenix.controls.JFXButton;
import com.jfoenix.controls.JFXTabPane;
import com.sun.javafx.scene.control.skin.TableViewSkin;
import com.sun.javafx.scene.control.skin.VirtualFlow;
import vsim.Globals;
import vsim.Settings;
import vsim.assembler.Assembler;
import vsim.gui.components.BooleanCell;
import vsim.gui.components.InfoCell;
import vsim.gui.components.MemoryEditingCell;
import vsim.gui.components.RegisterEditingCell;
import vsim.gui.components.TableViewExt;
import vsim.gui.utils.Icons;
import vsim.gui.utils.SymbolInfo;
import vsim.linker.InfoStatement;
Expand Down Expand Up @@ -168,6 +167,13 @@ public class SimulatorController {
/** current go task */
private Task<Boolean> goTask;

/** text table extension */
private TableViewExt<?> txtExt;
/** rvi table extension */
private TableViewExt<?> rviExt;
/** rvf table extension */
private TableViewExt<?> rvfExt;

/**
* Initialize simulator controller.
*
Expand Down Expand Up @@ -574,11 +580,10 @@ private void initText() {
this.textTable.refresh();
int pc = (Globals.regfile.getProgramCounter() - MemorySegments.TEXT_SEGMENT_BEGIN) / Data.WORD_LENGTH;
int row = Math.min(pc, this.textTable.getItems().size() - 1);
VirtualFlow<?> vflow = (VirtualFlow<?>) ((TableViewSkin<?>) this.textTable.getSkin()).getChildren().get(1);
if (vflow != null) {
int first = vflow.getFirstVisibleCell().getIndex();
int last = vflow.getLastVisibleCell().getIndex();
if (row >= last || row <= first)
if (this.txtExt != null) {
int first = this.txtExt.getFirstVisibleIndex();
int last = this.txtExt.getLastVisibleIndex();
if (first != -1 && last != -1 && (row >= last || row <= first))
this.textTable.scrollTo(row);
}
});
Expand Down Expand Up @@ -621,6 +626,8 @@ public void updateItem(InfoStatement stmt, boolean isEmpty) {
TableColumn<InfoStatement, Boolean> p) -> new BooleanCell();
this.txtBkptCol.setCellValueFactory(new PropertyValueFactory<InfoStatement, Boolean>("breakpoint"));
this.txtBkptCol.setCellFactory(boolCellFactory);
// load table extension
this.txtExt = new TableViewExt<>(this.textTable);
}

/** This method initializes the memory table. */
Expand Down Expand Up @@ -722,11 +729,10 @@ private void initRegFiles() {
if (!Status.RUNNING.get()) {
Platform.runLater(() -> {
hardware.getSelectionModel().select(rviTab);
VirtualFlow<?> vflow = (VirtualFlow<?>) ((TableViewSkin<?>) this.rviTable.getSkin()).getChildren().get(1);
if (vflow != null) {
int first = vflow.getFirstVisibleCell().getIndex();
int last = vflow.getLastVisibleCell().getIndex();
if (number >= last || number <= first)
if (this.rviExt != null) {
int first = this.rviExt.getFirstVisibleIndex();
int last = this.rviExt.getLastVisibleIndex();
if (first != -1 && last != -1 && (number >= last || number <= first))
rviTable.scrollTo(number);
rviTable.refresh();
}
Expand All @@ -749,6 +755,7 @@ public void updateItem(Register reg, boolean isEmpty) {
}
};
});
this.rviExt = new TableViewExt<>(this.rviTable);
this.rviTable.setItems(rviList);
// RVF table
this.rvfMnemonic.setCellValueFactory(new PropertyValueFactory<Register, String>("mnemonic"));
Expand All @@ -767,11 +774,10 @@ public void updateItem(Register reg, boolean isEmpty) {
if (!Status.RUNNING.get()) {
Platform.runLater(() -> {
hardware.getSelectionModel().select(rvfTab);
VirtualFlow<?> vflow = (VirtualFlow<?>) ((TableViewSkin<?>) this.rvfTable.getSkin()).getChildren().get(1);
if (vflow != null) {
int first = vflow.getFirstVisibleCell().getIndex();
int last = vflow.getLastVisibleCell().getIndex();
if (number >= last || number <= first)
if (this.rvfExt != null) {
int first = this.rvfExt.getFirstVisibleIndex();
int last = this.rvfExt.getLastVisibleIndex();
if (first != -1 && last != -1 && (number >= last || number <= first))
rvfTable.scrollTo(number);
rvfTable.refresh();
}
Expand All @@ -793,6 +799,7 @@ public void updateItem(Register reg, boolean isEmpty) {
}
};
});
this.rvfExt = new TableViewExt<>(this.rvfTable);
this.rvfTable.setItems(rvfList);
// set rvi table context menu
MenuItem hex = new MenuItem("Hex Display Mode");
Expand Down

0 comments on commit a17c922

Please sign in to comment.