Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

General housekeeping cleanup #306

Merged
merged 10 commits into from
Dec 21, 2017
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,22 @@
import java.util.Optional;
import java.util.stream.Collectors;

import javafx.beans.property.BooleanProperty;
import javafx.beans.property.Property;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.value.ObservableValue;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Control;
import javafx.scene.control.TextField;
import javafx.util.StringConverter;

/**
* A property sheet for a specific widget.
* A version of {@link PropertySheet} that has better support for editing numbers (using {@link NumberField} and
* {@link IntegerField} for doubles and integers, respectively) and booleans (using {@link ToggleSwitch}), and themes.
*/
public class WidgetPropertySheet extends PropertySheet {
public class ExtendedPropertySheet extends PropertySheet {

/**
* Creates an empty property sheet.
*/
public WidgetPropertySheet() {
public ExtendedPropertySheet() {
super();
setModeSwitcherVisible(false);
setSearchBoxVisible(false);
Expand Down Expand Up @@ -60,7 +58,7 @@ public PropertyEditor<?> call(Item item) {
/**
* Creates a new property sheet containing items for each of the given properties.
*/
public WidgetPropertySheet(Collection<Property<?>> properties) {
public ExtendedPropertySheet(Collection<Property<?>> properties) {
this();
getItems().setAll(properties.stream()
.map(property -> new PropertyItem<>(property))
Expand All @@ -75,18 +73,34 @@ public static class PropertyItem<T> implements Item {
private final Property<T> property;
private final String name;

/**
* Creates a new PropertyItem from the given property. The name of the item is generated from the name of the
* property by converting from <tt>camelCase</tt> to a natural-language <tt>Sentence case</tt> text. For example,
* a property with the name <tt>"fooBarBaz"</tt> will generate a name of <tt>"Foo bar baz"</tt>. If a name other
* than the property name is desired, or if generating a sentence-case string would be inappropriate, use
* {@link #PropertyItem(Property, String)} that lets the name be directly specified.
*
* @param property the property the item represents
*/
public PropertyItem(Property<T> property) {
this.property = property;
this.name = camelCaseToSentence(property.getName());
this(property, camelCaseToSentence(property.getName()));
}

/**
* Creates a new PropertyItem from the given property and with the given name.
*
* @param property the property the item represents
* @param name the name of the item to display in the property sheet
*/
public PropertyItem(Property<T> property, String name) {
this.property = property;
this.name = name;
}

/**
* Converts a "CamelCase" string to "Sentence case".
* Converts a "CamelCase" string to "Sentence case". This is implemented by replacing every upper-case character
* (except for the first one, if it is upper-case) with a space character (<tt>' '</tt>) and that character's
* lower-case representation.
*/
private static String camelCaseToSentence(String camel) {
if (camel == null) {
Expand Down Expand Up @@ -115,7 +129,7 @@ public Class<?> getType() {

@Override
public String getCategory() {
return "Widget Properties";
return "Ungrouped";
}

@Override
Expand All @@ -133,8 +147,8 @@ public Object getValue() {
return property.getValue();
}

@SuppressWarnings("unchecked")
@Override
@SuppressWarnings("unchecked")
public void setValue(Object value) {
if (getType().isInstance(value)) {
property.setValue((T) value);
Expand All @@ -152,22 +166,11 @@ public Optional<ObservableValue<?>> getObservableValue() {

}


private abstract static class AbstractEditor<T, C extends Control> extends AbstractPropertyEditor<T, C> {

protected final BooleanProperty wait = new SimpleBooleanProperty(this, "wait", false);

public AbstractEditor(Item property, C control) {
super(property, control);
}

}

/**
* A property editor for numbers. We use this instead of the one bundled with ControlsFX because
* their implementation is bad.
*/
private static class NumberPropertyEditor extends AbstractEditor<Double, NumberField> {
private static class NumberPropertyEditor extends AbstractPropertyEditor<Double, NumberField> {

NumberPropertyEditor(Item item) {
super(item, new NumberField(((Number) item.getValue()).doubleValue()));
Expand All @@ -185,7 +188,7 @@ public void setValue(Double value) {

}

private static class IntegerPropertyEditor extends AbstractEditor<Integer, IntegerField> {
private static class IntegerPropertyEditor extends AbstractPropertyEditor<Integer, IntegerField> {

IntegerPropertyEditor(Item item) {
super(item, new IntegerField((Integer) item.getValue()));
Expand All @@ -203,7 +206,7 @@ public void setValue(Integer value) {
}


private static class TextPropertyEditor extends AbstractEditor<String, TextField> {
private static class TextPropertyEditor extends AbstractPropertyEditor<String, TextField> {

TextPropertyEditor(Item item) {
super(item, new TextField((String) item.getValue()));
Expand All @@ -221,7 +224,7 @@ public void setValue(String value) {

}

private static class ToggleSwitchEditor extends AbstractEditor<Boolean, ToggleSwitch> {
private static class ToggleSwitchEditor extends AbstractPropertyEditor<Boolean, ToggleSwitch> {

ToggleSwitchEditor(Item item) {
super(item, new ToggleSwitch());
Expand Down
102 changes: 93 additions & 9 deletions api/src/main/java/edu/wpi/first/shuffleboard/api/data/DataTypes.java
Original file line number Diff line number Diff line change
@@ -1,16 +1,25 @@
package edu.wpi.first.shuffleboard.api.data;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.primitives.Primitives;

import edu.wpi.first.shuffleboard.api.data.types.AllType;
import edu.wpi.first.shuffleboard.api.data.types.BooleanArrayType;
import edu.wpi.first.shuffleboard.api.data.types.BooleanType;
import edu.wpi.first.shuffleboard.api.data.types.MapType;
import edu.wpi.first.shuffleboard.api.data.types.NoneType;
import edu.wpi.first.shuffleboard.api.data.types.NumberArrayType;
import edu.wpi.first.shuffleboard.api.data.types.NumberType;
import edu.wpi.first.shuffleboard.api.data.types.RawByteType;
import edu.wpi.first.shuffleboard.api.data.types.StringArrayType;
import edu.wpi.first.shuffleboard.api.data.types.StringType;
import edu.wpi.first.shuffleboard.api.data.types.UnknownType;
import edu.wpi.first.shuffleboard.api.util.Registry;
import edu.wpi.first.shuffleboard.api.util.TestUtils;
import edu.wpi.first.shuffleboard.api.util.TypeUtils;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableSet;
import com.google.common.primitives.Primitives;

import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
Expand All @@ -24,17 +33,91 @@

import static java.util.Objects.requireNonNull;

/**
* Registry of data types in shuffleboard. This class also provides data types for various "wildcard" types, as well as
* types for primitive and arrays of primitive data. These types are always registered and may not be unregistered.
*/
public class DataTypes extends Registry<DataType> {

// TODO replace with DI eg Guice
private static DataTypes defaultInstance = null;

// Catchall or wildcard types
Copy link
Member

@JLLeitschuh JLLeitschuh Nov 22, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Catch-all?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's just an alternate spelling.

/**
* Represents the type of "null" or non-present data. Differs from {@link UnknownType} in that <i>no</i> data is
* present for this type, while data <i>is</i> present but of an unknown type for the latter.
*/
public static final DataType None = new NoneType();

/**
* Represents the type of <i>all</i> data; a widget that can accept this data type can accept data of <i>any</i>
* type.
*/
public static final DataType All = new AllType();

/**
* Represents an "unknown" data type; that is, data is present, but the type could not be determined.
*/
public static final DataType Unknown = new UnknownType();

public static final ComplexDataType<MapData> Map = new MapType();

// Primitive types
/**
* The type corresponding to <i>boolean</i> data.
*/
public static final DataType<Boolean> Boolean = new BooleanType();

/**
* The type corresponding to a boolean array (<tt>boolean[]</tt>).
*/
public static final DataType<boolean[]> BooleanArray = new BooleanArrayType();

/**
* The type corresponding to <i>numeric</i> data.
*/
public static final DataType<Number> Number = new NumberType();

/**
* The type corresponding to an array of numeric data (<tt>double[]</tt>). Note that number arrays <i>must</i> be
* implemented as <tt>double[]</tt> in order to be represented by this type.
*/
public static final DataType<double[]> NumberArray = new NumberArrayType();

/**
* The type corresponding to text data.
*/
public static final DataType<String> String = new StringType();

/**
* The type corresponding to an array of strings (<tt>String[]</tt>).
*/
public static final DataType<String[]> StringArray = new StringArrayType();

/**
* The type corresponding to an array of raw bytes (<tt>byte[]</tt>).
*/
public static final DataType<byte[]> ByteArray = new RawByteType();

/**
* The default data types. None of these may be unregistered.
*/
private static final ImmutableCollection<DataType<?>> defaultTypes = ImmutableSet.of(
// catchall
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

catch-all

None,
All,
Unknown,
Map,
// primitives
Boolean,
BooleanArray,
Number,
NumberArray,
String,
StringArray,
ByteArray
);

private final Map<String, DataType> dataTypes = new TreeMap<>();

private final Map<Class, Optional<DataType>> typeCache = new HashMap<>();
Expand All @@ -52,14 +135,11 @@ public static DataTypes getDefault() {
}

/**
* Creates a new data type registry. The registry will initially contain {@link #None}, {@link #All},
* {@link #Unknown}, and {@link #Map}, none of why may be unregistered.
* Creates a new data type registry. The registry will initially contain the default data types, none of which may be
* unregistered.
*/
public DataTypes() {
register(None);
register(All);
register(Unknown);
register(Map);
registerAll(defaultTypes);
}

/**
Expand Down Expand Up @@ -91,6 +171,10 @@ public void register(DataType dataType) {

@Override
public void unregister(DataType dataType) {
requireNonNull(dataType, "dataType");
if (defaultTypes.contains(dataType)) {
throw new IllegalArgumentException("A default data type cannot be unregistered: '" + dataType + "'");
}
dataTypes.remove(dataType.getName());
typeCache.remove(dataType.getJavaClass());
removeItem(dataType);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package edu.wpi.first.shuffleboard.plugin.base.data.types;
package edu.wpi.first.shuffleboard.api.data.types;

import edu.wpi.first.shuffleboard.api.data.SimpleDataType;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package edu.wpi.first.shuffleboard.plugin.base.data.types;
package edu.wpi.first.shuffleboard.api.data.types;

import edu.wpi.first.shuffleboard.api.data.SimpleDataType;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package edu.wpi.first.shuffleboard.plugin.base.data.types;
package edu.wpi.first.shuffleboard.api.data.types;

import edu.wpi.first.shuffleboard.api.data.SimpleDataType;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package edu.wpi.first.shuffleboard.plugin.base.data.types;
package edu.wpi.first.shuffleboard.api.data.types;

import edu.wpi.first.shuffleboard.api.data.SimpleDataType;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package edu.wpi.first.shuffleboard.plugin.base.data.types;
package edu.wpi.first.shuffleboard.api.data.types;

import edu.wpi.first.shuffleboard.api.data.SimpleDataType;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package edu.wpi.first.shuffleboard.plugin.base.data.types;
package edu.wpi.first.shuffleboard.api.data.types;

import edu.wpi.first.shuffleboard.api.data.SimpleDataType;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package edu.wpi.first.shuffleboard.plugin.base.data.types;
package edu.wpi.first.shuffleboard.api.data.types;

import edu.wpi.first.shuffleboard.api.data.SimpleDataType;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
package edu.wpi.first.shuffleboard.plugin.base.recording.serialization;
package edu.wpi.first.shuffleboard.api.sources.recording.serialization;

import edu.wpi.first.shuffleboard.api.data.DataTypes;
import edu.wpi.first.shuffleboard.api.sources.recording.Serialization;
import edu.wpi.first.shuffleboard.api.sources.recording.serialization.TypeAdapter;
import edu.wpi.first.shuffleboard.plugin.base.data.types.BooleanArrayType;

public class BooleanArrayAdapter extends TypeAdapter<boolean[]> {

public BooleanArrayAdapter() {
super(new BooleanArrayType());
super(DataTypes.BooleanArray);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
package edu.wpi.first.shuffleboard.plugin.base.recording.serialization;

import com.google.common.primitives.Bytes;
package edu.wpi.first.shuffleboard.api.sources.recording.serialization;

import edu.wpi.first.shuffleboard.api.data.DataTypes;
import edu.wpi.first.shuffleboard.api.sources.recording.Serialization;
import edu.wpi.first.shuffleboard.api.sources.recording.serialization.TypeAdapter;
import edu.wpi.first.shuffleboard.plugin.base.data.types.RawByteType;

import com.google.common.primitives.Bytes;

import static edu.wpi.first.shuffleboard.api.sources.recording.Serialization.SIZE_OF_INT;

public class ByteArrayAdapter extends TypeAdapter<byte[]> {

public ByteArrayAdapter() {
super(new RawByteType());
super(DataTypes.ByteArray);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
package edu.wpi.first.shuffleboard.plugin.base.recording.serialization;
package edu.wpi.first.shuffleboard.api.sources.recording.serialization;

import edu.wpi.first.shuffleboard.api.data.DataTypes;
import edu.wpi.first.shuffleboard.api.sources.recording.Serialization;
import edu.wpi.first.shuffleboard.api.sources.recording.serialization.TypeAdapter;
import edu.wpi.first.shuffleboard.plugin.base.data.types.NumberArrayType;

public class NumberArrayAdapter extends TypeAdapter<double[]> {

public NumberArrayAdapter() {
super(new NumberArrayType());
super(DataTypes.NumberArray);
}

@Override
Expand Down
Loading