mirror of
https://github.com/brendanhaines/RasPi.git
synced 2025-08-01 13:22:56 -06:00
Adds Ground Station
This commit is contained in:
BIN
GroundStation/GroundStation.class
Normal file
BIN
GroundStation/GroundStation.class
Normal file
Binary file not shown.
449
GroundStation/GroundStation.java
Normal file
449
GroundStation/GroundStation.java
Normal file
@@ -0,0 +1,449 @@
|
||||
// graphics
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import javax.swing.*;
|
||||
import java.awt.image.*;
|
||||
import javax.swing.border.*;
|
||||
|
||||
// communication
|
||||
import java.lang.*;
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
|
||||
/**
|
||||
* Replaces GroundStation.java
|
||||
* Written by Brendan Haines
|
||||
*/
|
||||
class GroundStation implements ActionListener, Runnable {
|
||||
|
||||
//////////////////
|
||||
///// FIELDS /////
|
||||
//////////////////
|
||||
|
||||
/** string to hold the connection type */
|
||||
private String connectionType = "";
|
||||
/** boolean to hold connected/disconnected status */
|
||||
private boolean connectionStatus = false;
|
||||
/** TCP/IP socket for communication */
|
||||
private Socket tcpSocket;
|
||||
/** input buffer handling for tcpSocket */
|
||||
private BufferedReader tcpIn;
|
||||
/** output handler for tcpSocket */
|
||||
private PrintWriter tcpOut;
|
||||
/** thread to listen to tcpSocket */
|
||||
private Thread tcpListener;
|
||||
|
||||
// Main GUI components
|
||||
/** window to hold GUI */
|
||||
private JFrame mainFrame;
|
||||
/** panel to fill mainFrame */
|
||||
private JPanel mainPanel;
|
||||
|
||||
/** panel to hold connection options */
|
||||
private JPanel connectionPanel;
|
||||
/** connection options panel */
|
||||
private JPanel connectionOptionsPanel;
|
||||
/** connection type selection box */
|
||||
private JComboBox connectionTypeComboBox;
|
||||
/** card layout container for different connection types */
|
||||
private JPanel connectionTypePanel;
|
||||
/** JPanel to hold TCP/IP settings */
|
||||
private JPanel tcpPanel;
|
||||
/** label for host address field */
|
||||
private JLabel tcpHostAddressFieldLabel;
|
||||
/** text field for host address */
|
||||
private JTextField tcpHostAddressField;
|
||||
/** label for port field */
|
||||
private JLabel tcpHostPortFieldLabel;
|
||||
/** text field for port of socket */
|
||||
private JTextField tcpHostPortField;
|
||||
/** connect/disconnect button */
|
||||
private JButton connectButton;
|
||||
|
||||
/** tabbed pane to hold many features */
|
||||
private JTabbedPane tabbedPane;
|
||||
/** command line interface tab */
|
||||
private JPanel cliPanel;
|
||||
/** panel to hold display options */
|
||||
private JPanel cliOptionsPanel;
|
||||
/** checkbox to display confirmation/replies from pi */
|
||||
private JCheckBox cliShowReceivedCheckBox;
|
||||
/** scrolling pane to hold command area */
|
||||
private JScrollPane cliCommandScrollPane;
|
||||
/** text area to display commands */
|
||||
private JTextArea cliCommandArea;
|
||||
/** panel to hold input stuff */
|
||||
private JPanel cliInputPanel;
|
||||
/** text field to enter commands */
|
||||
private JTextField cliInputField;
|
||||
/** send command button */
|
||||
private JButton cliInputButton;
|
||||
/** control panel */
|
||||
private JPanel controlPanel;
|
||||
/** arm/disarm flight controller button */
|
||||
private JButton armDisarmButton;
|
||||
/** calibrate IMU button */
|
||||
private JButton calibrateImuButton;
|
||||
/** motor testing tab */
|
||||
private JPanel motorTestPanel;
|
||||
/** placeholder */
|
||||
private JLabel motorTestPlaceholder;
|
||||
|
||||
////////////////////////
|
||||
///// CONSTRUCTORS /////
|
||||
////////////////////////
|
||||
|
||||
public GroundStation() {
|
||||
setupWindow();
|
||||
}
|
||||
|
||||
///////////////////
|
||||
///// METHODS /////
|
||||
///////////////////
|
||||
|
||||
/**
|
||||
* sets up GUI
|
||||
*/
|
||||
private void setupWindow() {
|
||||
mainFrame = new JFrame( "PiCopter Ground Station" );
|
||||
mainFrame.setResizable( true );
|
||||
mainFrame.setDefaultCloseOperation( JFrame.DISPOSE_ON_CLOSE );
|
||||
|
||||
mainPanel = new JPanel();
|
||||
mainPanel.setLayout( new BorderLayout() );
|
||||
|
||||
setupConnectionPanel();
|
||||
setupTabbedPane();
|
||||
|
||||
mainPanel.add( connectionPanel, BorderLayout.NORTH );
|
||||
mainPanel.add( tabbedPane, BorderLayout.CENTER );
|
||||
|
||||
mainFrame.add( mainPanel );
|
||||
|
||||
mainFrame.pack();
|
||||
mainFrame.setVisible( true );
|
||||
}
|
||||
|
||||
/**
|
||||
* sets up the connection panel
|
||||
*/
|
||||
private void setupConnectionPanel() {
|
||||
connectionPanel = new JPanel( new BorderLayout() );
|
||||
connectionPanel.setBorder( BorderFactory.createTitledBorder( "connection options" ) );
|
||||
connectionOptionsPanel = new JPanel( new FlowLayout() );
|
||||
|
||||
connectionTypeComboBox = new JComboBox();
|
||||
connectionTypeComboBox.addItem( "TCP/IP" );
|
||||
connectionTypeComboBox.setSelectedIndex( 0 );
|
||||
connectionOptionsPanel.add( connectionTypeComboBox );
|
||||
|
||||
connectionTypePanel = new JPanel( new CardLayout() );
|
||||
|
||||
tcpPanel = new JPanel( new FlowLayout() );
|
||||
|
||||
tcpHostAddressFieldLabel = new JLabel( "Host Address:" );
|
||||
tcpHostAddressField = new JTextField();
|
||||
tcpHostAddressField.setColumns( 10 );
|
||||
tcpHostAddressField.setText( "192.168.42.1" );
|
||||
tcpHostPortFieldLabel = new JLabel( "Port:" );
|
||||
tcpHostPortField = new JTextField();
|
||||
tcpHostPortField.setColumns( 6 );
|
||||
tcpHostPortField.setText( "51717" );
|
||||
|
||||
tcpPanel.add( tcpHostAddressFieldLabel );
|
||||
tcpPanel.add( tcpHostAddressField );
|
||||
tcpPanel.add( tcpHostPortFieldLabel );
|
||||
tcpPanel.add( tcpHostPortField );
|
||||
|
||||
connectionTypePanel.add( tcpPanel, "TCP/IP" );
|
||||
|
||||
connectionOptionsPanel.add( connectionTypePanel );
|
||||
connectionPanel.add( connectionOptionsPanel, BorderLayout.NORTH );
|
||||
|
||||
connectButton = new JButton( "connect" );
|
||||
connectButton.addActionListener( this );
|
||||
connectionPanel.add( connectButton, BorderLayout.SOUTH );
|
||||
}
|
||||
|
||||
/**
|
||||
* sets up tabs
|
||||
*/
|
||||
private void setupTabbedPane() {
|
||||
tabbedPane = new JTabbedPane();
|
||||
|
||||
setupCliTab();
|
||||
setupControlTab();
|
||||
setupMotorTestTab();
|
||||
|
||||
tabbedPane.add( cliPanel, "CLI", 0 );
|
||||
tabbedPane.add( controlPanel, "Control", 1 );
|
||||
tabbedPane.add( motorTestPanel, "Motor Testing", 2 );
|
||||
tabbedPane.setEnabledAt( 1, false );
|
||||
tabbedPane.setEnabledAt( 2, false );
|
||||
}
|
||||
|
||||
/**
|
||||
* sets up command line interface tab
|
||||
*/
|
||||
private void setupCliTab() {
|
||||
cliPanel = new JPanel();
|
||||
cliPanel.setLayout( new BorderLayout() );
|
||||
|
||||
cliOptionsPanel = new JPanel();
|
||||
cliOptionsPanel.setLayout( new FlowLayout( FlowLayout.LEFT ) );
|
||||
|
||||
cliShowReceivedCheckBox = new JCheckBox( "show receive" );
|
||||
cliShowReceivedCheckBox.setSelected( true );
|
||||
cliShowReceivedCheckBox.addActionListener( this );
|
||||
cliOptionsPanel.add( cliShowReceivedCheckBox );
|
||||
|
||||
cliCommandArea = new JTextArea();
|
||||
cliCommandArea.setEditable( false );
|
||||
cliCommandScrollPane = new JScrollPane( cliCommandArea );
|
||||
cliCommandScrollPane.setPreferredSize( new Dimension( 400, 200 ) );
|
||||
new SmartScroller( cliCommandScrollPane );
|
||||
|
||||
cliInputPanel = new JPanel();
|
||||
cliInputPanel.setLayout( new BorderLayout() );
|
||||
cliInputField = new JTextField();
|
||||
cliInputField.addActionListener( this );
|
||||
cliInputButton = new JButton( "send" );
|
||||
cliInputButton.addActionListener( this );
|
||||
cliInputPanel.add( cliInputField, BorderLayout.CENTER );
|
||||
cliInputPanel.add( cliInputButton, BorderLayout.EAST );
|
||||
|
||||
cliPanel.add( cliOptionsPanel, BorderLayout.NORTH );
|
||||
cliPanel.add( cliCommandScrollPane, BorderLayout.CENTER );
|
||||
cliPanel.add( cliInputPanel, BorderLayout.SOUTH );
|
||||
}
|
||||
|
||||
/**
|
||||
* sets up control panel tab
|
||||
*/
|
||||
private void setupControlTab() {
|
||||
controlPanel = new JPanel( new FlowLayout( FlowLayout.LEFT ) );
|
||||
|
||||
armDisarmButton = new JButton( "arm" );
|
||||
armDisarmButton.addActionListener( this );
|
||||
|
||||
calibrateImuButton = new JButton( "calibrate IMU" );
|
||||
calibrateImuButton.addActionListener( this );
|
||||
|
||||
controlPanel.add( armDisarmButton);
|
||||
controlPanel.add( calibrateImuButton);
|
||||
}
|
||||
|
||||
/**
|
||||
* sets up motor testing tab
|
||||
*/
|
||||
private void setupMotorTestTab() {
|
||||
motorTestPanel = new JPanel();
|
||||
motorTestPanel.setLayout( new BorderLayout() );
|
||||
motorTestPlaceholder = new JLabel( "Motor Test Tab Placeholder" );
|
||||
motorTestPanel.add( motorTestPlaceholder, BorderLayout.NORTH );
|
||||
}
|
||||
|
||||
/**
|
||||
* enables/disables all components in a container
|
||||
* @param container - the container to enable/disable components of
|
||||
* @param enable - boolean value for .setEnabled()
|
||||
*/
|
||||
private void enableComponents( Container container, boolean enable ) {
|
||||
Component[] components = container.getComponents();
|
||||
for( Component component : components ) {
|
||||
component.setEnabled( enable );
|
||||
if (component instanceof Container) {
|
||||
enableComponents( (Container) component, enable );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* actionPerformed method to handle ActionEvents from all buttons and GUI interaction
|
||||
*/
|
||||
public void actionPerformed( ActionEvent evt ) {
|
||||
|
||||
// command line interface
|
||||
if( evt.getSource() == cliInputButton || evt.getSource() == cliInputField ) {
|
||||
String inputText = cliInputField.getText();
|
||||
cliInputField.setText( "" );
|
||||
if( inputText.equals( "" ) ) return; // if cliInput field is empty, do nothing
|
||||
cliCommandArea.append( inputText + "\n" );
|
||||
|
||||
if( inputText.indexOf( "CONNECT" ) == 0 ) {
|
||||
cliCommandArea.append( "--ERROR - connection with command line interface not supported\n");
|
||||
}
|
||||
else if( inputText.indexOf( "DISCONNECT") == 0 ) {
|
||||
disconnect();
|
||||
}
|
||||
else if( inputText.indexOf( "SEND " ) == 0 ) {
|
||||
String sendText = inputText.substring( 5, inputText.length() );
|
||||
cliCommandArea.append( "--SENDING: " + sendText + "\n" );
|
||||
tcpOut.println( sendText );
|
||||
}
|
||||
else if( inputText.indexOf( "CLEAR" ) == 0 ) {
|
||||
cliCommandArea.setText( "" );
|
||||
}
|
||||
|
||||
else {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// connect button
|
||||
else if( evt.getSource() == connectButton && evt.getActionCommand().equals( "connect" ) ) {
|
||||
if( connectionTypeComboBox.getSelectedItem().equals( "TCP/IP" ) ) {
|
||||
connectionType = "TCP/IP";
|
||||
if( tcpHostAddressField.getText().equals( "" ) || tcpHostPortField.getText().equals( "" ) ) {
|
||||
System.out.println( "must enter an address & port for TCP/IP" );
|
||||
}
|
||||
else if( connectTCP( tcpHostAddressField.getText(), Integer.parseInt( tcpHostPortField.getText() ) ) ) {
|
||||
startTcpListener();
|
||||
}
|
||||
else {
|
||||
System.out.println( "failed to connect to TCP/IP server" );
|
||||
}
|
||||
}
|
||||
else {
|
||||
System.out.println( "idk how you did that, but this protocol isn't supported...connectionTypeComboBox conains \"" + connectionTypeComboBox.getSelectedItem() + "\"" );
|
||||
}
|
||||
}
|
||||
|
||||
// disconnect button
|
||||
else if( evt.getSource() == connectButton && evt.getActionCommand().equals( "disconnect" ) ) {
|
||||
disconnect();
|
||||
}
|
||||
|
||||
// arm button
|
||||
else if( evt.getSource().equals( armDisarmButton ) && evt.getActionCommand().equals( "arm" ) ){
|
||||
cliCommandArea.append( "--ARMING..." );
|
||||
tcpOut.println( "ARM_CONTROLLER" );
|
||||
armDisarmButton.setText( "disarm" );
|
||||
cliCommandArea.append( "DONE\n" );
|
||||
}
|
||||
|
||||
// disarm button
|
||||
else if( evt.getSource().equals( armDisarmButton ) && evt.getActionCommand().equals( "disarm" ) ) {
|
||||
cliCommandArea.append( "--DISARMING..." );
|
||||
tcpOut.println( "DISARM_CONTROLLER" );
|
||||
armDisarmButton.setText( "arm" );
|
||||
cliCommandArea.append( "DONE\n" );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* connects over TCP/IP protocol
|
||||
* @param hostAddress - the ip address of the server host
|
||||
* @param hostPort - the port of the socket at the host
|
||||
* @return true on success, false on failure
|
||||
*/
|
||||
private boolean connectTCP( String hostAddress, int hostPort ) {
|
||||
cliCommandArea.append( "--CONNECTING WITH TCP..." );
|
||||
|
||||
try {
|
||||
tcpSocket = new Socket( hostAddress, hostPort );
|
||||
tcpIn = new BufferedReader( new InputStreamReader( tcpSocket.getInputStream() ) );
|
||||
tcpOut = new PrintWriter( tcpSocket.getOutputStream(), true );
|
||||
startTcpListener();
|
||||
}
|
||||
catch( UnknownHostException ex ) {
|
||||
cliCommandArea.append( "UnknownHostException\n" );
|
||||
return false;
|
||||
}
|
||||
catch( IOException ex ) {
|
||||
cliCommandArea.append( "IOException\n" );
|
||||
return false;
|
||||
}
|
||||
|
||||
setGuiConnected();
|
||||
connectionStatus = true;
|
||||
cliCommandArea.append( "DONE\n" );
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private void startTcpListener() {
|
||||
tcpListener = new Thread( this, "tcpListenerThread" );
|
||||
tcpListener.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* the method used by the TCP listening thread
|
||||
*/
|
||||
public void run() {
|
||||
while( connectionStatus ) {
|
||||
try {
|
||||
if( tcpIn.ready() ) {
|
||||
cliRxAppend( "--READING: " + tcpIn.readLine() + "\n" );
|
||||
}
|
||||
}
|
||||
catch( Exception ex ) {}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* will add the message to cli view if show receive checkbox is checked
|
||||
*/
|
||||
public void cliRxAppend( String message ) {
|
||||
if( cliShowReceivedCheckBox.isSelected() ) {
|
||||
cliCommandArea.append( message );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private void setGuiConnected() {
|
||||
connectButton.setText( "disconnect" );
|
||||
tabbedPane.setEnabledAt( 1, true ); // control panel
|
||||
tabbedPane.setEnabledAt( 2, true ); // motor testing panel
|
||||
enableComponents( connectionOptionsPanel, false );
|
||||
mainFrame.setDefaultCloseOperation( JFrame.DO_NOTHING_ON_CLOSE );
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private void setGuiDisconnected() {
|
||||
connectButton.setText( "connect" );
|
||||
tabbedPane.setSelectedIndex( 0 );
|
||||
tabbedPane.setEnabledAt( 1, false ); // control panel
|
||||
tabbedPane.setEnabledAt( 2, false ); // motor testing panel
|
||||
enableComponents( connectionOptionsPanel, true );
|
||||
mainFrame.setDefaultCloseOperation( JFrame.DISPOSE_ON_CLOSE );
|
||||
}
|
||||
|
||||
/**
|
||||
* disconnects from whatever connection has been set up with Raspberry Pi
|
||||
*/
|
||||
private void disconnect() {
|
||||
cliCommandArea.append( "--DISCONNECTING...");
|
||||
|
||||
tcpOut.println( "DISCONNECT" );
|
||||
|
||||
try {
|
||||
tcpIn.close();
|
||||
tcpOut.close();
|
||||
}
|
||||
catch( IOException ex ) {
|
||||
cliCommandArea.append( "IOException\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
setGuiDisconnected();
|
||||
connectionStatus = false;
|
||||
cliCommandArea.append( "DONE\n" );
|
||||
}
|
||||
|
||||
/**
|
||||
* main begins the ground station
|
||||
*/
|
||||
public static void main( String[] args ) {
|
||||
GroundStation groundStation = new GroundStation();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
BIN
GroundStation/SmartScroller$1.class
Normal file
BIN
GroundStation/SmartScroller$1.class
Normal file
Binary file not shown.
BIN
GroundStation/SmartScroller.class
Normal file
BIN
GroundStation/SmartScroller.class
Normal file
Binary file not shown.
172
GroundStation/SmartScroller.java
Normal file
172
GroundStation/SmartScroller.java
Normal file
@@ -0,0 +1,172 @@
|
||||
import java.awt.Component;
|
||||
import java.awt.event.*;
|
||||
import javax.swing.*;
|
||||
import javax.swing.text.*;
|
||||
|
||||
/**
|
||||
* The SmartScroller will attempt to keep the viewport positioned based on
|
||||
* the users interaction with the scrollbar. The normal behaviour is to keep
|
||||
* the viewport positioned to see new data as it is dynamically added.
|
||||
*
|
||||
* Assuming vertical scrolling and data is added to the bottom:
|
||||
*
|
||||
* - when the viewport is at the bottom and new data is added,
|
||||
* then automatically scroll the viewport to the bottom
|
||||
* - when the viewport is not at the bottom and new data is added,
|
||||
* then do nothing with the viewport
|
||||
*
|
||||
* Assuming vertical scrolling and data is added to the top:
|
||||
*
|
||||
* - when the viewport is at the top and new data is added,
|
||||
* then do nothing with the viewport
|
||||
* - when the viewport is not at the top and new data is added, then adjust
|
||||
* the viewport to the relative position it was at before the data was added
|
||||
*
|
||||
* Similiar logic would apply for horizontal scrolling.
|
||||
*/
|
||||
public class SmartScroller implements AdjustmentListener
|
||||
{
|
||||
public final static int HORIZONTAL = 0;
|
||||
public final static int VERTICAL = 1;
|
||||
|
||||
public final static int START = 0;
|
||||
public final static int END = 1;
|
||||
|
||||
private int viewportPosition;
|
||||
|
||||
private JScrollBar scrollBar;
|
||||
private boolean adjustScrollBar = true;
|
||||
|
||||
private int previousValue = -1;
|
||||
private int previousMaximum = -1;
|
||||
|
||||
/**
|
||||
* Convenience constructor.
|
||||
* Scroll direction is VERTICAL and viewport position is at the END.
|
||||
*
|
||||
* @param scrollPane the scroll pane to monitor
|
||||
*/
|
||||
public SmartScroller(JScrollPane scrollPane)
|
||||
{
|
||||
this(scrollPane, VERTICAL, END);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience constructor.
|
||||
* Scroll direction is VERTICAL.
|
||||
*
|
||||
* @param scrollPane the scroll pane to monitor
|
||||
* @param viewportPosition valid values are START and END
|
||||
*/
|
||||
public SmartScroller(JScrollPane scrollPane, int viewportPosition)
|
||||
{
|
||||
this(scrollPane, VERTICAL, viewportPosition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify how the SmartScroller will function.
|
||||
*
|
||||
* @param scrollPane the scroll pane to monitor
|
||||
* @param scrollDirection indicates which JScrollBar to monitor.
|
||||
* Valid values are HORIZONTAL and VERTICAL.
|
||||
* @param viewportPosition indicates where the viewport will normally be
|
||||
* positioned as data is added.
|
||||
* Valid values are START and END
|
||||
*/
|
||||
public SmartScroller(JScrollPane scrollPane, int scrollDirection, int viewportPosition)
|
||||
{
|
||||
if (scrollDirection != HORIZONTAL
|
||||
&& scrollDirection != VERTICAL)
|
||||
throw new IllegalArgumentException("invalid scroll direction specified");
|
||||
|
||||
if (viewportPosition != START
|
||||
&& viewportPosition != END)
|
||||
throw new IllegalArgumentException("invalid viewport position specified");
|
||||
|
||||
this.viewportPosition = viewportPosition;
|
||||
|
||||
if (scrollDirection == HORIZONTAL)
|
||||
scrollBar = scrollPane.getHorizontalScrollBar();
|
||||
else
|
||||
scrollBar = scrollPane.getVerticalScrollBar();
|
||||
|
||||
scrollBar.addAdjustmentListener( this );
|
||||
|
||||
// Turn off automatic scrolling for text components
|
||||
|
||||
Component view = scrollPane.getViewport().getView();
|
||||
|
||||
if (view instanceof JTextComponent)
|
||||
{
|
||||
JTextComponent textComponent = (JTextComponent)view;
|
||||
DefaultCaret caret = (DefaultCaret)textComponent.getCaret();
|
||||
caret.setUpdatePolicy(DefaultCaret.NEVER_UPDATE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void adjustmentValueChanged(final AdjustmentEvent e)
|
||||
{
|
||||
SwingUtilities.invokeLater(new Runnable()
|
||||
{
|
||||
public void run()
|
||||
{
|
||||
checkScrollBar(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* Analyze every adjustment event to determine when the viewport
|
||||
* needs to be repositioned.
|
||||
*/
|
||||
private void checkScrollBar(AdjustmentEvent e)
|
||||
{
|
||||
// The scroll bar listModel contains information needed to determine
|
||||
// whether the viewport should be repositioned or not.
|
||||
|
||||
JScrollBar scrollBar = (JScrollBar)e.getSource();
|
||||
BoundedRangeModel listModel = scrollBar.getModel();
|
||||
int value = listModel.getValue();
|
||||
int extent = listModel.getExtent();
|
||||
int maximum = listModel.getMaximum();
|
||||
|
||||
boolean valueChanged = previousValue != value;
|
||||
boolean maximumChanged = previousMaximum != maximum;
|
||||
|
||||
// Check if the user has manually repositioned the scrollbar
|
||||
|
||||
if (valueChanged && !maximumChanged)
|
||||
{
|
||||
if (viewportPosition == START)
|
||||
adjustScrollBar = value != 0;
|
||||
else
|
||||
adjustScrollBar = value + extent >= maximum;
|
||||
}
|
||||
|
||||
// Reset the "value" so we can reposition the viewport and
|
||||
// distinguish between a user scroll and a program scroll.
|
||||
// (ie. valueChanged will be false on a program scroll)
|
||||
|
||||
if (adjustScrollBar && viewportPosition == END)
|
||||
{
|
||||
// Scroll the viewport to the end.
|
||||
scrollBar.removeAdjustmentListener( this );
|
||||
value = maximum - extent;
|
||||
scrollBar.setValue( value );
|
||||
scrollBar.addAdjustmentListener( this );
|
||||
}
|
||||
|
||||
if (adjustScrollBar && viewportPosition == START)
|
||||
{
|
||||
// Keep the viewport at the same relative viewportPosition
|
||||
scrollBar.removeAdjustmentListener( this );
|
||||
value = value + maximum - previousMaximum;
|
||||
scrollBar.setValue( value );
|
||||
scrollBar.addAdjustmentListener( this );
|
||||
}
|
||||
|
||||
previousValue = value;
|
||||
previousMaximum = maximum;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user