mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-07-04 03:11:43 +00:00
Initial checkin of unified hierarchy of WPILib 2015
This commit is contained in:
53
networktables/NetworkTableViewerFX/build.xml
Normal file
53
networktables/NetworkTableViewerFX/build.xml
Normal file
@@ -0,0 +1,53 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?><!-- You may freely edit this file. See commented blocks below for --><!-- some examples of how to customize the build. --><!-- (If you delete it and reopen the project it will be recreated.) --><!-- By default, only the Clean and Build commands use this build script. --><project name="JavaNetworkTableViewer" default="default" basedir="." xmlns:fx="javafx:com.sun.javafx.tools.ant">
|
||||
<description>Builds, tests, and runs the project JavaNetworkTableViewer.</description>
|
||||
<import file="nbproject/build-impl.xml"/>
|
||||
<!--
|
||||
|
||||
There exist several targets which are by default empty and which can be
|
||||
used for execution of your tasks. These targets are usually executed
|
||||
before and after some main targets. Those of them relevant for JavaFX project are:
|
||||
|
||||
-pre-init: called before initialization of project properties
|
||||
-post-init: called after initialization of project properties
|
||||
-pre-compile: called before javac compilation
|
||||
-post-compile: called after javac compilation
|
||||
-pre-compile-test: called before javac compilation of JUnit tests
|
||||
-post-compile-test: called after javac compilation of JUnit tests
|
||||
-pre-jfx-jar: called before FX SDK specific <fx:jar> task
|
||||
-post-jfx-jar: called after FX SDK specific <fx:jar> task
|
||||
-pre-jfx-deploy: called before FX SDK specific <fx:deploy> task
|
||||
-post-jfx-deploy: called after FX SDK specific <fx:deploy> task
|
||||
-pre-jfx-native: called just after -pre-jfx-deploy if <fx:deploy> runs in native packaging mode
|
||||
-post-jfx-native: called just after -post-jfx-deploy if <fx:deploy> runs in native packaging mode
|
||||
-post-clean: called after cleaning build products
|
||||
|
||||
(Targets beginning with '-' are not intended to be called on their own.)
|
||||
|
||||
Example of inserting a HTML postprocessor after javaFX SDK deployment:
|
||||
|
||||
<target name="-post-jfx-deploy">
|
||||
<basename property="jfx.deployment.base" file="${jfx.deployment.jar}" suffix=".jar"/>
|
||||
<property name="jfx.deployment.html" location="${jfx.deployment.dir}${file.separator}${jfx.deployment.base}.html"/>
|
||||
<custompostprocess>
|
||||
<fileset dir="${jfx.deployment.html}"/>
|
||||
</custompostprocess>
|
||||
</target>
|
||||
|
||||
Example of calling an Ant task from JavaFX SDK. Note that access to JavaFX SDK Ant tasks must be
|
||||
initialized; to ensure this is done add the dependence on -check-jfx-sdk-version target:
|
||||
|
||||
<target name="-post-jfx-jar" depends="-check-jfx-sdk-version">
|
||||
<echo message="Calling jar task from JavaFX SDK"/>
|
||||
<fx:jar ...>
|
||||
...
|
||||
</fx:jar>
|
||||
</target>
|
||||
|
||||
For more details about JavaFX SDK Ant tasks go to
|
||||
http://docs.oracle.com/javafx/2/deployment/jfxpub-deployment.htm
|
||||
|
||||
For list of available properties check the files
|
||||
nbproject/build-impl.xml and nbproject/jfx-impl.xml.
|
||||
|
||||
-->
|
||||
</project>
|
||||
@@ -0,0 +1,18 @@
|
||||
libs.CopyLibs.classpath=\
|
||||
${base}/CopyLibs/org-netbeans-modules-java-j2seproject-copylibstask.jar
|
||||
libs.CopyLibs.displayName=CopyLibs Task
|
||||
libs.CopyLibs.prop-version=1.0
|
||||
libs.junit.classpath=\
|
||||
${base}/junit/junit-3.8.2.jar
|
||||
libs.junit.displayName=JUnit 3.8.2
|
||||
libs.junit.javadoc=\
|
||||
${base}/junit/junit-3.8.2-api.zip
|
||||
libs.junit.prop-maven-dependencies=junit:junit:3.8.2:jar
|
||||
libs.junit_4.classpath=\
|
||||
${base}/junit_4/junit-4.10.jar
|
||||
libs.junit_4.displayName=JUnit 4.10
|
||||
libs.junit_4.javadoc=\
|
||||
${base}/junit_4/junit-4.10-javadoc.jar
|
||||
libs.junit_4.prop-maven-dependencies=junit:junit:4.10:jar
|
||||
libs.junit_4.src=\
|
||||
${base}/junit_4/junit-4.10-sources.jar
|
||||
BIN
networktables/NetworkTableViewerFX/lib/networktables-desktop.jar
Normal file
BIN
networktables/NetworkTableViewerFX/lib/networktables-desktop.jar
Normal file
Binary file not shown.
3
networktables/NetworkTableViewerFX/manifest.mf
Normal file
3
networktables/NetworkTableViewerFX/manifest.mf
Normal file
@@ -0,0 +1,3 @@
|
||||
Manifest-Version: 1.0
|
||||
X-COMMENT: Main-Class will be added automatically by build
|
||||
|
||||
1470
networktables/NetworkTableViewerFX/nbproject/build-impl.xml
Normal file
1470
networktables/NetworkTableViewerFX/nbproject/build-impl.xml
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,2 @@
|
||||
# Do not modify this property in this configuration. It can be re-generated.
|
||||
$label=Run as WebStart
|
||||
@@ -0,0 +1,2 @@
|
||||
# Do not modify this property in this configuration. It can be re-generated.
|
||||
$label=Run in Browser
|
||||
@@ -0,0 +1,8 @@
|
||||
build.xml.data.CRC32=c8c66866
|
||||
build.xml.script.CRC32=d06c8c20
|
||||
build.xml.stylesheet.CRC32=28e38971@1.56.1.46
|
||||
# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
|
||||
# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
|
||||
nbproject/build-impl.xml.data.CRC32=9e01e615
|
||||
nbproject/build-impl.xml.script.CRC32=31676db4
|
||||
nbproject/build-impl.xml.stylesheet.CRC32=c6d2a60f@1.56.1.46
|
||||
3213
networktables/NetworkTableViewerFX/nbproject/jfx-impl.xml
Normal file
3213
networktables/NetworkTableViewerFX/nbproject/jfx-impl.xml
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,4 @@
|
||||
# Do not modify this property in this configuration. It can be re-generated.
|
||||
$label=Run as WebStart
|
||||
# Do not modify this property in this configuration. It can be re-generated.
|
||||
javafx.run.as=webstart
|
||||
@@ -0,0 +1,4 @@
|
||||
# Do not modify this property in this configuration. It can be re-generated.
|
||||
$label=Run in Browser
|
||||
# Do not modify this property in this configuration. It can be re-generated.
|
||||
javafx.run.as=embedded
|
||||
@@ -0,0 +1,12 @@
|
||||
auxiliary.org-netbeans-modules-projectapi.issue214819_5f_fx_5f_enabled=true
|
||||
compile.on.save=true
|
||||
do.depend=false
|
||||
do.jar=true
|
||||
# No need to modify this property unless customizing JavaFX Ant task infrastructure
|
||||
endorsed.javafx.ant.classpath=.
|
||||
javac.debug=true
|
||||
javadoc.preview=true
|
||||
javafx.run.as=standalone
|
||||
javafx.run.inbrowser=<Default System Browser>
|
||||
javafx.run.inbrowser.path=C:\\Users\\Sam\\AppData\\Local\\Google\\Chrome\\Application\\chrome.exe
|
||||
user.properties.file=C:\\Users\\Sam\\AppData\\Roaming\\NetBeans\\7.3\\build.properties
|
||||
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project-private xmlns="http://www.netbeans.org/ns/project-private/1">
|
||||
<editor-bookmarks xmlns="http://www.netbeans.org/ns/editor-bookmarks/2" lastBookmarkId="0"/>
|
||||
</project-private>
|
||||
120
networktables/NetworkTableViewerFX/nbproject/project.properties
Normal file
120
networktables/NetworkTableViewerFX/nbproject/project.properties
Normal file
@@ -0,0 +1,120 @@
|
||||
annotation.processing.enabled=true
|
||||
annotation.processing.enabled.in.editor=false
|
||||
annotation.processing.processors.list=
|
||||
annotation.processing.run.all.processors=true
|
||||
annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output
|
||||
application.title=NetworkTableViewer
|
||||
application.vendor=
|
||||
build.classes.dir=${build.dir}/classes
|
||||
build.classes.excludes=**/*.java,**/*.form
|
||||
# This directory is removed when the project is cleaned:
|
||||
build.dir=build
|
||||
build.generated.dir=${build.dir}/generated
|
||||
build.generated.sources.dir=${build.dir}/generated-sources
|
||||
# Only compile against the classpath explicitly listed here:
|
||||
build.sysclasspath=ignore
|
||||
build.test.classes.dir=${build.dir}/test/classes
|
||||
build.test.results.dir=${build.dir}/test/results
|
||||
compile.on.save=true
|
||||
compile.on.save.unsupported.javafx=true
|
||||
# Uncomment to specify the preferred debugger connection transport:
|
||||
#debug.transport=dt_socket
|
||||
debug.classpath=\
|
||||
${run.classpath}
|
||||
debug.test.classpath=\
|
||||
${run.test.classpath}
|
||||
# This directory is removed when the project is cleaned:
|
||||
dist.dir=dist
|
||||
dist.jar=${dist.dir}/NetworkTableViewer.jar
|
||||
dist.javadoc.dir=${dist.dir}/javadoc
|
||||
endorsed.classpath=
|
||||
excludes=
|
||||
file.reference.networktables-desktop.jar=lib\\networktables-desktop.jar
|
||||
includes=**
|
||||
# Non-JavaFX jar file creation is deactivated in JavaFX 2.0+ projects
|
||||
jar.archive.disabled=true
|
||||
jar.compress=false
|
||||
javac.classpath=\
|
||||
${javafx.runtime}/lib/jfxrt.jar:\
|
||||
${javafx.runtime}/lib/deploy.jar:\
|
||||
${javafx.runtime}/lib/javaws.jar:\
|
||||
${javafx.runtime}/lib/plugin.jar:\
|
||||
${file.reference.networktables-desktop.jar}
|
||||
# Space-separated list of extra javac options
|
||||
javac.compilerargs=
|
||||
javac.deprecation=false
|
||||
javac.processorpath=\
|
||||
${javac.classpath}
|
||||
javac.source=1.7
|
||||
javac.target=1.7
|
||||
javac.test.classpath=\
|
||||
${javac.classpath}:\
|
||||
${build.classes.dir}:\
|
||||
${libs.junit_4.classpath}
|
||||
javac.test.processorpath=\
|
||||
${javac.test.classpath}
|
||||
javadoc.additionalparam=
|
||||
javadoc.author=true
|
||||
javadoc.encoding=${source.encoding}
|
||||
javadoc.noindex=false
|
||||
javadoc.nonavbar=false
|
||||
javadoc.notree=false
|
||||
javadoc.private=false
|
||||
javadoc.splitindex=true
|
||||
javadoc.use=true
|
||||
javadoc.version=false
|
||||
javadoc.windowtitle=
|
||||
javafx.binarycss=false
|
||||
javafx.deploy.adddesktopshortcut=false
|
||||
javafx.deploy.addstartmenushortcut=false
|
||||
javafx.deploy.allowoffline=true
|
||||
# If true, application update mode is set to 'background', if false, update mode is set to 'eager'
|
||||
javafx.deploy.backgroundupdate=false
|
||||
javafx.deploy.embedJNLP=true
|
||||
javafx.deploy.includeDT=true
|
||||
javafx.deploy.installpermanently=false
|
||||
javafx.deploy.permissionselevated=true
|
||||
# Set true to prevent creation of temporary copy of deployment artifacts before each run (disables concurrent runs)
|
||||
javafx.disable.concurrent.runs=false
|
||||
# Set true to enable multiple concurrent runs of the same WebStart or Run-in-Browser project
|
||||
javafx.enable.concurrent.external.runs=false
|
||||
# This is a JavaFX project
|
||||
javafx.enabled=true
|
||||
javafx.fallback.class=com.javafx.main.NoJavaFXFallback
|
||||
# Main class for JavaFX
|
||||
javafx.main.class=edu.wpi.first.tableviewer.NetworkTableViewer
|
||||
javafx.native.bundling.enabled=false
|
||||
javafx.native.bundling.type=all
|
||||
javafx.preloader.class=
|
||||
# This project does not use Preloader
|
||||
javafx.preloader.enabled=false
|
||||
javafx.preloader.jar.filename=
|
||||
javafx.preloader.jar.path=
|
||||
javafx.preloader.project.path=
|
||||
javafx.preloader.type=none
|
||||
# Set true for GlassFish only. Rebases manifest classpaths of JARs in lib dir. Not usable with signed JARs.
|
||||
javafx.rebase.libs=false
|
||||
javafx.run.height=600
|
||||
javafx.run.width=800
|
||||
javafx.runtime=${platforms.JDK_1.7.0_21.javafx.runtime.home}
|
||||
javafx.sdk=${platforms.JDK_1.7.0_21.javafx.sdk.home}
|
||||
javafx.signing.enabled=true
|
||||
javafx.signing.type=self
|
||||
# Pre-JavaFX 2.0 WebStart is deactivated in JavaFX 2.0+ projects
|
||||
jnlp.enabled=false
|
||||
# Main class for Java launcher
|
||||
main.class=com.javafx.main.Main
|
||||
manifest.file=manifest.mf
|
||||
meta.inf.dir=${src.dir}/META-INF
|
||||
mkdist.disabled=false
|
||||
platform.active=JDK_1.7.0_21
|
||||
run.classpath=\
|
||||
${dist.jar}:\
|
||||
${javac.classpath}
|
||||
run.test.classpath=\
|
||||
${javac.test.classpath}:\
|
||||
${build.test.classes.dir}
|
||||
source.encoding=UTF-8
|
||||
source.reference.networktables-desktop.jar=../java/dist/desktop-lib/networktables-desktop.src.zip
|
||||
src.dir=src
|
||||
test.src.dir=test
|
||||
35
networktables/NetworkTableViewerFX/nbproject/project.xml
Normal file
35
networktables/NetworkTableViewerFX/nbproject/project.xml
Normal file
@@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://www.netbeans.org/ns/project/1">
|
||||
<type>org.netbeans.modules.java.j2seproject</type>
|
||||
<configuration>
|
||||
<buildExtensions xmlns="http://www.netbeans.org/ns/ant-build-extender/1">
|
||||
<extension file="jfx-impl.xml" id="jfx">
|
||||
<dependency dependsOn="-check-javafx" target="-init-check"/>
|
||||
<dependency dependsOn="-jfx-copylibs" target="-post-jar"/>
|
||||
<dependency dependsOn="-rebase-libs" target="-post-jar"/>
|
||||
<dependency dependsOn="jfx-deployment" target="-post-jar"/>
|
||||
<dependency dependsOn="jar" target="debug"/>
|
||||
<dependency dependsOn="-jfx-copylibs" target="jar"/>
|
||||
<dependency dependsOn="-rebase-libs" target="jar"/>
|
||||
<dependency dependsOn="jar" target="profile"/>
|
||||
<dependency dependsOn="jar" target="run"/>
|
||||
</extension>
|
||||
</buildExtensions>
|
||||
<data xmlns="http://www.netbeans.org/ns/j2se-project/3">
|
||||
<name>NetworkTableViewer</name>
|
||||
<explicit-platform explicit-source-supported="true"/>
|
||||
<source-roots>
|
||||
<root id="src.dir"/>
|
||||
</source-roots>
|
||||
<test-roots>
|
||||
<root id="test.src.dir"/>
|
||||
</test-roots>
|
||||
</data>
|
||||
<libraries xmlns="http://www.netbeans.org/ns/ant-project-libraries/1">
|
||||
<definitions>.\lib\nblibraries.properties</definitions>
|
||||
</libraries>
|
||||
<spellchecker-wordlist xmlns="http://www.netbeans.org/ns/spellchecker-wordlist/1">
|
||||
<word>popup</word>
|
||||
</spellchecker-wordlist>
|
||||
</configuration>
|
||||
</project>
|
||||
BIN
networktables/NetworkTableViewerFX/src.zip
Normal file
BIN
networktables/NetworkTableViewerFX/src.zip
Normal file
Binary file not shown.
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* To change this template, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package edu.wpi.first.tableviewer;
|
||||
|
||||
import edu.wpi.first.tableviewer.treeview.ITableItem;
|
||||
import edu.wpi.first.tableviewer.treeview.TableBranch;
|
||||
import edu.wpi.first.tableviewer.treeview.TableLeaf;
|
||||
import edu.wpi.first.tableviewer.treeview.TableLeaf.EntryType;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sam
|
||||
*/
|
||||
public class EntryData {
|
||||
|
||||
public static final EntryData EMPTY = new EntryData(null, null, null);
|
||||
|
||||
private String key;
|
||||
private Object value;
|
||||
private EntryType type;
|
||||
|
||||
private boolean representsLeaf = true;
|
||||
private ITableItem tableItem;
|
||||
|
||||
public EntryData(String key, Object value, EntryType type) {
|
||||
this.key = key;
|
||||
this.value = value;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public EntryData(TableLeaf leaf) {
|
||||
this(leaf.getTableKey(), leaf.getTableValue(), leaf.getEntryType());
|
||||
tableItem = leaf;
|
||||
}
|
||||
|
||||
public EntryData(TableBranch branch) {
|
||||
key = branch.toString();
|
||||
representsLeaf = false;
|
||||
tableItem = branch;
|
||||
}
|
||||
|
||||
public boolean representsLeaf() {
|
||||
return representsLeaf;
|
||||
}
|
||||
|
||||
public void setTableItem(ITableItem item) {
|
||||
tableItem = item;
|
||||
}
|
||||
|
||||
public ITableItem getTableItem() {
|
||||
return tableItem;
|
||||
}
|
||||
|
||||
public void setKey(String key) {
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
public void setValue(Object value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public void setType(EntryType type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public Object getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public EntryType getType() {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* To change this template, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package edu.wpi.first.tableviewer;
|
||||
|
||||
import edu.wpi.first.tableviewer.popup.PreferencesDialog;
|
||||
import edu.wpi.first.tableviewer.tableview.TableTableView;
|
||||
import edu.wpi.first.wpilibj.networktables2.NetworkTableNode;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
import javafx.application.Application;
|
||||
import javafx.event.EventHandler;
|
||||
import javafx.fxml.FXMLLoader;
|
||||
import javafx.scene.Group;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.layout.BorderPane;
|
||||
import javafx.stage.Modality;
|
||||
import javafx.stage.Stage;
|
||||
import javafx.stage.StageStyle;
|
||||
import javafx.stage.WindowEvent;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sam
|
||||
*/
|
||||
public class NetworkTableViewer extends Application {
|
||||
|
||||
@Override
|
||||
public void start(Stage primaryStage) {
|
||||
FXMLLoader loader = new FXMLLoader(PreferencesDialog.class.getResource("PreferencesDialog.fxml"));
|
||||
Scene scene;
|
||||
PreferencesDialog controller = null;
|
||||
try {
|
||||
scene = new Scene(new Group());
|
||||
((Group)scene.getRoot()).getChildren().add((BorderPane)loader.load());
|
||||
controller = loader.getController();
|
||||
Stage s = new Stage();
|
||||
controller.setStage(s);
|
||||
s.setResizable(false);
|
||||
s.initStyle(StageStyle.UTILITY);
|
||||
s.initModality(Modality.WINDOW_MODAL);
|
||||
s.setScene(scene);
|
||||
s.setOnCloseRequest(new EventHandler<WindowEvent>() {
|
||||
@Override
|
||||
public void handle(WindowEvent t) {
|
||||
System.exit(0);
|
||||
}
|
||||
});
|
||||
s.showAndWait();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
NetworkTableNode node = controller.getNode();
|
||||
TableTableView view = new TableTableView(node);
|
||||
view.show();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* To change this template, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package edu.wpi.first.tableviewer.popup;
|
||||
|
||||
import edu.wpi.first.wpilibj.tables.ITable;
|
||||
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.event.EventHandler;
|
||||
import javafx.scene.Group;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.ComboBox;
|
||||
import javafx.scene.control.Control;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.TextField;
|
||||
import javafx.scene.layout.GridPane;
|
||||
import javafx.scene.paint.Color;
|
||||
import javafx.stage.Modality;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sam
|
||||
*/
|
||||
class AddValuePopup extends Popup {
|
||||
|
||||
public enum InputType {
|
||||
BOOLEAN, NUMBER, STRING, SUBTABLE
|
||||
}
|
||||
|
||||
private final InputType type;
|
||||
private final ITable table;
|
||||
|
||||
public AddValuePopup(ITable table, InputType type) {
|
||||
super();
|
||||
|
||||
this.table = table;
|
||||
this.type = type;
|
||||
|
||||
initModality(Modality.WINDOW_MODAL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showPopup() {
|
||||
initComponents();
|
||||
showAndWait();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initComponents() {
|
||||
initComponents(type);
|
||||
}
|
||||
|
||||
private void initComponents(final InputType type) {
|
||||
final Scene scene = new Scene(new Group());
|
||||
scene.setFill(Color.WHITESMOKE);
|
||||
scene.getStylesheets().add(
|
||||
"edu/wpi/first/tableviewer/stylesheets/ViewerStyleSheet.css");
|
||||
final Label messageLabel = new Label();
|
||||
final Label keyLabel = new Label("Key:");
|
||||
final Label valueLabel = new Label("Value:");
|
||||
final TextField keyField = new TextField();
|
||||
final Button confirm = new Button("Add");
|
||||
|
||||
keyField.setPromptText("Key");
|
||||
keyField.setPrefWidth(100);
|
||||
|
||||
final Control valueControl;
|
||||
ObservableList<String> booleanOptions = FXCollections.observableArrayList("True", "False");
|
||||
switch (type) {
|
||||
case BOOLEAN:
|
||||
messageLabel.setText("Add boolean");
|
||||
valueControl = new ComboBox(booleanOptions);
|
||||
((ComboBox) valueControl).getSelectionModel().select(0);
|
||||
confirm.setOnAction(new EventHandler<ActionEvent>() {
|
||||
@Override
|
||||
public void handle(ActionEvent t) {
|
||||
if (table.containsKey(keyField.getText())) {
|
||||
PopupFactory.showErrorDialog("Key already in use!");
|
||||
} else {
|
||||
table.putBoolean(keyField.getText(), ((ComboBox) valueControl).getSelectionModel().isSelected(0));
|
||||
close();
|
||||
}
|
||||
}
|
||||
});
|
||||
break;
|
||||
case NUMBER:
|
||||
messageLabel.setText("Add number");
|
||||
valueControl = new TextField();
|
||||
((TextField) valueControl).setPromptText("Number");
|
||||
confirm.setOnAction(new EventHandler<ActionEvent>() {
|
||||
@Override
|
||||
public void handle(ActionEvent t) {
|
||||
try {
|
||||
if (table.containsKey(keyField.getText())) {
|
||||
PopupFactory.showErrorDialog("Key already in use!");
|
||||
} else {
|
||||
table.putNumber(keyField.getText(), Double.parseDouble(((TextField) valueControl).getText()));
|
||||
close();
|
||||
}
|
||||
} catch (NumberFormatException ex) {
|
||||
PopupFactory.showErrorDialog("Invalid number!");
|
||||
}
|
||||
}
|
||||
});
|
||||
break;
|
||||
case STRING:
|
||||
messageLabel.setText("Add string");
|
||||
valueControl = new TextField();
|
||||
((TextField) valueControl).setPromptText("Text");
|
||||
confirm.setOnAction(new EventHandler<ActionEvent>() {
|
||||
@Override
|
||||
public void handle(ActionEvent t) {
|
||||
if (table.containsKey(keyField.getText())) {
|
||||
PopupFactory.showErrorDialog("Key already in use!");
|
||||
} else {
|
||||
table.putString(keyField.getText(), ((TextField) valueControl).getText());
|
||||
close();
|
||||
}
|
||||
}
|
||||
});
|
||||
break;
|
||||
case SUBTABLE:
|
||||
keyLabel.setText("Table name");
|
||||
keyField.setPromptText("Name");
|
||||
valueControl = null;
|
||||
confirm.setOnAction(new EventHandler<ActionEvent>() {
|
||||
@Override
|
||||
public void handle(ActionEvent t) {
|
||||
//TODO make a subtable show up without putting a value
|
||||
ITable i = table.getSubTable(keyField.getText());
|
||||
close();
|
||||
}
|
||||
});
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
final GridPane grid = new GridPane();
|
||||
grid.setHgap(10);
|
||||
grid.setVgap(5);
|
||||
grid.add(keyLabel, 1, 1);
|
||||
grid.add(keyField, 2, 1);
|
||||
if (type != InputType.SUBTABLE) {
|
||||
grid.add(valueLabel, 1, 2);
|
||||
grid.add(valueControl, 2, 2);
|
||||
valueControl.setPrefWidth(100);
|
||||
}
|
||||
grid.add(confirm, 2, 3);
|
||||
|
||||
((Group) scene.getRoot()).getChildren().add(grid);
|
||||
setScene(scene);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* To change this template, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package edu.wpi.first.tableviewer.popup;
|
||||
|
||||
import edu.wpi.first.tableviewer.treeview.TableLeaf;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.event.EventHandler;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.Group;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.ComboBox;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.TextField;
|
||||
import javafx.scene.layout.GridPane;
|
||||
import javafx.scene.paint.Color;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sam
|
||||
*/
|
||||
public class EditorPopup extends Popup {
|
||||
|
||||
private final Label inputLabel = new Label();
|
||||
private final TextField inputField = new TextField();
|
||||
private final ComboBox booleanBox = new ComboBox(FXCollections.observableArrayList("True", "False"));
|
||||
private final Button okayButton = new Button("OK"),
|
||||
cancelButton = new Button("Cancel");
|
||||
|
||||
private final String itemType;
|
||||
private final TableLeaf leaf;
|
||||
|
||||
public EditorPopup(TableLeaf leaf) {
|
||||
super("Edit Value", null, null);
|
||||
this.leaf = leaf;
|
||||
|
||||
String tableValue = leaf.getTableValue().toString();
|
||||
String tableKey = leaf.getTableKey();
|
||||
|
||||
inputLabel.setText(tableKey+":");
|
||||
|
||||
inputField.setText(tableValue);
|
||||
inputField.setPromptText("New value");
|
||||
inputField.setPrefWidth(100);
|
||||
|
||||
booleanBox.getSelectionModel().selectFirst();
|
||||
|
||||
itemType = leaf.getEntryType().toString();
|
||||
cancelButton.setOnAction(new EventHandler<ActionEvent>() {
|
||||
@Override
|
||||
public void handle(ActionEvent t) {
|
||||
close();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initComponents() {
|
||||
initComponents(itemType);
|
||||
}
|
||||
|
||||
private void initComponents(final String type) {
|
||||
final Scene scene = new Scene(new Group());
|
||||
scene.setFill(Color.WHITESMOKE);
|
||||
scene.getStylesheets().add(
|
||||
"edu/wpi/first/tableviewer/stylesheets/ViewerStyleSheet.css");
|
||||
|
||||
final GridPane grid = new GridPane();
|
||||
grid.setHgap(10);
|
||||
grid.setVgap(15);
|
||||
grid.setPadding(new Insets(5, 5, 5, 5));
|
||||
grid.setAlignment(Pos.CENTER);
|
||||
grid.add(inputLabel, 0, 1);
|
||||
|
||||
((Group) scene.getRoot()).getChildren().add(grid);
|
||||
setScene(scene);
|
||||
|
||||
switch (type.toLowerCase()) {
|
||||
case "boolean":
|
||||
grid.add(booleanBox, 1, 1);
|
||||
okayButton.setOnAction(new EventHandler<ActionEvent>() {
|
||||
@Override
|
||||
public void handle(ActionEvent t) {
|
||||
leaf.updateValue(booleanBox.getSelectionModel().isSelected(0));
|
||||
leaf.setExpanded(false); // refresh the leaf to updateValue the shown value
|
||||
leaf.setExpanded(true);
|
||||
close();
|
||||
}
|
||||
});
|
||||
break;
|
||||
case "number":
|
||||
grid.add(inputField, 1, 1);
|
||||
okayButton.setOnAction(new EventHandler<ActionEvent>() {
|
||||
@Override
|
||||
public void handle(ActionEvent t) {
|
||||
try {
|
||||
leaf.updateValue(Double.parseDouble(inputField.getText()));
|
||||
leaf.setExpanded(false); // refresh the leaf to updateValue the shown value
|
||||
leaf.setExpanded(true);
|
||||
close();
|
||||
} catch (NumberFormatException ex) {
|
||||
PopupFactory.showErrorDialog("Invalid number value!");
|
||||
}
|
||||
}
|
||||
});
|
||||
break;
|
||||
case "string":
|
||||
grid.add(inputField, 1, 1);
|
||||
okayButton.setOnAction(new EventHandler<ActionEvent>() {
|
||||
@Override
|
||||
public void handle(ActionEvent t) {
|
||||
leaf.updateValue(inputField.getText());
|
||||
leaf.setExpanded(false); // refresh the leaf to updateValue the shown value
|
||||
leaf.setExpanded(true);
|
||||
close();
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
grid.add(okayButton, 0, 2);
|
||||
grid.add(cancelButton, 1, 2);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import java.lang.*?>
|
||||
<?import java.util.*?>
|
||||
<?import javafx.geometry.*?>
|
||||
<?import javafx.scene.control.*?>
|
||||
<?import javafx.scene.image.*?>
|
||||
<?import javafx.scene.layout.*?>
|
||||
<?import javafx.scene.paint.*?>
|
||||
<?import javafx.scene.text.*?>
|
||||
|
||||
<GridPane hgap="14.0" maxHeight="+Infinity" maxWidth="+Infinity" minHeight="-Infinity" minWidth="-Infinity" vgap="20.0" xmlns:fx="http://javafx.com/fxml">
|
||||
<children>
|
||||
<ImageView fitHeight="60.0" fitWidth="60.0" pickOnBounds="true" preserveRatio="true" GridPane.columnIndex="0" GridPane.halignment="CENTER" GridPane.rowIndex="0" GridPane.valignment="TOP">
|
||||
<image>
|
||||
<!-- place holder -->
|
||||
</image>
|
||||
</ImageView>
|
||||
<VBox maxHeight="+Infinity" maxWidth="+Infinity" minHeight="-Infinity" prefWidth="400.0" spacing="7.0" GridPane.columnIndex="1" GridPane.rowIndex="0">
|
||||
<children>
|
||||
<Label fx:id="messageLabel" minHeight="15.999908447265625" prefHeight="17.0" prefWidth="400.0" text="Illegal number value!" textAlignment="LEFT" wrapText="false">
|
||||
<font>
|
||||
<Font name="System Bold" size="13.0" />
|
||||
</font>
|
||||
</Label>
|
||||
<Label fx:id="detailsLabel" text="[number] is not a valid value" textAlignment="LEFT" wrapText="false">
|
||||
<font>
|
||||
<Font size="12.0" />
|
||||
</font>
|
||||
</Label>
|
||||
</children>
|
||||
</VBox>
|
||||
<HBox maxHeight="-Infinity" maxWidth="+Infinity" minHeight="-Infinity" minWidth="-Infinity" GridPane.columnIndex="1" GridPane.rowIndex="1">
|
||||
<children>
|
||||
<HBox id="HBox" fx:id="actionParent" alignment="CENTER">
|
||||
<children>
|
||||
<Button fx:id="okButton" alignment="CENTER" contentDisplay="LEFT" minWidth="80.0" mnemonicParsing="false" text="OK" HBox.hgrow="NEVER">
|
||||
<HBox.margin>
|
||||
<Insets />
|
||||
</HBox.margin>
|
||||
</Button>
|
||||
</children>
|
||||
<HBox.margin>
|
||||
<Insets />
|
||||
</HBox.margin>
|
||||
</HBox>
|
||||
</children>
|
||||
</HBox>
|
||||
</children>
|
||||
<columnConstraints>
|
||||
<ColumnConstraints hgrow="NEVER" maxWidth="-Infinity" minWidth="-Infinity" />
|
||||
<ColumnConstraints halignment="CENTER" hgrow="ALWAYS" maxWidth="+Infinity" minWidth="-Infinity" />
|
||||
</columnConstraints>
|
||||
<padding>
|
||||
<Insets bottom="14.0" left="14.0" right="14.0" top="14.0" />
|
||||
</padding>
|
||||
<rowConstraints>
|
||||
<RowConstraints maxHeight="+Infinity" minHeight="-Infinity" valignment="CENTER" vgrow="ALWAYS" />
|
||||
<RowConstraints maxHeight="-Infinity" minHeight="-Infinity" vgrow="NEVER" />
|
||||
</rowConstraints>
|
||||
</GridPane>
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* To change this template, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package edu.wpi.first.tableviewer.popup;
|
||||
|
||||
/**
|
||||
* An interface for defining popups.
|
||||
* @author Sam
|
||||
* @see Popup
|
||||
* @see InputPopup
|
||||
*/
|
||||
public interface IPopup {
|
||||
|
||||
/**
|
||||
* An enumeration representing the type of popup this is.
|
||||
*/
|
||||
public enum Type {
|
||||
MESSAGE,
|
||||
WARNING,
|
||||
ERROR,
|
||||
INPUT
|
||||
}
|
||||
|
||||
/**
|
||||
* A method used to show this popup.
|
||||
*/
|
||||
public void showPopup();
|
||||
|
||||
/**
|
||||
* Initialize all components in this popup.
|
||||
*/
|
||||
public void initComponents();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* To change this template, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package edu.wpi.first.tableviewer.popup;
|
||||
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.event.EventHandler;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.Group;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.layout.VBox;
|
||||
import javafx.scene.paint.Color;
|
||||
import javafx.scene.text.TextAlignment;
|
||||
import javafx.stage.Modality;
|
||||
import javafx.stage.Stage;
|
||||
|
||||
/**
|
||||
* A generic popup. Call
|
||||
* {@link PopupFactory Popupfactory}.{@code showXXXXDialog()} to show a
|
||||
* predefined popup of a specific type.
|
||||
*
|
||||
* @see IPopup
|
||||
* @see InputPopup
|
||||
* @see PopupFactory
|
||||
* @author Sam
|
||||
*/
|
||||
class Popup extends Stage implements IPopup {
|
||||
|
||||
protected final String message;
|
||||
protected final Type type;
|
||||
|
||||
Popup() {
|
||||
this(null, null, Type.INPUT);
|
||||
}
|
||||
|
||||
Popup(String title, String message, Type type) {
|
||||
super();
|
||||
this.message = message;
|
||||
this.type = type;
|
||||
|
||||
setTitle(title);
|
||||
setWidth(200);
|
||||
setHeight(150);
|
||||
setResizable(false);
|
||||
|
||||
initModality(Modality.WINDOW_MODAL);
|
||||
}
|
||||
|
||||
private void initComponents(Type messageType) {
|
||||
final Scene scene = new Scene(new Group());
|
||||
scene.setFill(Color.WHITESMOKE);
|
||||
final Label messageText = new Label(message);
|
||||
final Button okayButton = new Button("Okay");
|
||||
final VBox box = new VBox();
|
||||
|
||||
messageText.setAlignment(Pos.CENTER);
|
||||
messageText.setTextAlignment(TextAlignment.CENTER);
|
||||
messageText.setWrapText(true);
|
||||
okayButton.setAlignment(Pos.CENTER);
|
||||
|
||||
okayButton.setOnAction(new EventHandler<ActionEvent>() {
|
||||
@Override
|
||||
public void handle(ActionEvent t) {
|
||||
close();
|
||||
}
|
||||
});
|
||||
|
||||
String messageClass = "";
|
||||
switch (messageType) {
|
||||
case MESSAGE:
|
||||
messageClass = "";
|
||||
box.setPadding(new Insets(10, 0, 0, 0));
|
||||
break;
|
||||
case WARNING:
|
||||
messageClass = "warning-";
|
||||
box.setPadding(new Insets(10, 0, 0, 0));
|
||||
break;
|
||||
case ERROR:
|
||||
messageClass = "error-";
|
||||
box.setPadding(new Insets(30, 0, 0, 0));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
scene.getStylesheets().add(
|
||||
"edu/wpi/first/tableviewer/stylesheets/PopupCSS.css");
|
||||
messageText.getStyleClass().add(messageClass + "message");
|
||||
|
||||
box.setPrefWidth(200);
|
||||
box.setSpacing(15);
|
||||
box.setAlignment(Pos.CENTER);
|
||||
|
||||
box.getChildren().addAll(messageText, okayButton);
|
||||
|
||||
((Group) scene.getRoot()).getChildren().addAll(box);
|
||||
|
||||
setScene(scene);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initComponents() {
|
||||
initComponents(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showPopup() {
|
||||
initComponents();
|
||||
showAndWait();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* To change this template, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package edu.wpi.first.tableviewer.popup;
|
||||
|
||||
import edu.wpi.first.tableviewer.popup.IPopup.Type;
|
||||
import edu.wpi.first.tableviewer.popup.AddValuePopup.InputType;
|
||||
import edu.wpi.first.tableviewer.treeview.TableLeaf;
|
||||
import edu.wpi.first.wpilibj.tables.ITable;
|
||||
|
||||
/**
|
||||
* A factory for creating and showing {@link Popup Popups} of a defined type.
|
||||
* @author Sam
|
||||
*/
|
||||
public final class PopupFactory {
|
||||
|
||||
public static void showMessageDialog(String title, String message) {
|
||||
IPopup popup = new Popup(title, message, Type.MESSAGE);
|
||||
popup.showPopup();
|
||||
}
|
||||
|
||||
public static void showMessageDialog(String message) {
|
||||
showMessageDialog("", message);
|
||||
}
|
||||
|
||||
public static void showWarningDialog(String title, String message) {
|
||||
IPopup popup = new Popup(title, message, Type.WARNING);
|
||||
popup.showPopup();
|
||||
}
|
||||
|
||||
public static void showWarningDialog(String message) {
|
||||
showWarningDialog("", message);
|
||||
}
|
||||
|
||||
public static void showErrorDialog(String title, String message) {
|
||||
IPopup popup = new Popup(title, message, Type.ERROR);
|
||||
popup.showPopup();
|
||||
}
|
||||
|
||||
public static void showErrorDialog(String message) {
|
||||
showErrorDialog("", message);
|
||||
}
|
||||
|
||||
public static void showAddBooleanDialog(ITable table) {
|
||||
IPopup popup = new AddValuePopup(table, InputType.BOOLEAN);
|
||||
popup.showPopup();
|
||||
}
|
||||
|
||||
public static void showAddNumberDialog(ITable table) {
|
||||
IPopup popup = new AddValuePopup(table, InputType.NUMBER);
|
||||
popup.showPopup();
|
||||
}
|
||||
|
||||
public static void showAddStringDialog(ITable table) {
|
||||
IPopup popup = new AddValuePopup(table, InputType.STRING);
|
||||
popup.showPopup();
|
||||
}
|
||||
|
||||
public static void showEditorDialog(TableLeaf leaf) {
|
||||
IPopup popup = new EditorPopup(leaf);
|
||||
popup.showPopup();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
/*
|
||||
* Empty Stylesheet file.
|
||||
*/
|
||||
|
||||
.mainFxmlClass {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import java.lang.*?>
|
||||
<?import java.net.*?>
|
||||
<?import java.util.*?>
|
||||
<?import javafx.geometry.*?>
|
||||
<?import javafx.scene.control.*?>
|
||||
<?import javafx.scene.layout.*?>
|
||||
<?import javafx.scene.paint.*?>
|
||||
<?import javafx.scene.text.*?>
|
||||
|
||||
<BorderPane id="BorderPane" disable="false" focusTraversable="false" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" padding="$x1" prefHeight="150.0" prefWidth="350.0" visible="true" xmlns:fx="http://javafx.com/fxml" fx:controller="edu.wpi.first.tableviewer.popup.PreferencesDialog">
|
||||
<bottom>
|
||||
<HBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="-1.0" prefWidth="350.0" spacing="10.0" BorderPane.alignment="CENTER">
|
||||
<children>
|
||||
<Button alignment="CENTER" contentDisplay="CENTER" maxWidth="-1.0" minHeight="-Infinity" minWidth="-Infinity" mnemonicParsing="false" onAction="#handleStartClientAction" prefHeight="25.0" prefWidth="100.0" text="Start Client" textAlignment="CENTER" HBox.hgrow="NEVER" />
|
||||
<Button contentDisplay="CENTER" minHeight="-Infinity" minWidth="-Infinity" mnemonicParsing="false" onAction="#handleStartServerAction" prefHeight="25.0" prefWidth="100.0" text="Start Server" textAlignment="CENTER" wrapText="false" HBox.hgrow="NEVER" />
|
||||
<Button cancelButton="true" contentDisplay="CENTER" minHeight="-Infinity" minWidth="-Infinity" mnemonicParsing="false" onAction="#handleCancelAction" prefHeight="25.0" prefWidth="100.0" text="Cancel" textAlignment="CENTER" HBox.hgrow="NEVER" />
|
||||
</children>
|
||||
<padding>
|
||||
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" fx:id="x1" />
|
||||
</padding>
|
||||
</HBox>
|
||||
</bottom>
|
||||
<right>
|
||||
<HBox alignment="CENTER" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="50.0" prefWidth="250.0" spacing="15.0" BorderPane.alignment="CENTER" BorderPane.margin="$x2">
|
||||
<children>
|
||||
<Label text="IP Address">
|
||||
<font>
|
||||
<Font name="System Bold" size="12.0" />
|
||||
</font>
|
||||
</Label>
|
||||
<TextField fx:id="addressField" alignment="CENTER_LEFT" onAction="#handleAddressEntered" prefWidth="-1.0" promptText="Host" text="127.0.0.1" />
|
||||
</children>
|
||||
<padding>
|
||||
<Insets bottom="15.0" left="15.0" right="15.0" top="15.0" fx:id="x2" />
|
||||
</padding>
|
||||
</HBox>
|
||||
</right>
|
||||
<stylesheets>
|
||||
<URL value="@PreferencesDialog.css" />
|
||||
</stylesheets>
|
||||
</BorderPane>
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* To change this template, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package edu.wpi.first.tableviewer.popup;
|
||||
|
||||
import edu.wpi.first.tableviewer.NetworkTableViewer;
|
||||
import edu.wpi.first.tableviewer.treeview.TableTreeView;
|
||||
|
||||
import edu.wpi.first.wpilibj.networktables2.NetworkTableNode;
|
||||
import edu.wpi.first.wpilibj.networktables2.client.NetworkTableClient;
|
||||
import edu.wpi.first.wpilibj.networktables2.server.NetworkTableServer;
|
||||
import edu.wpi.first.wpilibj.networktables2.stream.SocketStreams;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.prefs.Preferences;
|
||||
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.control.TextField;
|
||||
import javafx.stage.Stage;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sam
|
||||
*/
|
||||
public class PreferencesDialog {
|
||||
|
||||
public static final int DEFAULT_PORT = 1735;
|
||||
private final Preferences prefs = Preferences.userNodeForPackage(NetworkTableViewer.class);
|
||||
private String host = "localhost";
|
||||
private NetworkTableNode node;
|
||||
@FXML public TextField addressField;
|
||||
private Stage stage;
|
||||
|
||||
public NetworkTableNode getNode() {
|
||||
return node;
|
||||
}
|
||||
|
||||
public void setStage(Stage stage) {
|
||||
this.stage = stage;
|
||||
}
|
||||
|
||||
private void setServer(int port) throws IOException {
|
||||
this.node = new NetworkTableServer(SocketStreams.newStreamProvider(port));
|
||||
}
|
||||
|
||||
private void setClient(String host, int port) throws IOException {
|
||||
this.node = new NetworkTableClient(SocketStreams.newStreamFactory(host, port));
|
||||
((NetworkTableClient) node).reconnect();
|
||||
}
|
||||
|
||||
@FXML
|
||||
void handleStartClientAction(ActionEvent event) {
|
||||
try {
|
||||
setClient(host, DEFAULT_PORT);
|
||||
System.out.println("Connecting client to " + host + ":" + DEFAULT_PORT);
|
||||
handleStartAction();
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
|
||||
@FXML
|
||||
void handleStartServerAction(ActionEvent event) {
|
||||
try {
|
||||
setServer(DEFAULT_PORT);
|
||||
System.out.println("Starting server on port " + DEFAULT_PORT);
|
||||
handleStartAction();
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
|
||||
private void handleStartAction() {
|
||||
TableTreeView.setRootNode(node);
|
||||
stage.close();
|
||||
}
|
||||
|
||||
@FXML
|
||||
void handleAddressEntered(ActionEvent event) {
|
||||
host = addressField.getText();
|
||||
prefs.put("host", host);
|
||||
System.out.println("Set host to "+addressField.getText());
|
||||
}
|
||||
|
||||
@FXML
|
||||
void handleCancelAction(ActionEvent event) {
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
Document : ErrorMessageCSS
|
||||
Created on : Apr 23, 2013, 4:23:41 PM
|
||||
Author : Sam
|
||||
Description:
|
||||
Purpose of the stylesheet follows.
|
||||
*/
|
||||
|
||||
root {
|
||||
display: block;
|
||||
-fx-font-family: "Trebuchet MS";
|
||||
-fx-background: #000000;
|
||||
}
|
||||
|
||||
.message {
|
||||
-fx-text-fill: #000000; /* black */
|
||||
-fx-font-size: 14pt;
|
||||
-fx-font-weight: bold;
|
||||
}
|
||||
|
||||
.warning-message {
|
||||
-fx-text-fill: #FF5500; /* yellow */
|
||||
-fx-font-size: 14pt;
|
||||
-fx-font-weight: bold;
|
||||
}
|
||||
|
||||
/* Might need to change this*/
|
||||
.error-message {
|
||||
-fx-text-fill: #CC0000; /* red */
|
||||
-fx-font-size: 14pt;
|
||||
-fx-font-weight: bold;
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
|
||||
root {
|
||||
display: block;
|
||||
-fx-font-family: "Trebuchet MS";
|
||||
}
|
||||
|
||||
.button {
|
||||
-fx-text-fill: #111111;
|
||||
-fx-border-color: #000000;
|
||||
-fx-background-color: linear-gradient(#DDDDDD, #AAAAAA);
|
||||
-fx-border-radius: 5;
|
||||
-fx-padding: 3 6 6 6;
|
||||
}
|
||||
|
||||
.button:hover {
|
||||
-fx-background-color: linear-gradient(#FFFFFF, #CCCCCC);
|
||||
}
|
||||
|
||||
.button:focused {
|
||||
-fx-background-color: linear-gradient(#FFFFFF, #CCCCCC);
|
||||
}
|
||||
|
||||
.combo-box {
|
||||
-fx-text-fill: #111111;
|
||||
-fx-border-color: #000000;
|
||||
-fx-background-color: linear-gradient(#DDDDDD, #AAAAAA);
|
||||
-fx-border-radius: 5;
|
||||
}
|
||||
|
||||
.combo-box:focused {
|
||||
-fx-background-color: linear-gradient(#FFFFFF, #CCCCCC);
|
||||
}
|
||||
|
||||
.text-field {
|
||||
-fx-text-fill: #111111;
|
||||
-fx-prompt-text-fill: #444444;
|
||||
-fx-border-color: #000000;
|
||||
-fx-background-color: #CCCCCC;
|
||||
-fx-border-radius: 5;
|
||||
}
|
||||
|
||||
.text-field:focused {
|
||||
-fx-background-color: #EEEEEE;
|
||||
}
|
||||
|
||||
.scroll-bar .track{
|
||||
-fx-background-color: #EFEFEF;
|
||||
}
|
||||
|
||||
.scroll-bar .thumb {
|
||||
-fx-background-color: linear-gradient(to right, #AAAAAA, #CCCCCC);
|
||||
-fx-border-radius: 5;
|
||||
}
|
||||
|
||||
.tree-cell {
|
||||
-fx-font: 12pt "Trebuchet MS";
|
||||
-fx-text-fill: #111111;
|
||||
-fx-border-color: #DDDDFF;
|
||||
}
|
||||
|
||||
.tree-cell:selected:focused {
|
||||
-fx-background-color: #CCCCCC;
|
||||
}
|
||||
|
||||
.tree-cell:odd {
|
||||
-fx-background-color: rgb(240,240,255);
|
||||
}
|
||||
|
||||
.tree-cell:even {
|
||||
-fx-background-color: rgb(255,255,255);
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* To change this template, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package edu.wpi.first.tableviewer.tableview;
|
||||
|
||||
import edu.wpi.first.wpilibj.tables.ITable;
|
||||
import edu.wpi.first.wpilibj.tables.ITableListener;
|
||||
import javafx.beans.property.SimpleStringProperty;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sam
|
||||
*/
|
||||
public class EntryData implements ITableListener {
|
||||
|
||||
private final SimpleStringProperty
|
||||
key = new SimpleStringProperty(),
|
||||
value = new SimpleStringProperty(),
|
||||
type = new SimpleStringProperty();
|
||||
|
||||
public EntryData(ITable table, String key, Object value) {
|
||||
table.addTableListener(key, this, true);
|
||||
table.addSubTableListener(this);
|
||||
|
||||
setKey(key);
|
||||
setValue(value.toString());
|
||||
setType(typeFromValue(value));
|
||||
}
|
||||
|
||||
public void setKey(String key) {
|
||||
this.key.set(key);
|
||||
}
|
||||
|
||||
public void setValue(String value) {
|
||||
this.value.set(value);
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type.set(type);
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
return key.get();
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value.get();
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void valueChanged(ITable source, String key, Object value, boolean isNew) {
|
||||
System.out.println("Value of " + key + " changed to " + value);
|
||||
setKey(key);
|
||||
setValue(value.toString());
|
||||
setType(typeFromValue(value));
|
||||
}
|
||||
|
||||
private String typeFromValue(Object value) {
|
||||
String valueClassName = value.getClass().toString().substring(value.getClass().toString().lastIndexOf(".") + 1);
|
||||
switch (valueClassName.toLowerCase()) {
|
||||
case "boolean":
|
||||
return "BOOLEAN";
|
||||
case "double":
|
||||
return "NUMBER";
|
||||
case "string":
|
||||
return "STRING";
|
||||
default:
|
||||
return "UNSUPPORTED";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* To change this template, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package edu.wpi.first.tableviewer.tableview;
|
||||
|
||||
import edu.wpi.first.wpilibj.networktables.NetworkTableProvider;
|
||||
import edu.wpi.first.wpilibj.networktables2.NetworkTableNode;
|
||||
import edu.wpi.first.wpilibj.networktables2.server.NetworkTableServer;
|
||||
import edu.wpi.first.wpilibj.tables.ITable;
|
||||
import edu.wpi.first.wpilibj.tables.ITableListener;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ObservableMap;
|
||||
import javafx.event.EventHandler;
|
||||
import javafx.fxml.FXMLLoader;
|
||||
import javafx.scene.Group;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.control.TableView;
|
||||
import javafx.scene.layout.BorderPane;
|
||||
import javafx.stage.Stage;
|
||||
import javafx.stage.WindowEvent;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sam
|
||||
*/
|
||||
public class TableTableView extends Stage implements ITableListener {
|
||||
|
||||
private static ITable rootTable;
|
||||
private TableView tableView;
|
||||
private ObservableMap<String, EntryData> data = FXCollections.observableHashMap();
|
||||
|
||||
public static void setRootTableNode(NetworkTableNode node) {
|
||||
rootTable = new NetworkTableProvider(node).getRootTable();
|
||||
}
|
||||
|
||||
public TableTableView(NetworkTableNode node) {
|
||||
super();
|
||||
setRootTableNode(node);
|
||||
rootTable.addTableListener(this, true);
|
||||
rootTable.addSubTableListener(this);
|
||||
FXMLLoader loader = new FXMLLoader(getClass().getResource("TableViewFXML.fxml"));
|
||||
setTitle("Network Table Viewer " + ((node instanceof NetworkTableServer) ? "Server" : "Client"));
|
||||
Scene scene = new Scene(new Group());
|
||||
try {
|
||||
((Group) scene.getRoot()).getChildren().add((BorderPane) loader.load());
|
||||
setScene(scene);
|
||||
setOnCloseRequest(new EventHandler<WindowEvent>() {
|
||||
@Override
|
||||
public void handle(WindowEvent t) {
|
||||
System.exit(0);
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
setHeight(500);
|
||||
setWidth(380);
|
||||
setMinHeight(500);
|
||||
setMinWidth(380);
|
||||
setScene(scene);
|
||||
setOnCloseRequest(new EventHandler<WindowEvent>() {
|
||||
@Override
|
||||
public void handle(WindowEvent t) {
|
||||
// network tables keep the application running, so exit
|
||||
System.exit(0);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void valueChanged(ITable source, String key, Object value, boolean isNew) {
|
||||
data.put(key, new EntryData(source, key, value));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import java.lang.*?>
|
||||
<?import java.util.*?>
|
||||
<?import javafx.scene.control.*?>
|
||||
<?import javafx.scene.layout.*?>
|
||||
<?import javafx.scene.paint.*?>
|
||||
|
||||
<BorderPane id="BorderPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns:fx="http://javafx.com/fxml">
|
||||
<center>
|
||||
<TableView prefHeight="200.0" prefWidth="200.0">
|
||||
<columns>
|
||||
<TableColumn maxWidth="5000.0" minWidth="10.0" prefWidth="150.0" text="Key" fx:id="keyColumn" />
|
||||
<TableColumn editable="false" maxWidth="5000.0" minWidth="10.0" prefWidth="150.0" text="Value" visible="true" fx:id="valueColumn" />
|
||||
<TableColumn editable="false" maxWidth="5000.0" minWidth="10.0" prefWidth="150.0" text="Type" fx:id="typeColumn" />
|
||||
</columns>
|
||||
</TableView>
|
||||
</center>
|
||||
</BorderPane>
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* To change this template, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package edu.wpi.first.tableviewer.tableview;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.ResourceBundle;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.Initializable;
|
||||
import javafx.scene.control.TableColumn;
|
||||
import javafx.scene.control.TableView;
|
||||
import javafx.scene.control.cell.PropertyValueFactory;
|
||||
import javafx.stage.Stage;
|
||||
|
||||
/**
|
||||
* FXML Controller class
|
||||
*
|
||||
* @author Sam
|
||||
*/
|
||||
public class TableViewFXMLController implements Initializable {
|
||||
|
||||
@FXML
|
||||
public TableColumn keyColumn, valueColumn, typeColumn;
|
||||
@FXML
|
||||
public TableView tableView;
|
||||
|
||||
private Stage stage;
|
||||
|
||||
@Override
|
||||
public void initialize(URL url, ResourceBundle rb) {
|
||||
tableView.prefWidthProperty().bind(stage.widthProperty());
|
||||
keyColumn.prefWidthProperty().bind(stage.widthProperty().divide(3));
|
||||
valueColumn.prefWidthProperty().bind(stage.widthProperty().divide(3));
|
||||
typeColumn.prefWidthProperty().bind(stage.widthProperty().divide(3));
|
||||
|
||||
keyColumn.setCellValueFactory(new PropertyValueFactory<EntryData, String>("key"));
|
||||
valueColumn.setCellValueFactory(new PropertyValueFactory<EntryData, String>("value"));
|
||||
typeColumn.setCellValueFactory(new PropertyValueFactory<EntryData, String>("type"));
|
||||
}
|
||||
|
||||
public void setStage(Stage stage) {
|
||||
this.stage = stage;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* To change this template, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package edu.wpi.first.tableviewer.treeview;
|
||||
|
||||
import edu.wpi.first.tableviewer.EntryData;
|
||||
import javafx.scene.control.TreeItem;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sam
|
||||
*/
|
||||
public abstract class ITableItem extends TreeItem<EntryData> {
|
||||
|
||||
protected EntryData entryData;
|
||||
|
||||
public ITableItem() {
|
||||
super();
|
||||
}
|
||||
|
||||
public final EntryData getData() {
|
||||
return entryData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract boolean isLeaf();
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* To change this template, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package edu.wpi.first.tableviewer.treeview;
|
||||
|
||||
import edu.wpi.first.tableviewer.EntryData;
|
||||
import edu.wpi.first.wpilibj.networktables.NetworkTableProvider;
|
||||
import edu.wpi.first.wpilibj.networktables2.NetworkTableNode;
|
||||
import edu.wpi.first.wpilibj.tables.ITable;
|
||||
import edu.wpi.first.wpilibj.tables.ITableListener;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import javafx.beans.property.SimpleBooleanProperty;
|
||||
|
||||
import javafx.scene.control.TreeItem;
|
||||
|
||||
/**
|
||||
* A {@link TreeItem} responsible for displaying all the data within a certain
|
||||
* {@link ITable}. It can contain {@link TableLeaf TableLeaves} and other
|
||||
* {@code TableBranches} if there are subtables in the given {@code ITable}.
|
||||
*
|
||||
* @see TableLeaf
|
||||
* @author Sam
|
||||
*/
|
||||
public class TableBranch extends ITableItem implements ITableListener {
|
||||
|
||||
/**
|
||||
* Keeps track of values in the table.
|
||||
*/
|
||||
private HashMap<String, ITableItem> entries = new HashMap<>();
|
||||
private final ITable table;
|
||||
|
||||
/**
|
||||
* Constructs a TableBranch that displays data from the given ITable.
|
||||
*
|
||||
* @param table The ITable to show the data of.
|
||||
*/
|
||||
public TableBranch(final ITable table) {
|
||||
super();
|
||||
this.table = table;
|
||||
table.addTableListener(this, true);
|
||||
table.addSubTableListener(this);
|
||||
setExpanded(true);
|
||||
// expandedProperty().bind(new SimpleBooleanProperty(true)); //REMOVEME
|
||||
entryData = new EntryData(this);
|
||||
setValue(entryData);
|
||||
}
|
||||
|
||||
/**
|
||||
* This should only be called once, when making the root TableBranch.
|
||||
*
|
||||
* @param node The root node to listen to. Sibling or parent nodes, if they
|
||||
* exist, will be ignored.
|
||||
* @see TableBranch(ITable)
|
||||
*/
|
||||
public TableBranch(NetworkTableNode node) {
|
||||
this(new NetworkTableProvider(node).getRootTable());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void valueChanged(ITable source, String key, Object value, boolean isNew) {
|
||||
if (isNew && !entries.containsKey(key)) {
|
||||
if (value.toString().startsWith("NetworkTable: /")) {
|
||||
String tableName = value.toString().substring(source.toString().length() + 1);
|
||||
TableBranch branch = new TableBranch(source.getSubTable(tableName));
|
||||
this.getChildren().add(branch);
|
||||
entries.put(key, branch);
|
||||
} else {
|
||||
TableLeaf leaf = new TableLeaf(source, key, value);
|
||||
entries.put(key, leaf);
|
||||
this.getChildren().add(leaf);
|
||||
this.getChildren().removeAll(getLeaves());
|
||||
this.getChildren().addAll(sortLeaves(getLeaves()));
|
||||
}
|
||||
} else if (!isNew && entries.get(key) instanceof TableLeaf) {
|
||||
((TableLeaf) entries.get(key)).setTableValue(value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts the leaves in this branch alphabetically. Doesn't apply to
|
||||
* sub-branches.
|
||||
*
|
||||
* @return The sorted list of leaves.
|
||||
*/
|
||||
private List<TableLeaf> sortLeaves(List<TableLeaf> leaves) {
|
||||
List<TableLeaf> list = leaves.subList(0, leaves.size());
|
||||
Collections.sort(list);
|
||||
return list;
|
||||
}
|
||||
|
||||
private List<TableLeaf> getLeaves() {
|
||||
List<TableLeaf> leaves = new ArrayList<>();
|
||||
for (ITableItem item : entries.values()) {
|
||||
if (item instanceof TableLeaf) {
|
||||
leaves.add((TableLeaf) item);
|
||||
}
|
||||
}
|
||||
return leaves;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link ITable} associated with this branch.
|
||||
*/
|
||||
public ITable getTable() {
|
||||
return table;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLeaf() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return table.toString().substring(table.toString().lastIndexOf("/") + 1);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* To change this template, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package edu.wpi.first.tableviewer.treeview;
|
||||
|
||||
import edu.wpi.first.tableviewer.EntryData;
|
||||
import edu.wpi.first.tableviewer.popup.PopupFactory;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.event.EventHandler;
|
||||
import javafx.scene.control.ContextMenu;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.MenuItem;
|
||||
import javafx.scene.control.TreeCell;
|
||||
import javafx.scene.input.MouseEvent;
|
||||
import javafx.scene.layout.GridPane;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sam
|
||||
*/
|
||||
public class TableCell extends TreeCell<EntryData> {
|
||||
|
||||
private GridPane grid = new GridPane();
|
||||
private Label key = new Label(),
|
||||
value = new Label(),
|
||||
type = new Label();
|
||||
|
||||
// Very hackish but it almost works. Just don't collapse tables.
|
||||
// I blame JavaFX/Patrick for making me do this.
|
||||
private static List<TableCell> cells = new ArrayList<>();
|
||||
private static int currentCell = 0;
|
||||
private static int maxCells = 100;
|
||||
|
||||
private static HashMap<TableCell, EntryData> cellMap = new HashMap<>();
|
||||
|
||||
static {
|
||||
for (int i = 0; i < maxCells; i++) {
|
||||
cells.add(new TableCell());
|
||||
}
|
||||
}
|
||||
|
||||
public static TableCell getCell() {
|
||||
if (currentCell >= maxCells) {
|
||||
currentCell = 0;
|
||||
}
|
||||
return cells.get(currentCell++);
|
||||
}
|
||||
|
||||
private TableCell() {
|
||||
super();
|
||||
genGrid();
|
||||
this.setOnMouseClicked(new EventHandler<MouseEvent>() {
|
||||
@Override
|
||||
public void handle(MouseEvent t) {
|
||||
ITableItem selected = getItem().getTableItem();
|
||||
if (selected != null && selected instanceof TableLeaf && t.getClickCount() == 2) {
|
||||
TableLeaf leaf = (TableLeaf) selected;
|
||||
PopupFactory.showEditorDialog(leaf);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void genGrid() {
|
||||
key.setPrefWidth(50);
|
||||
value.setPrefWidth(125);
|
||||
type.setPrefWidth(75);
|
||||
grid.add(key, 0, 0);
|
||||
grid.add(value, 1, 0);
|
||||
grid.add(type, 2, 0);
|
||||
grid.setHgap(15);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateItem(EntryData data, boolean empty) {
|
||||
super.updateItem(data, empty);
|
||||
if (data != null && !empty) {
|
||||
cellMap.put(this, data);
|
||||
if (!data.representsLeaf()) {
|
||||
setContextMenu(getBranchMenu((TableBranch) data.getTableItem()));
|
||||
setText(data.getKey());
|
||||
setGraphic(null);
|
||||
} else {
|
||||
key.setText(data.getKey());
|
||||
value.setText(data.getValue().toString());
|
||||
type.setText(data.getType().toString());
|
||||
|
||||
setText(null);
|
||||
setGraphic(grid);
|
||||
setContextMenu(getLeafMenu((TableLeaf)data.getTableItem()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ContextMenu getBranchMenu(final TableBranch branch) {
|
||||
MenuItem addBoolean = new MenuItem("Add boolean");
|
||||
MenuItem addNumber = new MenuItem("Add number");
|
||||
MenuItem addString = new MenuItem("Add string");
|
||||
|
||||
addBoolean.setOnAction(new EventHandler<ActionEvent>() {
|
||||
@Override
|
||||
public void handle(ActionEvent t) {
|
||||
PopupFactory.showAddBooleanDialog(branch.getTable());
|
||||
}
|
||||
});
|
||||
|
||||
addNumber.setOnAction(new EventHandler<ActionEvent>() {
|
||||
@Override
|
||||
public void handle(ActionEvent t) {
|
||||
PopupFactory.showAddNumberDialog(branch.getTable());
|
||||
}
|
||||
});
|
||||
|
||||
addString.setOnAction(new EventHandler<ActionEvent>() {
|
||||
@Override
|
||||
public void handle(ActionEvent t) {
|
||||
PopupFactory.showAddStringDialog(branch.getTable());
|
||||
}
|
||||
});
|
||||
|
||||
ContextMenu cMenu = new ContextMenu();
|
||||
cMenu.getItems().addAll(addBoolean, addNumber, addString);
|
||||
return cMenu;
|
||||
}
|
||||
|
||||
private ContextMenu getLeafMenu(final TableLeaf leaf) {
|
||||
MenuItem edit = new MenuItem("Edit");
|
||||
|
||||
edit.setOnAction(new EventHandler<ActionEvent>() {
|
||||
@Override
|
||||
public void handle(ActionEvent t) {
|
||||
PopupFactory.showEditorDialog(leaf);
|
||||
}
|
||||
});
|
||||
|
||||
ContextMenu cMenu = new ContextMenu(edit);
|
||||
return cMenu;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* To change this template, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package edu.wpi.first.tableviewer.treeview;
|
||||
|
||||
import edu.wpi.first.tableviewer.EntryData;
|
||||
import edu.wpi.first.wpilibj.tables.ITable;
|
||||
import javafx.application.Platform;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sam
|
||||
*/
|
||||
public class TableLeaf extends ITableItem implements Comparable {
|
||||
|
||||
private final ITable table;
|
||||
|
||||
@Override
|
||||
public int compareTo(Object o) {
|
||||
return this.getTableKey().toLowerCase().compareTo(((TableLeaf)o).getTableKey().toLowerCase());
|
||||
}
|
||||
|
||||
public enum EntryType {
|
||||
BOOLEAN, NUMBER, STRING, UNSUPPORTED
|
||||
}
|
||||
|
||||
public TableLeaf(ITable table, String key, Object value) {
|
||||
super();
|
||||
this.table = table;
|
||||
entryData = new EntryData(key, value, getTypeFromValue(value));
|
||||
entryData.setTableItem(this);
|
||||
setValue(entryData);
|
||||
}
|
||||
|
||||
public ITable getTable() {
|
||||
return table;
|
||||
}
|
||||
|
||||
public String getTableKey() {
|
||||
return entryData.getKey();
|
||||
}
|
||||
|
||||
public Object getTableValue() {
|
||||
return entryData.getValue();
|
||||
}
|
||||
|
||||
public EntryType getEntryType() {
|
||||
return entryData.getType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the display value of this TableLeaf to a new value.
|
||||
*
|
||||
* @param newValue The new value of this leaf.
|
||||
*/
|
||||
public void setTableValue(Object newValue) {
|
||||
entryData.setValue(newValue);
|
||||
entryData.setType(getTypeFromValue(newValue));
|
||||
Platform.runLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
setValue(EntryData.EMPTY);
|
||||
setValue(entryData);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private EntryType getTypeFromValue(Object value) {
|
||||
String valueClassName = value.getClass().toString().substring(value.getClass().toString().lastIndexOf(".") + 1);
|
||||
switch (valueClassName.toLowerCase()) {
|
||||
case "boolean":
|
||||
return EntryType.BOOLEAN;
|
||||
case "double":
|
||||
return EntryType.NUMBER;
|
||||
case "string":
|
||||
return EntryType.STRING;
|
||||
default:
|
||||
return EntryType.UNSUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the value in this TableLeaf's ITable and updates the displayed
|
||||
* value.
|
||||
*
|
||||
* @param newValue The new value of this entry.
|
||||
* @see #setTableValue
|
||||
*/
|
||||
public void updateValue(Object newValue) {
|
||||
// table.putValue(entryData.getKey(), newValue);
|
||||
setTableValue(newValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLeaf() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* To change this template, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package edu.wpi.first.tableviewer.treeview;
|
||||
|
||||
import edu.wpi.first.wpilibj.networktables2.NetworkTableNode;
|
||||
import edu.wpi.first.wpilibj.networktables2.server.NetworkTableServer;
|
||||
|
||||
import javafx.event.EventHandler;
|
||||
import javafx.scene.Group;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.control.TreeCell;
|
||||
import javafx.scene.control.TreeItem;
|
||||
import javafx.scene.control.TreeView;
|
||||
import javafx.stage.Stage;
|
||||
import javafx.stage.WindowEvent;
|
||||
import javafx.util.Callback;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sam
|
||||
*/
|
||||
public class TableTreeView extends Stage {
|
||||
|
||||
private TreeView<ITableItem> tree;
|
||||
private static NetworkTableNode rootTableNode;
|
||||
|
||||
public static void setRootNode(NetworkTableNode node) {
|
||||
rootTableNode = node;
|
||||
}
|
||||
|
||||
public TableTreeView(NetworkTableNode node) {
|
||||
Scene scene = initTree();
|
||||
setTitle("Network Table Viewer " + ((node instanceof NetworkTableServer) ? "Server" : "Client"));
|
||||
setRootNode(node);
|
||||
setHeight(500);
|
||||
setWidth(380);
|
||||
setMinHeight(500);
|
||||
setMinWidth(380);
|
||||
setScene(scene);
|
||||
setOnCloseRequest(new EventHandler<WindowEvent>() {
|
||||
@Override
|
||||
public void handle(WindowEvent t) {
|
||||
// network tables keep the application running, so exit
|
||||
System.exit(0);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private Scene initTree() {
|
||||
Scene scene = new Scene(new Group());
|
||||
|
||||
scene.getStylesheets().add("edu/wpi/first/tableviewer/stylesheets/ViewerStyleSheet.css");
|
||||
TableBranch rootBranch = new TableBranch(rootTableNode); // create a branch to show the entire contents of the node
|
||||
|
||||
TreeItem root = new TreeItem<>();
|
||||
root.getChildren().add(rootBranch);
|
||||
|
||||
tree = new TreeView(root);
|
||||
tree.setShowRoot(false);
|
||||
tree.prefWidthProperty().bind(scene.widthProperty());
|
||||
tree.prefHeightProperty().bind(scene.heightProperty());
|
||||
|
||||
tree.setCellFactory(new Callback<TreeView<ITableItem>, TreeCell<ITableItem>>() {
|
||||
@Override
|
||||
public TreeCell call(TreeView<ITableItem> p) {
|
||||
return TableCell.getCell();
|
||||
}
|
||||
});
|
||||
|
||||
((Group) scene.getRoot()).getChildren().add(tree);
|
||||
return scene;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user