adds documentation written before update
This commit is contained in:
commit
f0ecd6f495
@ -36,9 +36,7 @@ public class Appearance {
|
|||||||
* @param shine shine of the appearance, will be clamped between 0 and 1
|
* @param shine shine of the appearance, will be clamped between 0 and 1
|
||||||
*/
|
*/
|
||||||
public Appearance(final Color paint, final double shine) {
|
public Appearance(final Color paint, final double shine) {
|
||||||
this.paint = paint;
|
this(paint,shine,null);
|
||||||
this.shine = MathUtil.clamp(shine, 0, 1);
|
|
||||||
this.texture = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -4,12 +4,17 @@ import net.sf.openrocket.startup.Application;
|
|||||||
import net.sf.openrocket.util.Coordinate;
|
import net.sf.openrocket.util.Coordinate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A texture that can be applied by an Appearance. This class is immutable.
|
* A texture that can be applied by an Appearance. an object of this class is immutable.
|
||||||
*
|
*
|
||||||
* @author Bill Kuker <bkuker@billkuker.com>
|
* @author Bill Kuker <bkuker@billkuker.com>
|
||||||
*/
|
*/
|
||||||
public class Decal {
|
public class Decal {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* enum to flag what happens on edge in a decal
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
public static enum EdgeMode {
|
public static enum EdgeMode {
|
||||||
REPEAT("TextureWrap.Repeat"), MIRROR("TextureWrap.Mirror"), CLAMP("TextureWrap.Clamp"), STICKER("TextureWrap.Sticker");
|
REPEAT("TextureWrap.Repeat"), MIRROR("TextureWrap.Mirror"), CLAMP("TextureWrap.Clamp"), STICKER("TextureWrap.Sticker");
|
||||||
private final String transName;
|
private final String transName;
|
||||||
@ -29,6 +34,16 @@ public class Decal {
|
|||||||
private final DecalImage image;
|
private final DecalImage image;
|
||||||
private final EdgeMode mode;
|
private final EdgeMode mode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds a new decal with the given itens
|
||||||
|
*
|
||||||
|
* @param offset The offset of the decal, in coordinate obejct format
|
||||||
|
* @param center The position of the center of the decal, in coordinate object format
|
||||||
|
* @param scale The scale of the decal, in coordinate obejct format
|
||||||
|
* @param rotation Rotation of the decal, in radians
|
||||||
|
* @param image The image itself
|
||||||
|
* @param mode The description of Edge behaviour
|
||||||
|
*/
|
||||||
public Decal(final Coordinate offset, final Coordinate center, final Coordinate scale, final double rotation,
|
public Decal(final Coordinate offset, final Coordinate center, final Coordinate scale, final double rotation,
|
||||||
final DecalImage image, final EdgeMode mode) {
|
final DecalImage image, final EdgeMode mode) {
|
||||||
this.offset = offset;
|
this.offset = offset;
|
||||||
@ -39,26 +54,56 @@ public class Decal {
|
|||||||
this.mode = mode;
|
this.mode = mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns the offset, in coordinates object format
|
||||||
|
*
|
||||||
|
* @return offset coordinates of the decal
|
||||||
|
*/
|
||||||
public Coordinate getOffset() {
|
public Coordinate getOffset() {
|
||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* return the center, in coordinates object format
|
||||||
|
*
|
||||||
|
* @return The center coordinates of the decal
|
||||||
|
*/
|
||||||
public Coordinate getCenter() {
|
public Coordinate getCenter() {
|
||||||
return center;
|
return center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* return the scaling of the decal, in coordinate format
|
||||||
|
*
|
||||||
|
* @return the scale coordinates of the decal
|
||||||
|
*/
|
||||||
public Coordinate getScale() {
|
public Coordinate getScale() {
|
||||||
return scale;
|
return scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns the rotation of the decal, in radians
|
||||||
|
*
|
||||||
|
* @return the rotation of the decal, in radians
|
||||||
|
*/
|
||||||
public double getRotation() {
|
public double getRotation() {
|
||||||
return rotation;
|
return rotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* return the edge behaviour of the decal
|
||||||
|
*
|
||||||
|
* @return the edge behaviour of the decal
|
||||||
|
*/
|
||||||
public EdgeMode getEdgeMode() {
|
public EdgeMode getEdgeMode() {
|
||||||
return mode;
|
return mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns the image of the decal itself
|
||||||
|
*
|
||||||
|
* @return the image of the decal itself
|
||||||
|
*/
|
||||||
public DecalImage getImage() {
|
public DecalImage getImage() {
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
@ -7,13 +7,37 @@ import java.io.InputStream;
|
|||||||
|
|
||||||
import net.sf.openrocket.util.ChangeSource;
|
import net.sf.openrocket.util.ChangeSource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface to handle image files for declas
|
||||||
|
*
|
||||||
|
*/
|
||||||
public interface DecalImage extends ChangeSource, Comparable<DecalImage> {
|
public interface DecalImage extends ChangeSource, Comparable<DecalImage> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns the name of the file path of the image
|
||||||
|
* @return name of file path
|
||||||
|
*/
|
||||||
public String getName();
|
public String getName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gets the Stream of bytes representing the image itself
|
||||||
|
*
|
||||||
|
* @return the Stream of bytes representing the image
|
||||||
|
* @throws FileNotFoundException
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
public InputStream getBytes() throws FileNotFoundException, IOException;
|
public InputStream getBytes() throws FileNotFoundException, IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* exports an image into the File
|
||||||
|
* @param file The File handler object
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
public void exportImage(File file) throws IOException;
|
public void exportImage(File file) throws IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wake up call to listeners
|
||||||
|
* @param source The source of the wake up call
|
||||||
|
*/
|
||||||
public void fireChangeEvent(Object source);
|
public void fireChangeEvent(Object source);
|
||||||
}
|
}
|
||||||
|
@ -23,8 +23,22 @@ import net.sf.openrocket.rocketcomponent.TubeFinSet;
|
|||||||
import net.sf.openrocket.util.Color;
|
import net.sf.openrocket.util.Color;
|
||||||
import net.sf.openrocket.util.Coordinate;
|
import net.sf.openrocket.util.Coordinate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Class defining the default images of the application
|
||||||
|
*
|
||||||
|
*/
|
||||||
public class DefaultAppearance {
|
public class DefaultAppearance {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns a simple appearance with the image in the path with
|
||||||
|
* default color
|
||||||
|
* no shining
|
||||||
|
* no offset, origin center and scale 1
|
||||||
|
*
|
||||||
|
* @param resource the path file to the resource
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
private static Appearance simple(String resource) {
|
private static Appearance simple(String resource) {
|
||||||
return new Appearance(
|
return new Appearance(
|
||||||
new Color(1, 1, 1),
|
new Color(1, 1, 1),
|
||||||
@ -37,6 +51,14 @@ public class DefaultAppearance {
|
|||||||
new ResourceDecalImage(resource), EdgeMode.REPEAT));
|
new ResourceDecalImage(resource), EdgeMode.REPEAT));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns the image with custom color and shine
|
||||||
|
*
|
||||||
|
* @param base base color for the image
|
||||||
|
* @param shine the custom shine property
|
||||||
|
* @param resource the file path to the image
|
||||||
|
* @return The appearance with custom color and shine.
|
||||||
|
*/
|
||||||
private static Appearance simpleAlpha(Color base, float shine, String resource) {
|
private static Appearance simpleAlpha(Color base, float shine, String resource) {
|
||||||
return new Appearance(
|
return new Appearance(
|
||||||
base,
|
base,
|
||||||
@ -69,6 +91,12 @@ public class DefaultAppearance {
|
|||||||
|
|
||||||
private static HashMap<Color, Appearance> plastics = new HashMap<Color, Appearance>();
|
private static HashMap<Color, Appearance> plastics = new HashMap<Color, Appearance>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gets the appearance correspondent to the plastic with the given color
|
||||||
|
* also caches the plastics
|
||||||
|
* @param c the color of the plastics
|
||||||
|
* @return The plastic appearance with the given color
|
||||||
|
*/
|
||||||
private static Appearance getPlastic(Color c) {
|
private static Appearance getPlastic(Color c) {
|
||||||
if (!plastics.containsKey(c)) {
|
if (!plastics.containsKey(c)) {
|
||||||
plastics.put(c, new Appearance(c, .3));
|
plastics.put(c, new Appearance(c, .3));
|
||||||
@ -76,6 +104,12 @@ public class DefaultAppearance {
|
|||||||
return plastics.get(c);
|
return plastics.get(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gets the default based on the type of the rocket component
|
||||||
|
*
|
||||||
|
* @param c the rocket component
|
||||||
|
* @return the default appearance for that type of rocket component
|
||||||
|
*/
|
||||||
public static Appearance getDefaultAppearance(RocketComponent c) {
|
public static Appearance getDefaultAppearance(RocketComponent c) {
|
||||||
if (c instanceof BodyTube)
|
if (c instanceof BodyTube)
|
||||||
return ESTES_BT;
|
return ESTES_BT;
|
||||||
@ -100,6 +134,12 @@ public class DefaultAppearance {
|
|||||||
return Appearance.MISSING;
|
return Appearance.MISSING;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gets the default motor texture based on the manufacturer
|
||||||
|
* returns reusable motor texture as default
|
||||||
|
* @param m The motor object
|
||||||
|
* @return The default appearance for the motor
|
||||||
|
*/
|
||||||
public static Appearance getDefaultAppearance(Motor m) {
|
public static Appearance getDefaultAppearance(Motor m) {
|
||||||
if (m instanceof ThrustCurveMotor) {
|
if (m instanceof ThrustCurveMotor) {
|
||||||
ThrustCurveMotor tcm = (ThrustCurveMotor) m;
|
ThrustCurveMotor tcm = (ThrustCurveMotor) m;
|
||||||
|
@ -8,11 +8,20 @@ import java.io.InputStream;
|
|||||||
import net.sf.openrocket.appearance.DecalImage;
|
import net.sf.openrocket.appearance.DecalImage;
|
||||||
import net.sf.openrocket.util.StateChangeListener;
|
import net.sf.openrocket.util.StateChangeListener;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Default implementation class of DecalImage
|
||||||
|
*
|
||||||
|
*/
|
||||||
public class ResourceDecalImage implements DecalImage {
|
public class ResourceDecalImage implements DecalImage {
|
||||||
|
|
||||||
|
/** File path to the image*/
|
||||||
final String resource;
|
final String resource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* main constructor, stores the file path given
|
||||||
|
* @param resource
|
||||||
|
*/
|
||||||
public ResourceDecalImage(final String resource) {
|
public ResourceDecalImage(final String resource) {
|
||||||
this.resource = resource;
|
this.resource = resource;
|
||||||
}
|
}
|
||||||
|
@ -6,18 +6,30 @@ import net.sf.openrocket.util.ArrayList;
|
|||||||
import net.sf.openrocket.util.BuildProperties;
|
import net.sf.openrocket.util.BuildProperties;
|
||||||
import net.sf.openrocket.util.ComparablePair;
|
import net.sf.openrocket.util.ComparablePair;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* class that stores the update information of the application
|
||||||
|
*
|
||||||
|
*/
|
||||||
public class UpdateInfo {
|
public class UpdateInfo {
|
||||||
|
|
||||||
private final String latestVersion;
|
private final String latestVersion;
|
||||||
|
|
||||||
private final ArrayList<ComparablePair<Integer, String>> updates;
|
private final ArrayList<ComparablePair<Integer, String>> updates;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* loads the default information
|
||||||
|
*/
|
||||||
public UpdateInfo() {
|
public UpdateInfo() {
|
||||||
this.latestVersion = BuildProperties.getVersion();
|
this.latestVersion = BuildProperties.getVersion();
|
||||||
this.updates = new ArrayList<ComparablePair<Integer, String>>();
|
this.updates = new ArrayList<ComparablePair<Integer, String>>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* loads a custom update information into the cache
|
||||||
|
* @param version String with the version
|
||||||
|
* @param updates The list of updates contained in the version
|
||||||
|
*/
|
||||||
public UpdateInfo(String version, List<ComparablePair<Integer, String>> updates) {
|
public UpdateInfo(String version, List<ComparablePair<Integer, String>> updates) {
|
||||||
this.latestVersion = version;
|
this.latestVersion = version;
|
||||||
this.updates = new ArrayList<ComparablePair<Integer, String>>(updates);
|
this.updates = new ArrayList<ComparablePair<Integer, String>>(updates);
|
||||||
|
@ -41,10 +41,11 @@ public class UpdateInfoRetriever {
|
|||||||
* Check whether the update info fetching is still in progress.
|
* Check whether the update info fetching is still in progress.
|
||||||
*
|
*
|
||||||
* @return <code>true</code> if the communication is still in progress.
|
* @return <code>true</code> if the communication is still in progress.
|
||||||
|
* @throws IllegalStateException if {@link #startFetchUpdateInfo()} has not been called
|
||||||
*/
|
*/
|
||||||
public boolean isRunning() {
|
public boolean isRunning() {
|
||||||
if (fetcher == null) {
|
if (fetcher == null) {
|
||||||
throw new IllegalStateException("startFetchUpdateInfo() has not been called");
|
throw new IllegalStateException("startFetchUpdateInfo() has not been called");
|
||||||
}
|
}
|
||||||
return fetcher.isAlive();
|
return fetcher.isAlive();
|
||||||
}
|
}
|
||||||
@ -81,43 +82,76 @@ public class UpdateInfoRetriever {
|
|||||||
*/
|
*/
|
||||||
/* package-private */
|
/* package-private */
|
||||||
static UpdateInfo parseUpdateInput(Reader r) throws IOException {
|
static UpdateInfo parseUpdateInput(Reader r) throws IOException {
|
||||||
BufferedReader reader;
|
BufferedReader reader = convertToBufferedReader(r);
|
||||||
if (r instanceof BufferedReader) {
|
|
||||||
reader = (BufferedReader) r;
|
|
||||||
} else {
|
|
||||||
reader = new BufferedReader(r);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
String version = null;
|
String version = null;
|
||||||
|
|
||||||
ArrayList<ComparablePair<Integer, String>> updates =
|
ArrayList<ComparablePair<Integer, String>> updates =
|
||||||
new ArrayList<ComparablePair<Integer, String>>();
|
new ArrayList<ComparablePair<Integer, String>>();
|
||||||
|
|
||||||
String str = reader.readLine();
|
String str = reader.readLine();
|
||||||
while (str != null) {
|
while (str != null) {
|
||||||
if (str.matches("^Version: *[0-9]+\\.[0-9]+\\.[0-9]+[a-zA-Z0-9.-]* *$")) {
|
if (isHeader(str)) {
|
||||||
version = str.substring(8).trim();
|
version = str.substring(8).trim();
|
||||||
} else if (str.matches("^[0-9]+:\\p{Print}+$")) {
|
} else if (isUpdateToken(str)) {
|
||||||
int index = str.indexOf(':');
|
ComparablePair<Integer, String> update = parseUpdateToken(str);
|
||||||
int value = Integer.parseInt(str.substring(0, index));
|
if(update != null)
|
||||||
String desc = str.substring(index + 1).trim();
|
updates.add(update);
|
||||||
if (!desc.equals("")) {
|
|
||||||
updates.add(new ComparablePair<Integer, String>(value, desc));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// Ignore anything else
|
|
||||||
str = reader.readLine();
|
str = reader.readLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (version != null) {
|
if (version == null)
|
||||||
return new UpdateInfo(version, updates);
|
|
||||||
} else {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
return new UpdateInfo(version, updates);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* parses a line of a connection content into the information of an update
|
||||||
|
* @param str the line of the connection
|
||||||
|
* @return the update information
|
||||||
|
*/
|
||||||
|
private static ComparablePair<Integer, String> parseUpdateToken(String str){
|
||||||
|
int index = str.indexOf(':');
|
||||||
|
int value = Integer.parseInt(str.substring(0, index));
|
||||||
|
String desc = str.substring(index + 1).trim();
|
||||||
|
|
||||||
|
if (desc.equals(""))
|
||||||
|
return null;
|
||||||
|
return new ComparablePair<Integer, String>(value, desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* checks if a string contains and update information
|
||||||
|
* @param str the string itself
|
||||||
|
* @return true for when the string has an update
|
||||||
|
* false otherwise
|
||||||
|
*/
|
||||||
|
private static boolean isUpdateToken(String str) {
|
||||||
|
return str.matches("^[0-9]+:\\p{Print}+$");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* check if the string is formated as an update list header
|
||||||
|
* @param str the string to be checked
|
||||||
|
* @return true if str is a header, false otherwise
|
||||||
|
*/
|
||||||
|
private static boolean isHeader(String str) {
|
||||||
|
return str.matches("^Version: *[0-9]+\\.[0-9]+\\.[0-9]+[a-zA-Z0-9.-]* *$");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* convert, if not yet converted, a Reader into a buffered reader
|
||||||
|
* @param r the Reader object
|
||||||
|
* @return the Reader as a BufferedReader Object
|
||||||
|
*/
|
||||||
|
private static BufferedReader convertToBufferedReader(Reader r) {
|
||||||
|
if (r instanceof BufferedReader)
|
||||||
|
return (BufferedReader) r;
|
||||||
|
return new BufferedReader(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An asynchronous task that fetches and parses the update info.
|
* An asynchronous task that fetches and parses the update info.
|
||||||
*
|
*
|
||||||
@ -137,11 +171,193 @@ public class UpdateInfoRetriever {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Establishes a connection with data of previous updates
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
private void doConnection() throws IOException {
|
private void doConnection() throws IOException {
|
||||||
String url = Communicator.UPDATE_INFO_URL + "?" + Communicator.VERSION_PARAM + "="
|
HttpURLConnection connection = getConnection(getUrl());
|
||||||
+ Communicator.encode(BuildProperties.getVersion());
|
InputStream is = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
connection.connect();
|
||||||
|
if(!checkConnection(connection))
|
||||||
|
return;
|
||||||
|
if(!checkContentType(connection))
|
||||||
|
return;
|
||||||
|
is = new LimitedInputStream(connection.getInputStream(), Communicator.MAX_INPUT_BYTES);
|
||||||
|
parseUpdateInput(buildBufferedReader(connection,is));
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
if (is != null)
|
||||||
|
is.close();
|
||||||
|
connection.disconnect();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the data received in a buffered reader
|
||||||
|
* @param reader The reader object
|
||||||
|
* @throws IOException If anything bad happens
|
||||||
|
*/
|
||||||
|
private void parseUpdateInput(BufferedReader reader) throws IOException{
|
||||||
|
String version = null;
|
||||||
|
ArrayList<ComparablePair<Integer, String>> updates =
|
||||||
|
new ArrayList<ComparablePair<Integer, String>>();
|
||||||
|
|
||||||
|
String line = reader.readLine();
|
||||||
|
while (line != null) {
|
||||||
|
if (isHeader(line)) {
|
||||||
|
version = parseHeader(line);
|
||||||
|
} else if (isUpdateInfo(line)) {
|
||||||
|
updates.add(parseUpdateInfo(line));
|
||||||
|
}
|
||||||
|
line = reader.readLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isInvalidVersion(version)) {
|
||||||
|
log.warn("Invalid version received, ignoring.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
info = new UpdateInfo(version, updates);
|
||||||
|
log.info("Found update: " + info);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* parses a line into it's version name
|
||||||
|
* @param line the string of the header
|
||||||
|
* @return the version in it's right format
|
||||||
|
*/
|
||||||
|
private String parseHeader(String line) {
|
||||||
|
return line.substring(8).trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* parses a line into it's correspondent update information
|
||||||
|
* @param line the line to be parsed
|
||||||
|
* @return update information from the line
|
||||||
|
*/
|
||||||
|
private ComparablePair<Integer,String> parseUpdateInfo(String line){
|
||||||
|
String[] split = line.split(":", 2);
|
||||||
|
int n = Integer.parseInt(split[0]);
|
||||||
|
return new ComparablePair<Integer, String>(n, split[1].trim());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* checks if a line contains an update information
|
||||||
|
* @param line the line to be checked
|
||||||
|
* @return true if the line caontain an update information
|
||||||
|
* false otherwise
|
||||||
|
*/
|
||||||
|
private boolean isUpdateInfo(String line) {
|
||||||
|
return line.matches("^[0-9]{1,9}:\\P{Cntrl}{1,300}$");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* checks if a line is a header of an update list
|
||||||
|
* @param line the line to be checked
|
||||||
|
* @return true if line is a header, false otherwise
|
||||||
|
*/
|
||||||
|
private boolean isHeader(String line) {
|
||||||
|
return line.matches("^Version:[a-zA-Z0-9._ -]{1,30}$");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* checks if a String is a valid version
|
||||||
|
* @param version the String to be checked
|
||||||
|
* @return true if it's valid, false otherwise
|
||||||
|
*/
|
||||||
|
private boolean isInvalidVersion(String version) {
|
||||||
|
return version == null || version.length() == 0 ||
|
||||||
|
version.equalsIgnoreCase(BuildProperties.getVersion());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* builds a buffered reader from an open connection and a stream
|
||||||
|
* @param connection The connection
|
||||||
|
* @param is The input stream
|
||||||
|
* @return The Buffered reader created
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
private BufferedReader buildBufferedReader(HttpURLConnection connection, InputStream is) throws IOException {
|
||||||
|
String encoding = connection.getContentEncoding();
|
||||||
|
if (encoding == null || encoding.equals(""))
|
||||||
|
encoding = "UTF-8";
|
||||||
|
return new BufferedReader(new InputStreamReader(is, encoding));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* check if the content of a connection is valid
|
||||||
|
* @param connection the connection to be checked
|
||||||
|
* @return true if the content is valid, false otherwise
|
||||||
|
*/
|
||||||
|
private boolean checkContentType(HttpURLConnection connection) {
|
||||||
|
String contentType = connection.getContentType();
|
||||||
|
if (contentType == null ||
|
||||||
|
contentType.toLowerCase(Locale.ENGLISH).indexOf(Communicator.UPDATE_INFO_CONTENT_TYPE) < 0) {
|
||||||
|
// Unknown response type
|
||||||
|
log.warn("Unknown Content-type received:" + contentType);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* check if a connection is responsive and valid
|
||||||
|
* @param connection the connection to be checked
|
||||||
|
* @return true if connection is ok, false otherwise
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
private boolean checkConnection(HttpURLConnection connection) throws IOException{
|
||||||
|
log.debug("Update response code: " + connection.getResponseCode());
|
||||||
|
|
||||||
|
if (noUpdatesAvailable(connection)) {
|
||||||
|
log.info("No updates available");
|
||||||
|
info = new UpdateInfo();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!updateAvailable(connection)) {
|
||||||
|
// Error communicating with server
|
||||||
|
log.warn("Unknown server response code: " + connection.getResponseCode());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* checks if a connection sent an update available flag
|
||||||
|
* @param connection the connection to be checked
|
||||||
|
* @return true if the response was an update available flag
|
||||||
|
* false otherwise
|
||||||
|
* @throws IOException if anything goes wrong
|
||||||
|
*/
|
||||||
|
private boolean updateAvailable(HttpURLConnection connection) throws IOException {
|
||||||
|
return connection.getResponseCode() == Communicator.UPDATE_INFO_UPDATE_AVAILABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* checks if a connection sent an update unavailable flag
|
||||||
|
* @param connection the connection to be checked
|
||||||
|
* @return true if the response was an no update available flag
|
||||||
|
* false otherwise
|
||||||
|
* @throws IOException if anything goes wrong
|
||||||
|
*/
|
||||||
|
private boolean noUpdatesAvailable(HttpURLConnection connection) throws IOException {
|
||||||
|
return connection.getResponseCode() == Communicator.UPDATE_INFO_NO_UPDATE_CODE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds a connection with the given url
|
||||||
|
* @param url the url
|
||||||
|
* @return connection base on the url
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
private HttpURLConnection getConnection(String url) throws IOException{
|
||||||
HttpURLConnection connection = Communicator.connectionSource.getConnection(url);
|
HttpURLConnection connection = Communicator.connectionSource.getConnection(url);
|
||||||
|
|
||||||
connection.setConnectTimeout(Communicator.CONNECTION_TIMEOUT);
|
connection.setConnectTimeout(Communicator.CONNECTION_TIMEOUT);
|
||||||
@ -165,80 +381,16 @@ public class UpdateInfoRetriever {
|
|||||||
connection.setRequestProperty("X-OpenRocket-Locale",
|
connection.setRequestProperty("X-OpenRocket-Locale",
|
||||||
Communicator.encode(Locale.getDefault().toString()));
|
Communicator.encode(Locale.getDefault().toString()));
|
||||||
connection.setRequestProperty("X-OpenRocket-CPUs", "" + Runtime.getRuntime().availableProcessors());
|
connection.setRequestProperty("X-OpenRocket-CPUs", "" + Runtime.getRuntime().availableProcessors());
|
||||||
|
return connection;
|
||||||
InputStream is = null;
|
}
|
||||||
try {
|
|
||||||
connection.connect();
|
/**
|
||||||
|
* builds the default url for fetching updates
|
||||||
log.debug("Update response code: " + connection.getResponseCode());
|
* @return the string with an url for fethcing updates
|
||||||
|
*/
|
||||||
if (connection.getResponseCode() == Communicator.UPDATE_INFO_NO_UPDATE_CODE) {
|
private String getUrl() {
|
||||||
// No updates are available
|
return Communicator.UPDATE_INFO_URL + "?" + Communicator.VERSION_PARAM + "="
|
||||||
log.info("No updates available");
|
+ Communicator.encode(BuildProperties.getVersion());
|
||||||
info = new UpdateInfo();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (connection.getResponseCode() != Communicator.UPDATE_INFO_UPDATE_AVAILABLE) {
|
|
||||||
// Error communicating with server
|
|
||||||
log.warn("Unknown server response code: " + connection.getResponseCode());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
String contentType = connection.getContentType();
|
|
||||||
if (contentType == null ||
|
|
||||||
contentType.toLowerCase(Locale.ENGLISH).indexOf(Communicator.UPDATE_INFO_CONTENT_TYPE) < 0) {
|
|
||||||
// Unknown response type
|
|
||||||
log.warn("Unknown Content-type received:" + contentType);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update is available, parse input
|
|
||||||
is = connection.getInputStream();
|
|
||||||
is = new LimitedInputStream(is, Communicator.MAX_INPUT_BYTES);
|
|
||||||
String encoding = connection.getContentEncoding();
|
|
||||||
if (encoding == null || encoding.equals(""))
|
|
||||||
encoding = "UTF-8";
|
|
||||||
BufferedReader reader = new BufferedReader(new InputStreamReader(is, encoding));
|
|
||||||
|
|
||||||
String version = null;
|
|
||||||
ArrayList<ComparablePair<Integer, String>> updates =
|
|
||||||
new ArrayList<ComparablePair<Integer, String>>();
|
|
||||||
|
|
||||||
String line = reader.readLine();
|
|
||||||
while (line != null) {
|
|
||||||
|
|
||||||
if (line.matches("^Version:[a-zA-Z0-9._ -]{1,30}$")) {
|
|
||||||
version = line.substring(8).trim();
|
|
||||||
} else if (line.matches("^[0-9]{1,9}:\\P{Cntrl}{1,300}$")) {
|
|
||||||
String[] split = line.split(":", 2);
|
|
||||||
int n = Integer.parseInt(split[0]);
|
|
||||||
updates.add(new ComparablePair<Integer, String>(n, split[1].trim()));
|
|
||||||
}
|
|
||||||
// Ignore line otherwise
|
|
||||||
line = reader.readLine();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check version input
|
|
||||||
if (version == null || version.length() == 0 ||
|
|
||||||
version.equalsIgnoreCase(BuildProperties.getVersion())) {
|
|
||||||
// Invalid response
|
|
||||||
log.warn("Invalid version received, ignoring.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
info = new UpdateInfo(version, updates);
|
|
||||||
log.info("Found update: " + info);
|
|
||||||
} finally {
|
|
||||||
try {
|
|
||||||
if (is != null)
|
|
||||||
is.close();
|
|
||||||
connection.disconnect();
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,7 @@ public abstract class AsynchronousDatabaseLoader {
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return whether loading the database has ended.
|
* @return whether loading the database has ended.
|
||||||
*/
|
*/
|
||||||
public boolean isLoaded() {
|
public boolean isLoaded() {
|
||||||
return endedLoading;
|
return endedLoading;
|
||||||
@ -86,10 +86,27 @@ public abstract class AsynchronousDatabaseLoader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
private void doLoad() {
|
private void doLoad() {
|
||||||
|
|
||||||
// Pause for indicated startup time
|
// Pause for indicated startup time
|
||||||
|
pauseForStartupTime();
|
||||||
|
|
||||||
|
loadDatabase();
|
||||||
|
|
||||||
|
synchronized (this) {
|
||||||
|
endedLoading = true;
|
||||||
|
this.notifyAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* waits the startup time before loading the database
|
||||||
|
*/
|
||||||
|
private void pauseForStartupTime() {
|
||||||
long startLoading = System.currentTimeMillis() + startupDelay;
|
long startLoading = System.currentTimeMillis() + startupDelay;
|
||||||
while (!inUse && System.currentTimeMillis() < startLoading) {
|
while (!inUse && System.currentTimeMillis() < startLoading) {
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
@ -99,16 +116,11 @@ public abstract class AsynchronousDatabaseLoader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
loadDatabase();
|
|
||||||
|
|
||||||
synchronized (this) {
|
|
||||||
endedLoading = true;
|
|
||||||
this.notifyAll();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* method that actually load the database
|
||||||
|
*/
|
||||||
protected abstract void loadDatabase();
|
protected abstract void loadDatabase();
|
||||||
|
|
||||||
|
|
||||||
|
@ -6,10 +6,23 @@ import net.sf.openrocket.preset.ComponentPreset;
|
|||||||
|
|
||||||
public interface ComponentPresetDao {
|
public interface ComponentPresetDao {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* return a list all components
|
||||||
|
* @return list of all components
|
||||||
|
*/
|
||||||
public List<ComponentPreset> listAll();
|
public List<ComponentPreset> listAll();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* insert a component preset into a database
|
||||||
|
* @param preset the component to be inserted into the database
|
||||||
|
*/
|
||||||
public void insert( ComponentPreset preset );
|
public void insert( ComponentPreset preset );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* return all components preset matching the given type
|
||||||
|
* @param type the searched type
|
||||||
|
* @return the list of components matching the type
|
||||||
|
*/
|
||||||
public List<ComponentPreset> listForType( ComponentPreset.Type type );
|
public List<ComponentPreset> listForType( ComponentPreset.Type type );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -21,13 +34,35 @@ public interface ComponentPresetDao {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public List<ComponentPreset> listForType( ComponentPreset.Type type, boolean favorite );
|
public List<ComponentPreset> listForType( ComponentPreset.Type type, boolean favorite );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of components presets of multiple types
|
||||||
|
* @param type the types to be searched for
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
public List<ComponentPreset> listForTypes( ComponentPreset.Type ... type );
|
public List<ComponentPreset> listForTypes( ComponentPreset.Type ... type );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of components preset of each type in the list
|
||||||
|
* @param types the list of types to be searched for
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
public List<ComponentPreset> listForTypes( List<ComponentPreset.Type> types );
|
public List<ComponentPreset> listForTypes( List<ComponentPreset.Type> types );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* set or reset a component preset as favorite
|
||||||
|
* @param preset the preset to be set as favorite
|
||||||
|
* @param type the type of the preset
|
||||||
|
* @param favorite true to set, false to reset as favorite
|
||||||
|
*/
|
||||||
public void setFavorite( ComponentPreset preset, ComponentPreset.Type type, boolean favorite );
|
public void setFavorite( ComponentPreset preset, ComponentPreset.Type type, boolean favorite );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns a list of components preset based on manufacturer and part number
|
||||||
|
* @param manufacturer the manufacturer to be searched for
|
||||||
|
* @param partNo the part number of the component
|
||||||
|
* @return the resulting list of the search
|
||||||
|
*/
|
||||||
public List<ComponentPreset> find( String manufacturer, String partNo );
|
public List<ComponentPreset> find( String manufacturer, String partNo );
|
||||||
|
|
||||||
}
|
}
|
@ -19,6 +19,7 @@ import net.sf.openrocket.database.DatabaseListener;
|
|||||||
*/
|
*/
|
||||||
public class Database<T extends Comparable<T>> extends AbstractSet<T> {
|
public class Database<T extends Comparable<T>> extends AbstractSet<T> {
|
||||||
|
|
||||||
|
/** the list that contains the data from the database itself*/
|
||||||
protected final List<T> list = new ArrayList<T>();
|
protected final List<T> list = new ArrayList<T>();
|
||||||
private final ArrayList<DatabaseListener<T>> listeners = new ArrayList<DatabaseListener<T>>();
|
private final ArrayList<DatabaseListener<T>> listeners = new ArrayList<DatabaseListener<T>>();
|
||||||
|
|
||||||
@ -33,6 +34,10 @@ public class Database<T extends Comparable<T>> extends AbstractSet<T> {
|
|||||||
return list.size();
|
return list.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
* fires add event
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean add(T element) {
|
public boolean add(T element) {
|
||||||
int index;
|
int index;
|
||||||
@ -71,17 +76,27 @@ public class Database<T extends Comparable<T>> extends AbstractSet<T> {
|
|||||||
return list.indexOf(m);
|
return list.indexOf(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* adds a listener for database changes
|
||||||
|
* @param listener the listener
|
||||||
|
*/
|
||||||
public void addDatabaseListener(DatabaseListener<T> listener) {
|
public void addDatabaseListener(DatabaseListener<T> listener) {
|
||||||
listeners.add(listener);
|
listeners.add(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* removes a listener from the list os listeners
|
||||||
|
* @param listener
|
||||||
|
*/
|
||||||
public void removeChangeListener(DatabaseListener<T> listener) {
|
public void removeChangeListener(DatabaseListener<T> listener) {
|
||||||
listeners.remove(listener);
|
listeners.remove(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wake up call for database listeners for when elements are added
|
||||||
|
* @param element the element added
|
||||||
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
protected void fireAddEvent(T element) {
|
protected void fireAddEvent(T element) {
|
||||||
Object[] array = listeners.toArray();
|
Object[] array = listeners.toArray();
|
||||||
@ -90,6 +105,10 @@ public class Database<T extends Comparable<T>> extends AbstractSet<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wake up call for database listeners when elements are removed
|
||||||
|
* @param element the removed element
|
||||||
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
protected void fireRemoveEvent(T element) {
|
protected void fireRemoveEvent(T element) {
|
||||||
Object[] array = listeners.toArray();
|
Object[] array = listeners.toArray();
|
||||||
@ -98,10 +117,6 @@ public class Database<T extends Comparable<T>> extends AbstractSet<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Iterator class implementation that fires changes if remove() is called.
|
* Iterator class implementation that fires changes if remove() is called.
|
||||||
*/
|
*/
|
||||||
@ -120,6 +135,10 @@ public class Database<T extends Comparable<T>> extends AbstractSet<T> {
|
|||||||
return current;
|
return current;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
* fires remove event
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void remove() {
|
public void remove() {
|
||||||
iterator.remove();
|
iterator.remove();
|
||||||
|
@ -1,9 +1,24 @@
|
|||||||
package net.sf.openrocket.database;
|
package net.sf.openrocket.database;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* interface defining listeners for database
|
||||||
|
*
|
||||||
|
* @param <T> type stored in the database
|
||||||
|
*/
|
||||||
public interface DatabaseListener<T extends Comparable<T>> {
|
public interface DatabaseListener<T extends Comparable<T>> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* action for when elements are added
|
||||||
|
* @param element the element added
|
||||||
|
* @param source the database of which the element was added
|
||||||
|
*/
|
||||||
public void elementAdded(T element, Database<T> source);
|
public void elementAdded(T element, Database<T> source);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* action for when elements are removed
|
||||||
|
* @param element the removed element
|
||||||
|
* @param source the database on which the element was removed
|
||||||
|
*/
|
||||||
public void elementRemoved(T element, Database<T> source);
|
public void elementRemoved(T element, Database<T> source);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -117,7 +117,13 @@ public class Databases {
|
|||||||
BULK_MATERIAL.addDatabaseListener(listener);
|
BULK_MATERIAL.addDatabaseListener(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* builds a new material based on the parameters given
|
||||||
|
* @param type The type of material
|
||||||
|
* @param baseName the name of material
|
||||||
|
* @param density density
|
||||||
|
* @return a new onejct withe the material data
|
||||||
|
*/
|
||||||
private static Material newMaterial(Type type, String baseName, double density) {
|
private static Material newMaterial(Type type, String baseName, double density) {
|
||||||
String name = trans.get("material", baseName);
|
String name = trans.get("material", baseName);
|
||||||
return Material.newMaterial(type, name, density, false);
|
return Material.newMaterial(type, name, density, false);
|
||||||
@ -145,21 +151,7 @@ public class Databases {
|
|||||||
* @return the material, or <code>null</code> if not found.
|
* @return the material, or <code>null</code> if not found.
|
||||||
*/
|
*/
|
||||||
public static Material findMaterial(Material.Type type, String baseName) {
|
public static Material findMaterial(Material.Type type, String baseName) {
|
||||||
Database<Material> db;
|
Database<Material> db = getDatabase(type);
|
||||||
switch (type) {
|
|
||||||
case BULK:
|
|
||||||
db = BULK_MATERIAL;
|
|
||||||
break;
|
|
||||||
case SURFACE:
|
|
||||||
db = SURFACE_MATERIAL;
|
|
||||||
break;
|
|
||||||
case LINE:
|
|
||||||
db = LINE_MATERIAL;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new IllegalArgumentException("Illegal material type: " + type);
|
|
||||||
}
|
|
||||||
|
|
||||||
String name = trans.get("material", baseName);
|
String name = trans.get("material", baseName);
|
||||||
|
|
||||||
for (Material m : db) {
|
for (Material m : db) {
|
||||||
@ -170,6 +162,24 @@ public class Databases {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gets the specific database with the given type
|
||||||
|
* @param type the desired type
|
||||||
|
* @return the database of the type given
|
||||||
|
*/
|
||||||
|
private static Database<Material> getDatabase(Material.Type type){
|
||||||
|
switch (type) {
|
||||||
|
case BULK:
|
||||||
|
return BULK_MATERIAL;
|
||||||
|
case SURFACE:
|
||||||
|
return SURFACE_MATERIAL;
|
||||||
|
case LINE:
|
||||||
|
return LINE_MATERIAL;
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("Illegal material type: " + type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find a material from the database or return a new user defined material if the specified
|
* Find a material from the database or return a new user defined material if the specified
|
||||||
@ -184,21 +194,7 @@ public class Databases {
|
|||||||
* @return the material object from the database or a new material.
|
* @return the material object from the database or a new material.
|
||||||
*/
|
*/
|
||||||
public static Material findMaterial(Material.Type type, String baseName, double density) {
|
public static Material findMaterial(Material.Type type, String baseName, double density) {
|
||||||
Database<Material> db;
|
Database<Material> db = getDatabase(type);
|
||||||
switch (type) {
|
|
||||||
case BULK:
|
|
||||||
db = BULK_MATERIAL;
|
|
||||||
break;
|
|
||||||
case SURFACE:
|
|
||||||
db = SURFACE_MATERIAL;
|
|
||||||
break;
|
|
||||||
case LINE:
|
|
||||||
db = LINE_MATERIAL;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new IllegalArgumentException("Illegal material type: " + type);
|
|
||||||
}
|
|
||||||
|
|
||||||
String name = trans.get("material", baseName);
|
String name = trans.get("material", baseName);
|
||||||
|
|
||||||
for (Material m : db) {
|
for (Material m : db) {
|
||||||
|
@ -326,4 +326,4 @@ public class ThrustCurveMotorSet implements Comparable<ThrustCurveMotorSet> {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -7,21 +7,44 @@ import java.io.InputStream;
|
|||||||
import net.sf.openrocket.util.AbstractChangeSource;
|
import net.sf.openrocket.util.AbstractChangeSource;
|
||||||
import net.sf.openrocket.util.ChangeSource;
|
import net.sf.openrocket.util.ChangeSource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Class handler of documents attachments
|
||||||
|
*
|
||||||
|
*/
|
||||||
public abstract class Attachment extends AbstractChangeSource implements Comparable<Attachment>, ChangeSource {
|
public abstract class Attachment extends AbstractChangeSource implements Comparable<Attachment>, ChangeSource {
|
||||||
|
|
||||||
private final String name;
|
private final String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* default constructor
|
||||||
|
* @param name the attachment name
|
||||||
|
*/
|
||||||
public Attachment(String name) {
|
public Attachment(String name) {
|
||||||
super();
|
super();
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns the name of attachment
|
||||||
|
* @return name of attachment
|
||||||
|
*/
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns the stream of bytes representing the attachment
|
||||||
|
* @return the stream of bytes representing the attachment
|
||||||
|
* @throws FileNotFoundException
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
public abstract InputStream getBytes() throws FileNotFoundException, IOException;
|
public abstract InputStream getBytes() throws FileNotFoundException, IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
* considers only the name to equals
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int compareTo(Attachment o) {
|
public int compareTo(Attachment o) {
|
||||||
return this.name.compareTo(o.name);
|
return this.name.compareTo(o.name);
|
||||||
|
@ -25,13 +25,28 @@ import net.sf.openrocket.util.ChangeSource;
|
|||||||
import net.sf.openrocket.util.FileUtils;
|
import net.sf.openrocket.util.FileUtils;
|
||||||
import net.sf.openrocket.util.StateChangeListener;
|
import net.sf.openrocket.util.StateChangeListener;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Class that handles decal usage registration
|
||||||
|
*
|
||||||
|
*/
|
||||||
public class DecalRegistry {
|
public class DecalRegistry {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* default constructor, does nothing
|
||||||
|
*/
|
||||||
DecalRegistry() {
|
DecalRegistry() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** the decal usage map*/
|
||||||
private Map<String, DecalImageImpl> registeredDecals = new HashMap<String, DecalImageImpl>();
|
private Map<String, DecalImageImpl> registeredDecals = new HashMap<String, DecalImageImpl>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns a new decal with the same image but with unique names
|
||||||
|
* supports only classes and subclasses of DecalImageImpl
|
||||||
|
* @param original the decal to be made unique
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
public DecalImage makeUniqueImage(DecalImage original) {
|
public DecalImage makeUniqueImage(DecalImage original) {
|
||||||
|
|
||||||
if (!(original instanceof DecalImageImpl)) {
|
if (!(original instanceof DecalImageImpl)) {
|
||||||
@ -57,6 +72,11 @@ public class DecalRegistry {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get the image from an attachment
|
||||||
|
* @param attachment
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
public DecalImage getDecalImage(Attachment attachment) {
|
public DecalImage getDecalImage(Attachment attachment) {
|
||||||
String decalName = attachment.getName();
|
String decalName = attachment.getName();
|
||||||
DecalImageImpl d;
|
DecalImageImpl d;
|
||||||
@ -166,6 +186,10 @@ public class DecalRegistry {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
File getFileSystemLocation() {
|
File getFileSystemLocation() {
|
||||||
return fileSystemLocation;
|
return fileSystemLocation;
|
||||||
}
|
}
|
||||||
@ -205,6 +229,11 @@ public class DecalRegistry {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sercha
|
||||||
|
* @param file
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
private DecalImageImpl findDecalForFile(File file) {
|
private DecalImageImpl findDecalForFile(File file) {
|
||||||
|
|
||||||
for (DecalImageImpl d : registeredDecals.values()) {
|
for (DecalImageImpl d : registeredDecals.values()) {
|
||||||
@ -240,28 +269,25 @@ public class DecalRegistry {
|
|||||||
private static final int NUMBER_INDEX = 3;
|
private static final int NUMBER_INDEX = 3;
|
||||||
private static final int EXTENSION_INDEX = 4;
|
private static final int EXTENSION_INDEX = 4;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Makes a unique name for saving decal files in case the name already exists
|
||||||
|
* @param name the name of the decal
|
||||||
|
* @return the name formated and unique
|
||||||
|
*/
|
||||||
private String makeUniqueName(String name) {
|
private String makeUniqueName(String name) {
|
||||||
|
|
||||||
String newName = name;
|
String newName = checkPathConsistency(name);
|
||||||
if (!newName.startsWith("decals/")) {
|
String basename = getGroup(BASE_NAME_INDEX,fileNamePattern.matcher(newName));
|
||||||
newName = "decals/" + name;
|
String extension = getGroup(EXTENSION_INDEX,fileNamePattern.matcher(newName));
|
||||||
}
|
|
||||||
String basename = "";
|
|
||||||
String extension = "";
|
|
||||||
Matcher nameMatcher = fileNamePattern.matcher(newName);
|
|
||||||
if (nameMatcher.matches()) {
|
|
||||||
basename = nameMatcher.group(BASE_NAME_INDEX);
|
|
||||||
extension = nameMatcher.group(EXTENSION_INDEX);
|
|
||||||
}
|
|
||||||
|
|
||||||
Set<Integer> counts = new TreeSet<Integer>();
|
Set<Integer> counts = new TreeSet<Integer>();
|
||||||
|
|
||||||
boolean needsRewrite = false;
|
boolean needsRewrite = false;
|
||||||
|
|
||||||
for (DecalImageImpl d : registeredDecals.values()) {
|
for (DecalImageImpl d : registeredDecals.values()) {
|
||||||
Matcher m = fileNamePattern.matcher(d.getName());
|
Matcher m = fileNamePattern.matcher(d.getName());
|
||||||
if (m.matches()) {
|
if (m.matches()) {
|
||||||
if (basename.equals(m.group(BASE_NAME_INDEX)) && extension.equals(m.group(EXTENSION_INDEX))) {
|
if (isofSameBaseAndExtension(m, basename, extension)) {
|
||||||
String intString = m.group(NUMBER_INDEX);
|
String intString = m.group(NUMBER_INDEX);
|
||||||
if (intString != null) {
|
if (intString != null) {
|
||||||
Integer i = Integer.parseInt(intString);
|
Integer i = Integer.parseInt(intString);
|
||||||
@ -278,13 +304,54 @@ public class DecalRegistry {
|
|||||||
return newName;
|
return newName;
|
||||||
}
|
}
|
||||||
|
|
||||||
// find a missing integer;
|
return MessageFormat.format("{0} ({1}).{2}", basename, findMissingInteger(counts),extension);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Searches the count for a new Integer
|
||||||
|
* @param counts the count set
|
||||||
|
* @return a unique integer in the count
|
||||||
|
*/
|
||||||
|
private Integer findMissingInteger(Set<Integer> counts) {
|
||||||
Integer newIndex = 1;
|
Integer newIndex = 1;
|
||||||
while (counts.contains(newIndex)) {
|
while (counts.contains(newIndex)) {
|
||||||
newIndex++;
|
newIndex++;
|
||||||
}
|
}
|
||||||
|
return newIndex;
|
||||||
return MessageFormat.format("{0} ({1}).{2}", basename, newIndex, extension);
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests if a matcher has the same basename and extension
|
||||||
|
* @param m the matcher being tested
|
||||||
|
* @param basename the basename
|
||||||
|
* @param extension the extension
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private boolean isofSameBaseAndExtension(Matcher m, String basename, String extension) {
|
||||||
|
return basename.equals(m.group(BASE_NAME_INDEX)) && extension.equals(m.group(EXTENSION_INDEX));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gets the String group from a matcher
|
||||||
|
* @param index the index of the group to
|
||||||
|
* @param matcher the matcher for the search
|
||||||
|
* @return the String according with the group, empty if there's no match
|
||||||
|
*/
|
||||||
|
private String getGroup(int index, Matcher matcher) {
|
||||||
|
if (matcher.matches())
|
||||||
|
return matcher.group(index);
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* checks if the name starts with "decals/"
|
||||||
|
* @param name the name being checked
|
||||||
|
* @return the name complete with the starting folder
|
||||||
|
*/
|
||||||
|
private String checkPathConsistency(String name){
|
||||||
|
if (name.startsWith("decals/"))
|
||||||
|
return name;
|
||||||
|
return "decals/" + name;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -102,36 +102,56 @@ public class OpenRocketDocument implements ComponentChangeListener {
|
|||||||
|
|
||||||
private final List<DocumentChangeListener> listeners = new ArrayList<DocumentChangeListener>();
|
private final List<DocumentChangeListener> listeners = new ArrayList<DocumentChangeListener>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* main constructor, enable events in the rocket
|
||||||
|
* and initializes the document
|
||||||
|
* @param rocket the rocket to be used in the document
|
||||||
|
*/
|
||||||
OpenRocketDocument(Rocket rocket) {
|
OpenRocketDocument(Rocket rocket) {
|
||||||
this.rocket = rocket;
|
this.rocket = rocket;
|
||||||
rocket.enableEvents();
|
rocket.enableEvents();
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* initializes the document, clearing the undo cache and
|
||||||
|
* setting itself as a listener for changes in the rocket
|
||||||
|
*/
|
||||||
private void init() {
|
private void init() {
|
||||||
clearUndo();
|
clearUndo();
|
||||||
|
|
||||||
rocket.addComponentChangeListener(this);
|
rocket.addComponentChangeListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* adds a customExpression into the list
|
||||||
|
* @param expression the expression to be added
|
||||||
|
*/
|
||||||
public void addCustomExpression(CustomExpression expression) {
|
public void addCustomExpression(CustomExpression expression) {
|
||||||
if (customExpressions.contains(expression)) {
|
if (customExpressions.contains(expression)) {
|
||||||
log.info(Markers.USER_MARKER, "Could not add custom expression " + expression.getName() + " to document as document alerady has a matching expression.");
|
log.info(Markers.USER_MARKER, "Could not add custom expression " + expression.getName() + " to document as document alerady has a matching expression.");
|
||||||
} else {
|
}
|
||||||
customExpressions.add(expression);
|
customExpressions.add(expression);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* remves
|
||||||
|
* @param expression
|
||||||
|
*/
|
||||||
public void removeCustomExpression(CustomExpression expression) {
|
public void removeCustomExpression(CustomExpression expression) {
|
||||||
customExpressions.remove(expression);
|
customExpressions.remove(expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO:LOW:this leaves the object custom expression exposed, is it supposed to be like that?
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
public List<CustomExpression> getCustomExpressions() {
|
public List<CustomExpression> getCustomExpressions() {
|
||||||
return customExpressions;
|
return customExpressions;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* Returns a set of all the flight data types defined or available in any way in the rocket document
|
* @returns a set of all the flight data types defined or available in any way in the rocket document
|
||||||
*/
|
*/
|
||||||
public Set<FlightDataType> getFlightDataTypes() {
|
public Set<FlightDataType> getFlightDataTypes() {
|
||||||
Set<FlightDataType> allTypes = new LinkedHashSet<FlightDataType>();
|
Set<FlightDataType> allTypes = new LinkedHashSet<FlightDataType>();
|
||||||
@ -158,28 +178,50 @@ public class OpenRocketDocument implements ComponentChangeListener {
|
|||||||
return allTypes;
|
return allTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gets the rocket in the document
|
||||||
|
* @return the rocket in the document
|
||||||
|
*/
|
||||||
public Rocket getRocket() {
|
public Rocket getRocket() {
|
||||||
return rocket;
|
return rocket;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns the selected configuration from the rocket
|
||||||
|
* @return selected configuration from the rocket
|
||||||
|
*/
|
||||||
public FlightConfiguration getSelectedConfiguration() {
|
public FlightConfiguration getSelectedConfiguration() {
|
||||||
return rocket.getSelectedConfiguration();
|
return rocket.getSelectedConfiguration();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns the File handler object for the document
|
||||||
|
* @return the File handler object for the document
|
||||||
|
*/
|
||||||
public File getFile() {
|
public File getFile() {
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* set the file handler object for the document
|
||||||
|
* @param file the new file handler object
|
||||||
|
*/
|
||||||
public void setFile(File file) {
|
public void setFile(File file) {
|
||||||
this.file = file;
|
this.file = file;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns if the current rocket is saved
|
||||||
|
* @return if the current rocket is saved
|
||||||
|
*/
|
||||||
public boolean isSaved() {
|
public boolean isSaved() {
|
||||||
return rocket.getModID() == savedID;
|
return rocket.getModID() == savedID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sets the current rocket as saved, and none if false is given
|
||||||
|
* @param saved if the current rocket or none will be set to save
|
||||||
|
*/
|
||||||
public void setSaved(boolean saved) {
|
public void setSaved(boolean saved) {
|
||||||
if (saved == false)
|
if (saved == false)
|
||||||
this.savedID = -1;
|
this.savedID = -1;
|
||||||
@ -197,33 +239,57 @@ public class OpenRocketDocument implements ComponentChangeListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns the decal list used in the document
|
||||||
|
* @return the decal list registered in the document
|
||||||
|
*/
|
||||||
public Collection<DecalImage> getDecalList() {
|
public Collection<DecalImage> getDecalList() {
|
||||||
|
|
||||||
return decalRegistry.getDecalList();
|
return decalRegistry.getDecalList();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns the number of times the given decal was used
|
||||||
|
* @param img the decal to be counted
|
||||||
|
* @return the number of times
|
||||||
|
*/
|
||||||
public int countDecalUsage(DecalImage img) {
|
public int countDecalUsage(DecalImage img) {
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
||||||
Iterator<RocketComponent> it = rocket.iterator();
|
Iterator<RocketComponent> it = rocket.iterator();
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
RocketComponent comp = it.next();
|
if(hasDecal(it.next(),img))
|
||||||
Appearance a = comp.getAppearance();
|
|
||||||
if (a == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
Decal d = a.getTexture();
|
|
||||||
if (d == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (img.equals(d.getImage())) {
|
|
||||||
count++;
|
count++;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO: LOW: move this method to rocketComponent, Appearance and decal
|
||||||
|
//I see 3 layers of object accessed, seems unsafe
|
||||||
|
/**
|
||||||
|
* checks if a rocket component has the given decalImage
|
||||||
|
* @param comp the RocketComponent to be searched
|
||||||
|
* @param img the DecalImage to be checked
|
||||||
|
* @return if the comp has img
|
||||||
|
*/
|
||||||
|
private boolean hasDecal(RocketComponent comp, DecalImage img){
|
||||||
|
Appearance a = comp.getAppearance();
|
||||||
|
if(a == null)
|
||||||
|
return false;
|
||||||
|
Decal d = a.getTexture();
|
||||||
|
if(d == null)
|
||||||
|
return false;
|
||||||
|
if(img.equals(d.getImage()))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gets a unique identification for the given decal
|
||||||
|
* @param img the decal to be made unique
|
||||||
|
* @return the new unique decal
|
||||||
|
*/
|
||||||
public DecalImage makeUniqueDecal(DecalImage img) {
|
public DecalImage makeUniqueDecal(DecalImage img) {
|
||||||
if (countDecalUsage(img) <= 1) {
|
if (countDecalUsage(img) <= 1) {
|
||||||
return img;
|
return img;
|
||||||
@ -231,26 +297,54 @@ public class OpenRocketDocument implements ComponentChangeListener {
|
|||||||
return decalRegistry.makeUniqueImage(img);
|
return decalRegistry.makeUniqueImage(img);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gets the decal image from an attachment
|
||||||
|
* @param a the attachment
|
||||||
|
* @return the image from the attachment
|
||||||
|
*/
|
||||||
public DecalImage getDecalImage(Attachment a) {
|
public DecalImage getDecalImage(Attachment a) {
|
||||||
return decalRegistry.getDecalImage(a);
|
return decalRegistry.getDecalImage(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gets a list of simulations in the document
|
||||||
|
* @return the simulations in the document
|
||||||
|
*/
|
||||||
public List<Simulation> getSimulations() {
|
public List<Simulation> getSimulations() {
|
||||||
return simulations.clone();
|
return simulations.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gets the number of simulations in the document
|
||||||
|
* @return the number of simulations in the document
|
||||||
|
*/
|
||||||
public int getSimulationCount() {
|
public int getSimulationCount() {
|
||||||
return simulations.size();
|
return simulations.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the the Nth simulation from the document
|
||||||
|
* @param n simulation index
|
||||||
|
* @return the Nth simulation from the document, null if there's none
|
||||||
|
*/
|
||||||
public Simulation getSimulation(int n) {
|
public Simulation getSimulation(int n) {
|
||||||
return simulations.get(n);
|
return simulations.get(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gets the index of the given simulation
|
||||||
|
* @param simulation the simulation being searched
|
||||||
|
* @return the index of the simulation in the document
|
||||||
|
*/
|
||||||
public int getSimulationIndex(Simulation simulation) {
|
public int getSimulationIndex(Simulation simulation) {
|
||||||
return simulations.indexOf(simulation);
|
return simulations.indexOf(simulation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* adds simulation into the document
|
||||||
|
* fires document change event
|
||||||
|
* @param simulation the simulation to be added
|
||||||
|
*/
|
||||||
public void addSimulation(Simulation simulation) {
|
public void addSimulation(Simulation simulation) {
|
||||||
simulations.add(simulation);
|
simulations.add(simulation);
|
||||||
FlightConfigurationId simId = simulation.getId();
|
FlightConfigurationId simId = simulation.getId();
|
||||||
@ -260,33 +354,61 @@ public class OpenRocketDocument implements ComponentChangeListener {
|
|||||||
fireDocumentChangeEvent(new SimulationChangeEvent(simulation));
|
fireDocumentChangeEvent(new SimulationChangeEvent(simulation));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* adds the simulation to the Nth index, overwriting if there is already one
|
||||||
|
* fires change document event
|
||||||
|
* @param simulation the simulation to be added
|
||||||
|
* @param n the index to be added
|
||||||
|
*/
|
||||||
public void addSimulation(Simulation simulation, int n) {
|
public void addSimulation(Simulation simulation, int n) {
|
||||||
simulations.add(n, simulation);
|
simulations.add(n, simulation);
|
||||||
fireDocumentChangeEvent(new SimulationChangeEvent(simulation));
|
fireDocumentChangeEvent(new SimulationChangeEvent(simulation));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* removes the specific simulation from the list
|
||||||
|
* @param simulation the simulation to be removed
|
||||||
|
*/
|
||||||
public void removeSimulation(Simulation simulation) {
|
public void removeSimulation(Simulation simulation) {
|
||||||
simulations.remove(simulation);
|
simulations.remove(simulation);
|
||||||
fireDocumentChangeEvent(new SimulationChangeEvent(simulation));
|
fireDocumentChangeEvent(new SimulationChangeEvent(simulation));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* removes the Nth simulation from the document
|
||||||
|
* fires document change event
|
||||||
|
* @param n the Nth simulation
|
||||||
|
* @return the removed simulation
|
||||||
|
*/
|
||||||
public Simulation removeSimulation(int n) {
|
public Simulation removeSimulation(int n) {
|
||||||
Simulation simulation = simulations.remove(n);
|
Simulation simulation = simulations.remove(n);
|
||||||
fireDocumentChangeEvent(new SimulationChangeEvent(simulation));
|
fireDocumentChangeEvent(new SimulationChangeEvent(simulation));
|
||||||
return simulation;
|
return simulation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* removes the flight configuration and simulation with the specific id
|
||||||
|
* @param configId
|
||||||
|
*/
|
||||||
public void removeFlightConfigurationAndSimulations(FlightConfigurationId configId) {
|
public void removeFlightConfigurationAndSimulations(FlightConfigurationId configId) {
|
||||||
if (configId == null) {
|
if (configId == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
removeSimulations(configId);
|
||||||
|
rocket.removeFlightConfiguration(configId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* removes all simulations with the specific configId
|
||||||
|
* @param configId the Flight Configuration Id that dictates which simulations shoul be removed
|
||||||
|
*/
|
||||||
|
private void removeSimulations(FlightConfigurationId configId) {
|
||||||
for (Simulation s : getSimulations()) {
|
for (Simulation s : getSimulations()) {
|
||||||
// Assumes modifiable collection - which it is
|
// Assumes modifiable collection - which it is
|
||||||
if (configId.equals(s.getId())) {
|
if (configId.equals(s.getId())) {
|
||||||
removeSimulation(s);
|
removeSimulation(s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rocket.removeFlightConfiguration(configId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -331,42 +453,22 @@ public class OpenRocketDocument implements ComponentChangeListener {
|
|||||||
*/
|
*/
|
||||||
public void addUndoPosition(String description) {
|
public void addUndoPosition(String description) {
|
||||||
|
|
||||||
if (storedDescription != null) {
|
checkDescription(description);
|
||||||
logUndoError("addUndoPosition called while storedDescription=" + storedDescription +
|
|
||||||
" description=" + description);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check whether modifications have been done since last call
|
// Check whether modifications have been done since last call
|
||||||
if (isCleanState()) {
|
if(isCheckNoModification(description))
|
||||||
// No modifications
|
|
||||||
log.info("Adding undo position '" + description + "' to " + this + ", document was in clean state");
|
|
||||||
nextDescription = description;
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
log.info("Adding undo position '" + description + "' to " + this + ", document is in unclean state");
|
log.info("Adding undo position '" + description + "' to " + this + ", document is in unclean state");
|
||||||
|
checkUndoPositionConsistency();
|
||||||
|
addStateToUndoHistory(description);
|
||||||
|
|
||||||
/*
|
maintainMaximumUndoSize();
|
||||||
* Modifications have been made to the rocket. We should be at the end of the
|
}
|
||||||
* undo history, but check for consistency and try to recover.
|
|
||||||
*/
|
/**
|
||||||
if (undoPosition != undoHistory.size() - 1) {
|
*
|
||||||
logUndoError("undo position inconsistency");
|
*/
|
||||||
}
|
private void maintainMaximumUndoSize() {
|
||||||
while (undoPosition < undoHistory.size() - 1) {
|
|
||||||
undoHistory.removeLast();
|
|
||||||
undoDescription.removeLast();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Add the current state to the undo history
|
|
||||||
undoHistory.add(rocket.copyWithOriginalID());
|
|
||||||
undoDescription.add(null);
|
|
||||||
nextDescription = description;
|
|
||||||
undoPosition++;
|
|
||||||
|
|
||||||
|
|
||||||
// Maintain maximum undo size
|
|
||||||
if (undoHistory.size() > UNDO_LEVELS + UNDO_MARGIN && undoPosition > UNDO_MARGIN) {
|
if (undoHistory.size() > UNDO_LEVELS + UNDO_MARGIN && undoPosition > UNDO_MARGIN) {
|
||||||
for (int i = 0; i < UNDO_MARGIN; i++) {
|
for (int i = 0; i < UNDO_MARGIN; i++) {
|
||||||
undoHistory.removeFirst();
|
undoHistory.removeFirst();
|
||||||
@ -375,6 +477,57 @@ public class OpenRocketDocument implements ComponentChangeListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param description
|
||||||
|
*/
|
||||||
|
private void addStateToUndoHistory(String description) {
|
||||||
|
// Add the current state to the undo history
|
||||||
|
undoHistory.add(rocket.copyWithOriginalID());
|
||||||
|
undoDescription.add(null);
|
||||||
|
nextDescription = description;
|
||||||
|
undoPosition++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* checks if there was or not modification, and logs
|
||||||
|
*
|
||||||
|
* @param description the description to be used in the log
|
||||||
|
* @return if there was or not modification
|
||||||
|
*/
|
||||||
|
private boolean isCheckNoModification(String description){
|
||||||
|
if (isCleanState()) {
|
||||||
|
// No modifications
|
||||||
|
log.info("Adding undo position '" + description + "' to " + this + ", document was in clean state");
|
||||||
|
nextDescription = description;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* checks if the document already has a stored undo description
|
||||||
|
* logs if it has
|
||||||
|
*
|
||||||
|
* @param description undo description to be logged
|
||||||
|
*/
|
||||||
|
private void checkDescription(String description) {
|
||||||
|
if (storedDescription != null) {
|
||||||
|
logUndoError("addUndoPosition called while storedDescription=" + storedDescription +
|
||||||
|
" description=" + description);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If modifications have been made to the rocket. We should be at the end of the
|
||||||
|
* undo history, but check for consistency and try to recover.
|
||||||
|
*/
|
||||||
|
private void checkUndoPositionConsistency() {
|
||||||
|
if (undoPosition != undoHistory.size() - 1) {
|
||||||
|
logUndoError("undo position inconsistency");
|
||||||
|
}
|
||||||
|
removeRedoInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -436,18 +589,29 @@ public class OpenRocketDocument implements ComponentChangeListener {
|
|||||||
" undoPosition=" + undoPosition + " undoHistory.size=" + undoHistory.size() +
|
" undoPosition=" + undoPosition + " undoHistory.size=" + undoHistory.size() +
|
||||||
" isClean=" + isCleanState());
|
" isClean=" + isCleanState());
|
||||||
}
|
}
|
||||||
// Remove any redo information if available
|
removeRedoInfo();
|
||||||
while (undoPosition < undoHistory.size() - 1) {
|
setLatestDescription();
|
||||||
undoHistory.removeLast();
|
|
||||||
undoDescription.removeLast();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the latest description
|
|
||||||
undoDescription.set(undoPosition, nextDescription);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fireUndoRedoChangeEvent();
|
fireUndoRedoChangeEvent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the latest description
|
||||||
|
*/
|
||||||
|
private void setLatestDescription() {
|
||||||
|
undoDescription.set(undoPosition, nextDescription);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes any redo information if available
|
||||||
|
*/
|
||||||
|
private void removeRedoInfo() {
|
||||||
|
while (undoPosition < undoHistory.size() - 1) {
|
||||||
|
undoHistory.removeLast();
|
||||||
|
undoDescription.removeLast();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -610,6 +774,7 @@ public class OpenRocketDocument implements ComponentChangeListener {
|
|||||||
undoRedoListeners.remove(listener);
|
undoRedoListeners.remove(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void fireUndoRedoChangeEvent() {
|
private void fireUndoRedoChangeEvent() {
|
||||||
UndoRedoListener[] array = undoRedoListeners.toArray(new UndoRedoListener[0]);
|
UndoRedoListener[] array = undoRedoListeners.toArray(new UndoRedoListener[0]);
|
||||||
for (UndoRedoListener l : array) {
|
for (UndoRedoListener l : array) {
|
||||||
|
@ -8,19 +8,38 @@ import java.io.InputStream;
|
|||||||
|
|
||||||
import net.sf.openrocket.document.Attachment;
|
import net.sf.openrocket.document.Attachment;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* defines a file system attachment
|
||||||
|
* stores the attachment location
|
||||||
|
*/
|
||||||
public class FileSystemAttachment extends Attachment {
|
public class FileSystemAttachment extends Attachment {
|
||||||
|
/** the file location*/
|
||||||
private final File location;
|
private final File location;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* main constructor,
|
||||||
|
*
|
||||||
|
* @param name name of attachment
|
||||||
|
* @param location File location of attachment
|
||||||
|
*/
|
||||||
public FileSystemAttachment(String name, File location) {
|
public FileSystemAttachment(String name, File location) {
|
||||||
super(name);
|
super(name);
|
||||||
this.location = location;
|
this.location = location;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return the File object with the attachment location
|
||||||
|
*/
|
||||||
public File getLocation() {
|
public File getLocation() {
|
||||||
return location;
|
return location;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
* creates the stream based on the location passed while building
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public InputStream getBytes() throws FileNotFoundException, IOException {
|
public InputStream getBytes() throws FileNotFoundException, IOException {
|
||||||
return new FileInputStream(location);
|
return new FileInputStream(location);
|
||||||
|
@ -12,16 +12,24 @@ public class AxialStage extends ComponentAssembly implements FlightConfigurableC
|
|||||||
private static final Translator trans = Application.getTranslator();
|
private static final Translator trans = Application.getTranslator();
|
||||||
//private static final Logger log = LoggerFactory.getLogger(AxialStage.class);
|
//private static final Logger log = LoggerFactory.getLogger(AxialStage.class);
|
||||||
|
|
||||||
|
/** list of separations to be happening*/
|
||||||
protected FlightConfigurableParameterSet<StageSeparationConfiguration> separations;
|
protected FlightConfigurableParameterSet<StageSeparationConfiguration> separations;
|
||||||
|
/** number of stages */
|
||||||
protected int stageNumber;
|
protected int stageNumber;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* default constructor, builds a rocket with zero stages
|
||||||
|
*/
|
||||||
public AxialStage(){
|
public AxialStage(){
|
||||||
this.separations = new FlightConfigurableParameterSet<StageSeparationConfiguration>( new StageSeparationConfiguration());
|
this.separations = new FlightConfigurableParameterSet<StageSeparationConfiguration>( new StageSeparationConfiguration());
|
||||||
this.relativePosition = Position.AFTER;
|
this.relativePosition = Position.AFTER;
|
||||||
this.stageNumber = 0;
|
this.stageNumber = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
* AxialStage will always accept children
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean allowsChildren() {
|
public boolean allowsChildren() {
|
||||||
return true;
|
return true;
|
||||||
@ -33,6 +41,10 @@ public class AxialStage extends ComponentAssembly implements FlightConfigurableC
|
|||||||
return trans.get("Stage.Stage");
|
return trans.get("Stage.Stage");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gets the separation configuration of the rocket
|
||||||
|
* @return the separation configuration of the rocket
|
||||||
|
*/
|
||||||
public FlightConfigurableParameterSet<StageSeparationConfiguration> getSeparationConfigurations() {
|
public FlightConfigurableParameterSet<StageSeparationConfiguration> getSeparationConfigurations() {
|
||||||
return separations;
|
return separations;
|
||||||
}
|
}
|
||||||
@ -42,7 +54,10 @@ public class AxialStage extends ComponentAssembly implements FlightConfigurableC
|
|||||||
separations.reset(fcid);
|
separations.reset(fcid);
|
||||||
}
|
}
|
||||||
|
|
||||||
// not strictly accurate, but this should provide an acceptable estimate for total vehicle size
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
* not strictly accurate, but this should provide an acceptable estimate for total vehicle size
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Collection<Coordinate> getComponentBounds() {
|
public Collection<Coordinate> getComponentBounds() {
|
||||||
Collection<Coordinate> bounds = new ArrayList<Coordinate>(8);
|
Collection<Coordinate> bounds = new ArrayList<Coordinate>(8);
|
||||||
@ -110,16 +125,28 @@ public class AxialStage extends ComponentAssembly implements FlightConfigurableC
|
|||||||
return this.stageNumber;
|
return this.stageNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
* axialStage is always after
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean isAfter(){
|
public boolean isAfter(){
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns if the object is a launch stage
|
||||||
|
* @return if the object is a launch stage
|
||||||
|
*/
|
||||||
public boolean isLaunchStage(){
|
public boolean isLaunchStage(){
|
||||||
return ( this instanceof ParallelStage )
|
return ( this instanceof ParallelStage )
|
||||||
||( getRocket().getBottomCoreStage().equals(this));
|
||( getRocket().getBottomCoreStage().equals(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sets the stage number
|
||||||
|
* @param newStageNumber
|
||||||
|
*/
|
||||||
public void setStageNumber(final int newStageNumber) {
|
public void setStageNumber(final int newStageNumber) {
|
||||||
this.stageNumber = newStageNumber;
|
this.stageNumber = newStageNumber;
|
||||||
}
|
}
|
||||||
@ -138,12 +165,21 @@ public class AxialStage extends ComponentAssembly implements FlightConfigurableC
|
|||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* method used for debugging separation
|
||||||
|
* @return a string that represents the debug message of separation
|
||||||
|
*/
|
||||||
public String toDebugSeparation() {
|
public String toDebugSeparation() {
|
||||||
StringBuilder buff = new StringBuilder();
|
StringBuilder buff = new StringBuilder();
|
||||||
buff.append( this.separations.toDebug() );
|
buff.append( this.separations.toDebug() );
|
||||||
return buff.toString();
|
return buff.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gets the previous stage installed in the rockets
|
||||||
|
* returns null if this is the first stage
|
||||||
|
* @return the previous stage in the rocket
|
||||||
|
*/
|
||||||
public AxialStage getPreviousStage() {
|
public AxialStage getPreviousStage() {
|
||||||
if( this instanceof ParallelStage ){
|
if( this instanceof ParallelStage ){
|
||||||
return (AxialStage) this.parent;
|
return (AxialStage) this.parent;
|
||||||
|
@ -2,7 +2,7 @@ package net.sf.openrocket.rocketcomponent;
|
|||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* FlightConfigurationID is a very minimal wrapper class used to identify a given flight configuration for various components and options.
|
* FlightConfigurationID is a very minimal wrapper class used to identify a given flight configuration for various components and options.
|
||||||
* It is intended to provide better visibility and traceability by more specific type safety -- this class replaces a
|
* It is intended to provide better visibility and traceability by more specific type safety -- this class replaces a
|
||||||
* straight-up <code>String</code> Key in previous implementations.
|
* straight-up <code>String</code> Key in previous implementations.
|
||||||
@ -19,10 +19,17 @@ public final class FlightConfigurationId implements Comparable<FlightConfigurati
|
|||||||
public final static FlightConfigurationId ERROR_FCID = new FlightConfigurationId( FlightConfigurationId.ERROR_UUID);
|
public final static FlightConfigurationId ERROR_FCID = new FlightConfigurationId( FlightConfigurationId.ERROR_UUID);
|
||||||
public final static FlightConfigurationId DEFAULT_VALUE_FCID = new FlightConfigurationId( FlightConfigurationId.DEFAULT_VALUE_UUID );
|
public final static FlightConfigurationId DEFAULT_VALUE_FCID = new FlightConfigurationId( FlightConfigurationId.DEFAULT_VALUE_UUID );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* default constructor, builds with an unique random ID
|
||||||
|
*/
|
||||||
public FlightConfigurationId() {
|
public FlightConfigurationId() {
|
||||||
this(UUID.randomUUID());
|
this(UUID.randomUUID());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* builds the id with the given String
|
||||||
|
* @param _str te string to be made into the id
|
||||||
|
*/
|
||||||
public FlightConfigurationId(final String _str) {
|
public FlightConfigurationId(final String _str) {
|
||||||
UUID candidate;
|
UUID candidate;
|
||||||
if(_str == null || "".equals(_str)){
|
if(_str == null || "".equals(_str)){
|
||||||
@ -37,6 +44,10 @@ public final class FlightConfigurationId implements Comparable<FlightConfigurati
|
|||||||
this.key = candidate;
|
this.key = candidate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* builds he id with the given UUID object
|
||||||
|
* @param _val the UUID to be made into the id
|
||||||
|
*/
|
||||||
public FlightConfigurationId(final UUID _val) {
|
public FlightConfigurationId(final UUID _val) {
|
||||||
if (null == _val){
|
if (null == _val){
|
||||||
this.key = FlightConfigurationId.ERROR_UUID;
|
this.key = FlightConfigurationId.ERROR_UUID;
|
||||||
@ -45,6 +56,10 @@ public final class FlightConfigurationId implements Comparable<FlightConfigurati
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
* considers equals ids with the same key
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object anObject) {
|
public boolean equals(Object anObject) {
|
||||||
if (!(anObject instanceof FlightConfigurationId)) {
|
if (!(anObject instanceof FlightConfigurationId)) {
|
||||||
@ -55,32 +70,65 @@ public final class FlightConfigurationId implements Comparable<FlightConfigurati
|
|||||||
return this.key.equals(otherFCID.key);
|
return this.key.equals(otherFCID.key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
public String toShortKey(){
|
public String toShortKey(){
|
||||||
if( hasError() ){
|
if( hasError() )
|
||||||
return FlightConfigurationId.ERROR_KEY_NAME;
|
return FlightConfigurationId.ERROR_KEY_NAME;
|
||||||
}else if( this.key == FlightConfigurationId.DEFAULT_VALUE_UUID){
|
if( isDefaultId())
|
||||||
return FlightConfigurationId.DEFAULT_VALUE_NAME;
|
return FlightConfigurationId.DEFAULT_VALUE_NAME;
|
||||||
}else{
|
return this.key.toString().substring(0,8);
|
||||||
return this.key.toString().substring(0,8);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//extracted this method because maybe, just maybe, this info could be used somewhere else
|
||||||
|
/**
|
||||||
|
* gets if the id is the default
|
||||||
|
* @return if the id is default
|
||||||
|
*/
|
||||||
|
private boolean isDefaultId() {
|
||||||
|
return this.key == FlightConfigurationId.DEFAULT_VALUE_UUID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns the whole key in the id
|
||||||
|
* @return the full key of the id
|
||||||
|
*/
|
||||||
public String toFullKey(){
|
public String toFullKey(){
|
||||||
return this.key.toString();
|
return this.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
* uses the key hash code
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return this.key.hashCode();
|
return this.key.hashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* checks if the key is the ERROR_UUID flag
|
||||||
|
* @return if the id has error
|
||||||
|
*/
|
||||||
public boolean hasError(){
|
public boolean hasError(){
|
||||||
return (ERROR_UUID == this.key);
|
return (ERROR_UUID == this.key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* checks if the key from the id is valid
|
||||||
|
* @return if the id is valid or not
|
||||||
|
*/
|
||||||
public boolean isValid() {
|
public boolean isValid() {
|
||||||
return !hasError();
|
return !hasError();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
* same as get full id
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return this.key.toString();
|
return this.key.toString();
|
||||||
@ -91,6 +139,10 @@ public final class FlightConfigurationId implements Comparable<FlightConfigurati
|
|||||||
return this.key.compareTo( other.key);
|
return this.key.compareTo( other.key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* used for debuggin, gets the short key
|
||||||
|
* @return the short key version of the id
|
||||||
|
*/
|
||||||
public String toDebug(){
|
public String toDebug(){
|
||||||
return this.toShortKey();
|
return this.toShortKey();
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,11 @@ import net.sf.openrocket.util.SafetyMutex;
|
|||||||
import net.sf.openrocket.util.StateChangeListener;
|
import net.sf.openrocket.util.StateChangeListener;
|
||||||
import net.sf.openrocket.util.UniqueID;
|
import net.sf.openrocket.util.UniqueID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Master class that defines components of rockets
|
||||||
|
* almost all hardware from the rocket extends from this abstract class
|
||||||
|
*
|
||||||
|
*/
|
||||||
public abstract class RocketComponent implements ChangeSource, Cloneable, Iterable<RocketComponent> {
|
public abstract class RocketComponent implements ChangeSource, Cloneable, Iterable<RocketComponent> {
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
private static final Logger log = LoggerFactory.getLogger(RocketComponent.class);
|
private static final Logger log = LoggerFactory.getLogger(RocketComponent.class);
|
||||||
@ -41,7 +45,7 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
|
|||||||
//private static final Translator trans = Application.getTranslator();
|
//private static final Translator trans = Application.getTranslator();
|
||||||
|
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* Text is suitable to the form
|
* Text is suitable to the form
|
||||||
* Position relative to: <title>
|
* Position relative to: <title>
|
||||||
*/
|
*/
|
||||||
@ -351,6 +355,10 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* appends the debug string of the component into the passed builder
|
||||||
|
* @param sb String builder to be appended
|
||||||
|
*/
|
||||||
private void toDebugString(StringBuilder sb) {
|
private void toDebugString(StringBuilder sb) {
|
||||||
sb.append(this.getClass().getSimpleName()).append('@').append(System.identityHashCode(this));
|
sb.append(this.getClass().getSimpleName()).append('@').append(System.identityHashCode(this));
|
||||||
sb.append("[\"").append(this.getName()).append('"');
|
sb.append("[\"").append(this.getName()).append('"');
|
||||||
@ -958,6 +966,10 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns the axial offset of the component
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
public double getAxialOffset() {
|
public double getAxialOffset() {
|
||||||
mutex.verify();
|
mutex.verify();
|
||||||
return this.asPositionValue(this.relativePosition);
|
return this.asPositionValue(this.relativePosition);
|
||||||
@ -2081,6 +2093,7 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// debug functions
|
||||||
public String toDebugName(){
|
public String toDebugName(){
|
||||||
return this.getName()+"<"+this.getClass().getSimpleName()+">("+this.getID().substring(0,8)+")";
|
return this.getName()+"<"+this.getClass().getSimpleName()+">("+this.getID().substring(0,8)+")";
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user