first commit

This commit is contained in:
Your Name
2022-10-20 20:29:11 +08:00
commit 4d531f8044
3238 changed files with 1387862 additions and 0 deletions

View File

@@ -0,0 +1,178 @@
// FGFSDemo.java - Simple demo application.
import java.io.IOException;
import java.util.HashMap;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import org.flightgear.fgfsclient.FGFSConnection;
import org.flightgear.fgfsclient.PropertyPage;
/**
* Simple GUI demo.
*
* <p>This demo connects to a running FlightGear process and displays
* the current altitude, longitude, and latitude in a GUI window, with
* updates every second.</p>
*
* <p>Usage:</p>
*
* <blockquote><pre>
* fgfs --telnet=9000
* java FGFSDemo localhost 9000
* </pre></blockquote>
*/
public class FGFSDemo
extends JFrame
{
public FGFSDemo (String host, int port)
throws IOException
{
super("FlightGear Client Console");
fgfs = new FGFSConnection(host, port);
tabs = new JTabbedPane();
pages = new HashMap();
PropertyPage page = new PropertyPage(fgfs, "Simulation");
page.addField("/sim/aircraft", "Aircraft:");
page.addField("/sim/startup/airport-id", "Airport ID:");
page.addField("/sim/time/gmt", "Current time (GMT):");
page.addField("/sim/startup/trim", "Trim on ground (true/false):");
page.addField("/sim/sound/audible", "Sound enabled (true/false):");
page.addField("/sim/startup/browser-app", "Web browser:");
addPage(page);
page = new PropertyPage(fgfs, "View");
page.addField("/sim/view-mode", "View mode:");
page.addField("/sim/current-view/field-of-view",
"Field of view (deg):");
page.addField("/sim/current-view/pitch-offset-deg",
"View pitch offset (deg):");
page.addField("/sim/current-view/heading-offset-deg",
"View heading offset (deg):");
addPage(page);
page = new PropertyPage(fgfs, "Location");
page.addField("/position/altitude-ft", "Altitude (ft):");
page.addField("/position/longitude-deg", "Longitude (deg):");
page.addField("/position/latitude-deg", "Latitude (deg):");
page.addField("/orientation/roll-deg", "Roll (deg):");
page.addField("/orientation/pitch-deg", "Pitch (deg):");
page.addField("/orientation/heading-deg", "Heading (deg):");
addPage(page);
page = new PropertyPage(fgfs, "Weather");
page.addField("/environment/wind-from-heading-deg",
"Wind direction (deg FROM):");
page.addField("/environment/params/base-wind-speed-kt",
"Wind speed (kt):");
page.addField("/environment/params/gust-wind-speed-kt",
"Maximum gust (kt):");
page.addField("/environment/wind-from-down-fps",
"Updraft (fps):");
page.addField("/environment/temperature-degc", "Temperature (degC):");
page.addField("/environment/dewpoint-degc", "Dewpoint (degC):");
page.addField("/environment/pressure-sea-level-inhg",
"Altimeter setting (inHG):");
addPage(page);
page = new PropertyPage(fgfs, "Clouds");
page.addField("/environment/clouds/layer[0]/type",
"Layer 0 type:");
page.addField("/environment/clouds/layer[0]/elevation-ft",
"Layer 0 height (ft):");
page.addField("/environment/clouds/layer[0]/thickness-ft",
"Layer 0 thickness (ft):");
page.addField("/environment/clouds/layer[1]/type",
"Layer 1 type:");
page.addField("/environment/clouds/layer[1]/elevation-ft",
"Layer 1 height (ft):");
page.addField("/environment/clouds/layer[1]/thickness-ft",
"Layer 1 thickness (ft):");
page.addField("/environment/clouds/layer[2]/type",
"Layer 2 type:");
page.addField("/environment/clouds/layer[2]/elevation-ft",
"Layer 2 height (ft):");
page.addField("/environment/clouds/layer[2]/thickness-ft",
"Layer 2 thickness (ft):");
page.addField("/environment/clouds/layer[3]/type",
"Layer 3 type:");
page.addField("/environment/clouds/layer[3]/elevation-ft",
"Layer 3 height (ft):");
page.addField("/environment/clouds/layer[3]/thickness-ft",
"Layer 3 thickness (ft):");
page.addField("/environment/clouds/layer[4]/type",
"Layer 4 type:");
page.addField("/environment/clouds/layer[4]/elevation-ft",
"Layer 4 height (ft):");
page.addField("/environment/clouds/layer[4]/thickness-ft",
"Layer 4 thickness (ft):");
addPage(page);
page = new PropertyPage(fgfs, "Velocities");
page.addField("/velocities/airspeed-kt", "Airspeed (kt):");
page.addField("/velocities/speed-down-fps", "Descent speed (fps):");
addPage(page);
getContentPane().add(tabs);
new Thread(new Updater()).start();
}
private void addPage (PropertyPage page)
{
tabs.add(page.getName(), new JScrollPane(page));
pages.put(page.getName(), page);
}
private FGFSConnection fgfs;
private JTabbedPane tabs;
private HashMap pages;
public static void main (String args[])
throws Exception
{
if (args.length != 2) {
System.err.println("Usage: FGFSDemo <host> <port>");
System.exit(2);
}
FGFSDemo gui = new FGFSDemo(args[0], Integer.parseInt(args[1]));
gui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
gui.pack();
gui.show();
}
class Updater
implements Runnable
{
public void run ()
{
while (true) {
int index = tabs.getSelectedIndex();
if (index > -1) {
String name = tabs.getTitleAt(index);
PropertyPage page = (PropertyPage)pages.get(name);
try {
page.update();
} catch (IOException e) {
}
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
}
}
}
}
// end of FGFSDemo.java

View File

@@ -0,0 +1,317 @@
// FGFSConnection.java - client library for the FlightGear flight simulator.
// Started June 2002 by David Megginson, david@megginson.com
// This library is in the Public Domain and comes with NO WARRANTY.
package org.flightgear.fgfsclient;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;
/**
* A connection to a running instance of FlightGear.
*
* <p>This class currently uses the FlightGear telnet interface,
* though it may be modified to use a different TCP/IP interface in
* the future. Client applications can use this library to examine
* and modify internal FlightGear properties.</p>
*
* <p>To start FlightGear with the telnet server activated, use a
* command like this (to listen on port 9000):</p>
*
* <blockquote><pre>
* fgfs --telnet=9000
* </pre></blockquote>
*
* <p>Then create a connection to FlightGear from your Java client
* application:</p>
*
* <blockquote><pre>
* FGFSConnection fgfs = new FGFSConnection("localhost", 9000);
* </pre></blockquote>
*
* <p>Now you can use the connection to get and set FlightGear
* properties:</p>
*
* <blockquote><pre>
* double altitude = fgfs.getDouble("/position/altitude-ft");
* fgfs.setDouble("/orientation/heading", 270.0);
* </pre></blockquote>
*
* <p>All methods that communicate directly with FlightGear are
* synchronized, since they must work over a single telnet
* connection.</p>
*/
public class FGFSConnection
{
////////////////////////////////////////////////////////////////////
// Constructor.
////////////////////////////////////////////////////////////////////
/**
* Constructor.
*
* <p>Create a new connection to a running FlightGear program.
* The program must have been started with the --telnet=&lt;port&gt;
* command-line option.</p>
*
* @param host The host name or IP address to connect to.
* @param port The port number where FlightGear is listening.
* @exception IOException If it is not possible to connect to
* a FlightGear process.
*/
public FGFSConnection (String host, int port)
throws IOException
{
socket = new Socket(host, port);
in =
new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(), true);
out.println("data\r");
}
////////////////////////////////////////////////////////////////////
// Primitive getter and setter.
////////////////////////////////////////////////////////////////////
/**
* Close the connection to FlightGear.
*
* <p>The client application should always invoke this method when
* it has finished with a connection, to allow cleanup.</p>
*
* @exception IOException If there is an error closing the
* connection.
*/
public synchronized void close ()
throws IOException
{
out.println("quit\r");
in.close();
out.close();
socket.close();
}
/**
* Get the raw string value for a property.
*
* <p>This is the primitive method for all property lookup;
* everything comes in as a string, and is only later converted by
* methods like {@link #getDouble(String)}. As a result, if you
* need the value as a string anyway, it makes sense to use this
* method directly rather than forcing extra conversions.</p>
*
* @param name The FlightGear property name to look up.
* @return The property value as a string (non-existant properties
* return the empty string).
* @exception IOException If there is an error communicating with
* FlightGear or if the connection is lost.
* @see #getBoolean(String)
* @see #getInt(String)
* @see #getLong(String)
* @see #getFloat(String)
* @see #getDouble(String)
*/
public synchronized String get (String name)
throws IOException
{
out.println("get " + name + '\r');
return in.readLine();
}
/**
* Set the raw string value for a property.
*
* <p>This is the primitive method for all property modification;
* everything goes out as a string, after it has been converted by
* methods like {@link #setDouble(String,double)}. As a result, if
* you have the value as a string already, it makes sense to use
* this method directly rather than forcing extra conversions.</p>
*
* @param name The FlightGear property name to modify or create.
* @param value The new value for the property, as a string.
* @exception IOException If there is an error communicating with
* FlightGear or if the connection is lost.
* @see #setBoolean(String,boolean)
* @see #setInt(String,int)
* @see #setLong(String,long)
* @see #setFloat(String,float)
* @see #setDouble(String,double)
*/
public synchronized void set (String name, String value)
throws IOException
{
out.println("set " + name + ' ' + value + '\r');
}
////////////////////////////////////////////////////////////////////
// Derived getters and setters.
////////////////////////////////////////////////////////////////////
/**
* Get a property value as a boolean.
*
* @param name The property name to look up.
* @return The property value as a boolean.
* @see #get(String)
*/
public boolean getBoolean (String name)
throws IOException
{
return get(name).equals("true");
}
/**
* Get a property value as an integer.
*
* @param name The property name to look up.
* @return The property value as an int.
* @see #get(String)
*/
public int getInt (String name)
throws IOException
{
return Integer.parseInt(get(name));
}
/**
* Get a property value as a long.
*
* @param name The property name to look up.
* @return The property value as a long.
* @see #get(String)
*/
public long getLong (String name)
throws IOException
{
return Long.parseLong(get(name));
}
/**
* Get a property value as a float.
*
* @param name The property name to look up.
* @return The property value as a float.
* @see #get(String)
*/
public float getFloat (String name)
throws IOException
{
return Float.parseFloat(get(name));
}
/**
* Get a property value as a double.
*
* @param name The property name to look up.
* @return The property value as a double.
* @see #get(String)
*/
public double getDouble (String name)
throws IOException
{
return Double.parseDouble(get(name));
}
/**
* Set a property value from a boolean.
*
* @param name The property name to create or modify.
* @param value The new property value as a boolean.
* @see #set(String,String)
*/
public void setBoolean (String name, boolean value)
throws IOException
{
set(name, (value ? "true" : "false"));
}
/**
* Set a property value from an int.
*
* @param name The property name to create or modify.
* @param value The new property value as an int.
* @see #set(String,String)
*/
public void setInt (String name, int value)
throws IOException
{
set(name, Integer.toString(value));
}
/**
* Set a property value from a long.
*
* @param name The property name to create or modify.
* @param value The new property value as a long.
* @see #set(String,String)
*/
public void setLong (String name, long value)
throws IOException
{
set(name, Long.toString(value));
}
/**
* Set a property value from a float.
*
* @param name The property name to create or modify.
* @param value The new property value as a float.
* @see #set(String,String)
*/
public void setFloat (String name, float value)
throws IOException
{
set(name, Float.toString(value));
}
/**
* Set a property value from a double.
*
* @param name The property name to create or modify.
* @param value The new property value as a double.
* @see #set(String,String)
*/
public void setDouble (String name, double value)
throws IOException
{
set(name, Double.toString(value));
}
////////////////////////////////////////////////////////////////////
// Internal state.
////////////////////////////////////////////////////////////////////
private Socket socket;
private BufferedReader in;
private PrintWriter out;
}
// end of FGFSConnection.java

View File

@@ -0,0 +1,59 @@
package org.flightgear.fgfsclient;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class PropertyField
extends JPanel
{
public PropertyField (FGFSConnection fgfs,
String name,
String caption)
{
this.fgfs = fgfs;
propertyName = name;
label = new JLabel(caption);
value = new JTextField(10);
value.addActionListener(new ActionListener () {
public void actionPerformed (ActionEvent ev)
{
try {
modify();
grabFocus();
} catch (IOException ex) {
System.err.println("Failed to update " + propertyName);
}
}
});
add(label);
add(value);
}
public void update ()
throws IOException
{
if (!value.hasFocus())
value.setText(fgfs.get(propertyName));
}
public void modify ()
throws IOException
{
fgfs.set(propertyName, value.getText());
}
private FGFSConnection fgfs;
private String propertyName;
private JLabel label;
private JTextField value;
}

View File

@@ -0,0 +1,48 @@
package org.flightgear.fgfsclient;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import javax.swing.BoxLayout;
import javax.swing.JPanel;
public class PropertyPage
extends JPanel
{
public PropertyPage (FGFSConnection fgfs, String name)
{
this.fgfs = fgfs;
this.name = name;
fields = new ArrayList();
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
}
public String getName ()
{
return name;
}
public void addField (String name, String caption)
{
PropertyField field = new PropertyField(fgfs, name, caption);
add(field);
fields.add(field);
}
public void update ()
throws IOException
{
Iterator it = fields.iterator();
while (it.hasNext()) {
((PropertyField)it.next()).update();
}
}
private FGFSConnection fgfs;
private String name;
private ArrayList fields;
}

View File

@@ -0,0 +1,70 @@
package org.flightgear.fgfsclient;
import java.io.IOException;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JTextField;
public final class Util
{
public static void forceConnection (JFrame frame, final FGFSConnection fgfs)
{
while (!fgfs.isConnected()) {
final JDialog dialog =
new JDialog(frame, "Connect to FlightGear", true);
dialog.getContentPane().setLayout(new GridLayout(3, 2));
dialog.getContentPane().add(new JLabel("Host:"));
final JTextField hostField = new JTextField(20);
hostField.setText(fgfs.getHost());
dialog.getContentPane().add(hostField);
dialog.getContentPane().add(new JLabel("Port:"));
final JTextField portField = new JTextField(5);
portField.setText(Integer.toString(fgfs.getPort()));
dialog.getContentPane().add(portField);
JButton connectButton = new JButton("Connect");
connectButton.addActionListener(new ActionListener() {
public void actionPerformed (ActionEvent ev)
{
try {
fgfs.open(hostField.getText(),
Integer.parseInt(portField.getText()));
} catch (IOException ex) {
JOptionPane.showMessageDialog(dialog, ex.getMessage(),
"Alert", JOptionPane.ERROR_MESSAGE);
}
dialog.hide();
}
});
dialog.getContentPane().add(connectButton);
dialog.getRootPane().setDefaultButton(connectButton);
JButton quitButton = new JButton("Quit");
quitButton.addActionListener(new ActionListener() {
public void actionPerformed (ActionEvent ev)
{
System.exit(0); // FIXME
}
});
dialog.getContentPane().add(quitButton);
dialog.pack();
dialog.show();
}
}
}