Merge pull request #1563 from SiboVG/issue-1558
[#1558] Restore focus to motors, recovery, stage and simulation table after table action + others
This commit is contained in:
commit
26fbb73d8b
@ -4,9 +4,7 @@ import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseListener;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.io.File;
|
||||
@ -19,16 +17,12 @@ import java.net.URL;
|
||||
import java.net.URLDecoder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.BevelBorder;
|
||||
import javax.swing.border.TitledBorder;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.TreeSelectionEvent;
|
||||
import javax.swing.event.TreeSelectionListener;
|
||||
import javax.swing.tree.DefaultTreeSelectionModel;
|
||||
import javax.swing.tree.TreePath;
|
||||
import javax.swing.tree.TreeSelectionModel;
|
||||
@ -60,7 +54,6 @@ import net.sf.openrocket.gui.dialogs.preferences.PreferencesDialog;
|
||||
import net.sf.openrocket.gui.figure3d.photo.PhotoFrame;
|
||||
import net.sf.openrocket.gui.help.tours.GuidedTourSelectionDialog;
|
||||
import net.sf.openrocket.gui.main.componenttree.ComponentTree;
|
||||
import net.sf.openrocket.gui.main.flightconfigpanel.FlightConfigurationPanel;
|
||||
import net.sf.openrocket.gui.scalefigure.RocketPanel;
|
||||
import net.sf.openrocket.gui.util.DummyFrameMenuOSX;
|
||||
import net.sf.openrocket.gui.util.FileHelper;
|
||||
@ -69,13 +62,11 @@ import net.sf.openrocket.gui.util.Icons;
|
||||
import net.sf.openrocket.gui.util.OpenFileWorker;
|
||||
import net.sf.openrocket.gui.util.SaveFileWorker;
|
||||
import net.sf.openrocket.gui.util.SwingPreferences;
|
||||
import net.sf.openrocket.gui.widgets.SelectColorButton;
|
||||
import net.sf.openrocket.l10n.Translator;
|
||||
import net.sf.openrocket.logging.Markers;
|
||||
import net.sf.openrocket.rocketcomponent.AxialStage;
|
||||
import net.sf.openrocket.rocketcomponent.ComponentChangeEvent;
|
||||
import net.sf.openrocket.rocketcomponent.ComponentChangeListener;
|
||||
import net.sf.openrocket.rocketcomponent.PodSet;
|
||||
import net.sf.openrocket.rocketcomponent.Rocket;
|
||||
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
||||
import net.sf.openrocket.startup.Application;
|
||||
@ -108,9 +99,10 @@ public class BasicFrame extends JFrame {
|
||||
public static final int SHIFT_SHORTCUT_KEY = Toolkit.getDefaultToolkit().getMenuShortcutKeyMaskEx() |
|
||||
SHIFT_DOWN_MASK;
|
||||
|
||||
public static final int COMPONENT_TAB = 0;
|
||||
public static final int CONFIGURATION_TAB = 1;
|
||||
public static final int DESIGN_TAB = 0;
|
||||
public static final int FLIGHT_CONFIGURATION_TAB = 1;
|
||||
public static final int SIMULATION_TAB = 2;
|
||||
private int previousTab = DESIGN_TAB;
|
||||
|
||||
|
||||
/**
|
||||
@ -142,7 +134,9 @@ public class BasicFrame extends JFrame {
|
||||
/** Actions available for rocket modifications */
|
||||
private final RocketActions actions;
|
||||
|
||||
private SimulationPanel simulationPanel;
|
||||
private final DesignPanel designPanel;
|
||||
private final FlightConfigurationPanel flightConfigurationPanel;
|
||||
private final SimulationPanel simulationPanel;
|
||||
|
||||
public static BasicFrame lastFrameInstance = null; // Latest BasicFrame that was created
|
||||
private static boolean quitCalled = false; // Keeps track whether the quit action has been called
|
||||
@ -166,8 +160,13 @@ public class BasicFrame extends JFrame {
|
||||
componentSelectionModel = new DefaultTreeSelectionModel();
|
||||
componentSelectionModel.setSelectionMode(TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);
|
||||
|
||||
// Obtain the simulation selection model that will be used
|
||||
// ----- Create the different BasicFrame panels -----
|
||||
log.debug("Constructing the BasicFrame UI");
|
||||
|
||||
//// Top segment, tabbed pane
|
||||
simulationPanel = new SimulationPanel(document);
|
||||
{
|
||||
// Obtain the simulation selection model that will be used
|
||||
simulationSelectionModel = simulationPanel.getSimulationListSelectionModel();
|
||||
|
||||
// Combine into a DocumentSelectionModel
|
||||
@ -175,9 +174,39 @@ public class BasicFrame extends JFrame {
|
||||
selectionModel.attachComponentTreeSelectionModel(componentSelectionModel);
|
||||
selectionModel.attachSimulationListSelectionModel(simulationSelectionModel);
|
||||
|
||||
// Create RocketActions
|
||||
actions = new RocketActions(document, selectionModel, this, simulationPanel);
|
||||
}
|
||||
{
|
||||
// Create the component tree
|
||||
tree = new ComponentTree(document);
|
||||
tree.setSelectionModel(componentSelectionModel);
|
||||
}
|
||||
|
||||
designPanel = new DesignPanel(this, document, tree);
|
||||
flightConfigurationPanel = new FlightConfigurationPanel(this, document);
|
||||
tabbedPane = new JTabbedPane();
|
||||
tabbedPane.addTab(trans.get("BasicFrame.tab.Rocketdesign"), null, designPanel);
|
||||
tabbedPane.addTab(trans.get("BasicFrame.tab.Flightconfig"), null, flightConfigurationPanel);
|
||||
tabbedPane.addTab(trans.get("BasicFrame.tab.Flightsim"), null, simulationPanel);
|
||||
|
||||
// Add change listener to catch when the tabs are changed. This is to run simulations
|
||||
// automatically when the simulation tab is selected.
|
||||
tabbedPane.addChangeListener(new BasicFrame_changeAdapter(this));
|
||||
|
||||
//// Bottom segment, rocket figure
|
||||
rocketpanel = new RocketPanel(document, this);
|
||||
rocketpanel.setSelectionModel(tree.getSelectionModel());
|
||||
|
||||
//// The main vertical split pane
|
||||
JSplitPane vertical = new JSplitPane(JSplitPane.VERTICAL_SPLIT, true);
|
||||
vertical.setResizeWeight(0.5);
|
||||
vertical.setTopComponent(tabbedPane);
|
||||
vertical.setBottomComponent(rocketpanel);
|
||||
this.add(vertical);
|
||||
|
||||
// Populate the popup menu
|
||||
{
|
||||
popupMenu = new JPopupMenu();
|
||||
popupMenu.add(actions.getEditAction());
|
||||
popupMenu.add(actions.getCutAction());
|
||||
@ -187,35 +216,7 @@ public class BasicFrame extends JFrame {
|
||||
popupMenu.add(actions.getDeleteAction());
|
||||
popupMenu.addSeparator();
|
||||
popupMenu.add(actions.getScaleAction());
|
||||
|
||||
log.debug("Constructing the BasicFrame UI");
|
||||
|
||||
// The main vertical split pane
|
||||
JSplitPane vertical = new JSplitPane(JSplitPane.VERTICAL_SPLIT, true);
|
||||
vertical.setResizeWeight(0.5);
|
||||
this.add(vertical);
|
||||
|
||||
// The top tabbed pane
|
||||
tabbedPane = new JTabbedPane();
|
||||
//// Rocket design
|
||||
tabbedPane.addTab(trans.get("BasicFrame.tab.Rocketdesign"), null, designTab());
|
||||
//// Flight configurations
|
||||
tabbedPane.addTab(trans.get("BasicFrame.tab.Flightconfig"), null, new FlightConfigurationPanel(this, document));
|
||||
//// Flight simulations
|
||||
tabbedPane.addTab(trans.get("BasicFrame.tab.Flightsim"), null, simulationPanel);
|
||||
|
||||
// Add change listener to catch when the tabs are changed. This is to run simulations
|
||||
// automatically when the simulation tab is selected.
|
||||
tabbedPane.addChangeListener(new BasicFrame_changeAdapter(this));
|
||||
|
||||
vertical.setTopComponent(tabbedPane);
|
||||
|
||||
// Bottom segment, rocket figure
|
||||
|
||||
rocketpanel = new RocketPanel(document, this);
|
||||
vertical.setBottomComponent(rocketpanel);
|
||||
|
||||
rocketpanel.setSelectionModel(tree.getSelectionModel());
|
||||
}
|
||||
|
||||
createMenu();
|
||||
|
||||
@ -272,194 +273,6 @@ public class BasicFrame extends JFrame {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Construct the "Rocket design" tab. This contains a horizontal split pane
|
||||
* with the left component the design tree and the right component buttons
|
||||
* for adding components.
|
||||
*/
|
||||
private JComponent designTab() {
|
||||
JSplitPane horizontal = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true);
|
||||
horizontal.setResizeWeight(0.5);
|
||||
|
||||
|
||||
// Upper-left segment, component tree
|
||||
|
||||
JPanel panel = new JPanel(new MigLayout("fill, flowy", "[grow][grow 0]","[grow]"));
|
||||
|
||||
tree = new ComponentTree(document);
|
||||
tree.setSelectionModel(componentSelectionModel);
|
||||
|
||||
// Remove JTree key events that interfere with menu accelerators
|
||||
InputMap im = SwingUtilities.getUIInputMap(tree, JComponent.WHEN_FOCUSED);
|
||||
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_X, SHORTCUT_KEY), null);
|
||||
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_C, SHORTCUT_KEY), null);
|
||||
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_V, SHORTCUT_KEY), null);
|
||||
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_A, SHORTCUT_KEY), null);
|
||||
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_S, SHORTCUT_KEY), null);
|
||||
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_O, SHORTCUT_KEY), null);
|
||||
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_N, SHORTCUT_KEY), null);
|
||||
|
||||
// Visually select all child components of a stage/rocket/podset when it is selected
|
||||
componentSelectionModel.addTreeSelectionListener(new TreeSelectionListener() {
|
||||
@Override
|
||||
public void valueChanged(TreeSelectionEvent e) {
|
||||
if (tree == null || tree.getSelectionPaths() == null || tree.getSelectionPaths().length == 0
|
||||
|| rocketpanel == null) return;
|
||||
|
||||
// Get all the components that need to be selected = currently selected components + children of stages/boosters/podsets
|
||||
List<RocketComponent> children = new ArrayList<>(Arrays.asList(rocketpanel.getFigure().getSelection()));
|
||||
for (TreePath p : tree.getSelectionPaths()) {
|
||||
if (p != null) {
|
||||
RocketComponent c = (RocketComponent) p.getLastPathComponent();
|
||||
if (c instanceof AxialStage || c instanceof Rocket || c instanceof PodSet) {
|
||||
Iterator<RocketComponent> iter = c.iterator(false);
|
||||
while (iter.hasNext()) {
|
||||
RocketComponent child = iter.next();
|
||||
children.add(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Select all the child components
|
||||
if (rocketpanel.getFigure() != null && rocketpanel.getFigure3d() != null) {
|
||||
rocketpanel.getFigure().setSelection(children.toArray(new RocketComponent[0]));
|
||||
rocketpanel.getFigure3d().setSelection(children.toArray(new RocketComponent[0]));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Double-click opens config dialog
|
||||
MouseListener ml = new MouseAdapter() {
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
int selRow = tree.getRowForLocation(e.getX(), e.getY());
|
||||
TreePath selPath = tree.getPathForLocation(e.getX(), e.getY());
|
||||
if (selRow != -1) {
|
||||
if (selPath == null) return;
|
||||
|
||||
// Double-click
|
||||
if ((e.getButton() == MouseEvent.BUTTON1) && (e.getClickCount() == 2) && !ComponentConfigDialog.isDialogVisible()) {
|
||||
RocketComponent component = (RocketComponent) selPath.getLastPathComponent();
|
||||
|
||||
// Multi-component edit if shift/meta key is pressed
|
||||
if ((e.isShiftDown() || e.isMetaDown()) && tree.getSelectionPaths() != null) {
|
||||
// Add the other selected components as listeners to the last selected component
|
||||
for (TreePath p : tree.getSelectionPaths()) {
|
||||
if (p != null) {
|
||||
if (p.getLastPathComponent() == component) continue;
|
||||
RocketComponent c = (RocketComponent) p.getLastPathComponent();
|
||||
c.clearConfigListeners();
|
||||
component.addConfigListener(c);
|
||||
}
|
||||
}
|
||||
|
||||
// Add the selection path to the tree selection
|
||||
List<TreePath> paths = new LinkedList<>(Arrays.asList(tree.getSelectionPaths()));
|
||||
paths.add(selPath);
|
||||
tree.setSelectionPaths(paths.toArray(new TreePath[0]));
|
||||
}
|
||||
|
||||
ComponentConfigDialog.showDialog(BasicFrame.this, BasicFrame.this.document, component);
|
||||
}
|
||||
// Context menu
|
||||
else if ((e.getButton() == MouseEvent.BUTTON3) && (e.getClickCount() == 1)) {
|
||||
if (!tree.isPathSelected(selPath)) {
|
||||
// Select new path
|
||||
tree.setSelectionPath(selPath);
|
||||
}
|
||||
|
||||
doComponentTreePopup(e);
|
||||
}
|
||||
} else { // Clicked on blank space
|
||||
tree.clearSelection();
|
||||
}
|
||||
}
|
||||
};
|
||||
tree.addMouseListener(ml);
|
||||
|
||||
// Update dialog when selection is changed
|
||||
componentSelectionModel.addTreeSelectionListener(new TreeSelectionListener() {
|
||||
@Override
|
||||
public void valueChanged(TreeSelectionEvent e) {
|
||||
// Scroll tree to the selected item
|
||||
TreePath[] paths = componentSelectionModel.getSelectionPaths();
|
||||
if (paths == null || paths.length == 0)
|
||||
return;
|
||||
|
||||
for (TreePath path : paths) {
|
||||
tree.scrollPathToVisible(path);
|
||||
}
|
||||
|
||||
if (!ComponentConfigDialog.isDialogVisible())
|
||||
return;
|
||||
else
|
||||
ComponentConfigDialog.disposeDialog();
|
||||
|
||||
RocketComponent c = (RocketComponent) paths[0].getLastPathComponent();
|
||||
c.clearConfigListeners();
|
||||
for (int i = 1; i < paths.length; i++) {
|
||||
RocketComponent listener = (RocketComponent) paths[i].getLastPathComponent();
|
||||
listener.clearConfigListeners();
|
||||
c.addConfigListener(listener);
|
||||
}
|
||||
ComponentConfigDialog.showDialog(BasicFrame.this, BasicFrame.this.document, c);
|
||||
}
|
||||
});
|
||||
|
||||
// Place tree inside scroll pane
|
||||
JScrollPane scroll = new JScrollPane(tree);
|
||||
panel.add(scroll, "spany, grow, wrap");
|
||||
|
||||
|
||||
// Buttons
|
||||
JButton button = new SelectColorButton(actions.getMoveUpAction());
|
||||
panel.add(button, "sizegroup buttons, aligny 65%");
|
||||
|
||||
button = new SelectColorButton(actions.getMoveDownAction());
|
||||
panel.add(button, "sizegroup buttons, aligny 0%");
|
||||
|
||||
button = new SelectColorButton();
|
||||
RocketActions.tieActionToButtonNoIcon(button, actions.getEditAction());
|
||||
button.setMnemonic(0);
|
||||
panel.add(button, "sizegroup buttons, gaptop 20%");
|
||||
|
||||
button = new SelectColorButton();
|
||||
RocketActions.tieActionToButtonNoIcon(button, actions.getDuplicateAction());
|
||||
button.setMnemonic(0);
|
||||
panel.add(button, "sizegroup buttons");
|
||||
|
||||
button = new SelectColorButton();
|
||||
RocketActions.tieActionToButtonNoIcon(button, actions.getDeleteAction());
|
||||
button.setMnemonic(0);
|
||||
panel.add(button, "sizegroup buttons");
|
||||
|
||||
horizontal.setLeftComponent(panel);
|
||||
|
||||
|
||||
// Upper-right segment, component addition buttons
|
||||
|
||||
panel = new JPanel(new MigLayout("fill, insets 0", "[0::]"));
|
||||
|
||||
scroll = new JScrollPane(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
|
||||
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
|
||||
scroll.setViewportView(new ComponentAddButtons(document, componentSelectionModel,
|
||||
scroll.getViewport()));
|
||||
scroll.setBorder(null);
|
||||
scroll.setViewportBorder(null);
|
||||
|
||||
TitledBorder border = BorderFactory.createTitledBorder(trans.get("BasicFrame.title.Addnewcomp"));
|
||||
GUIUtil.changeFontStyle(border, Font.BOLD);
|
||||
scroll.setBorder(border);
|
||||
|
||||
panel.add(scroll, "grow");
|
||||
|
||||
horizontal.setRightComponent(panel);
|
||||
|
||||
return horizontal;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the currently selected rocket component, or <code>null</code> if none selected.
|
||||
*/
|
||||
@ -985,6 +798,10 @@ public class BasicFrame extends JFrame {
|
||||
this.setJMenuBar(menubar);
|
||||
}
|
||||
|
||||
public RocketActions getRocketActions() {
|
||||
return actions;
|
||||
}
|
||||
|
||||
public void doComponentTreePopup(MouseEvent e) {
|
||||
popupMenu.show(e.getComponent(), e.getX(), e.getY());
|
||||
}
|
||||
@ -1250,7 +1067,7 @@ public class BasicFrame extends JFrame {
|
||||
/**
|
||||
* Select the tab on the main pane.
|
||||
*
|
||||
* @param tab one of {@link #COMPONENT_TAB} or {@link #SIMULATION_TAB}.
|
||||
* @param tab one of {@link #DESIGN_TAB}, {@link #FLIGHT_CONFIGURATION_TAB} or {@link #SIMULATION_TAB}.
|
||||
*/
|
||||
public void selectTab(int tab) {
|
||||
tabbedPane.setSelectedIndex(tab);
|
||||
@ -1934,8 +1751,21 @@ public class BasicFrame extends JFrame {
|
||||
public void stateChanged(ChangeEvent e) {
|
||||
JTabbedPane tabSource = (JTabbedPane) e.getSource();
|
||||
int tab = tabSource.getSelectedIndex();
|
||||
if (tab == SIMULATION_TAB) {
|
||||
if (previousTab == SIMULATION_TAB) {
|
||||
simulationPanel.updatePreviousSelection();
|
||||
}
|
||||
previousTab = tab;
|
||||
switch (tab) {
|
||||
case DESIGN_TAB:
|
||||
designPanel.takeTheSpotlight();
|
||||
break;
|
||||
case FLIGHT_CONFIGURATION_TAB:
|
||||
flightConfigurationPanel.takeTheSpotlight();
|
||||
break;
|
||||
case SIMULATION_TAB:
|
||||
simulationPanel.takeTheSpotlight();
|
||||
simulationPanel.activating();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
237
swing/src/net/sf/openrocket/gui/main/DesignPanel.java
Normal file
237
swing/src/net/sf/openrocket/gui/main/DesignPanel.java
Normal file
@ -0,0 +1,237 @@
|
||||
package net.sf.openrocket.gui.main;
|
||||
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import net.sf.openrocket.document.OpenRocketDocument;
|
||||
import net.sf.openrocket.gui.configdialog.ComponentConfigDialog;
|
||||
import net.sf.openrocket.gui.main.componenttree.ComponentTree;
|
||||
import net.sf.openrocket.gui.scalefigure.RocketPanel;
|
||||
import net.sf.openrocket.gui.util.GUIUtil;
|
||||
import net.sf.openrocket.gui.widgets.SelectColorButton;
|
||||
import net.sf.openrocket.l10n.Translator;
|
||||
import net.sf.openrocket.rocketcomponent.AxialStage;
|
||||
import net.sf.openrocket.rocketcomponent.PodSet;
|
||||
import net.sf.openrocket.rocketcomponent.Rocket;
|
||||
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
||||
import net.sf.openrocket.startup.Application;
|
||||
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.InputMap;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JSplitPane;
|
||||
import javax.swing.KeyStroke;
|
||||
import javax.swing.ScrollPaneConstants;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.border.TitledBorder;
|
||||
import javax.swing.event.TreeSelectionEvent;
|
||||
import javax.swing.event.TreeSelectionListener;
|
||||
import javax.swing.tree.TreePath;
|
||||
import java.awt.Component;
|
||||
import java.awt.Font;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseListener;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import static net.sf.openrocket.gui.main.BasicFrame.SHORTCUT_KEY;
|
||||
|
||||
/**
|
||||
* Construct the "Rocket design" tab. This contains a horizontal split pane
|
||||
* with the left component the design tree and the right component buttons
|
||||
* for adding components.
|
||||
*/
|
||||
public class DesignPanel extends JSplitPane {
|
||||
private static final Translator trans = Application.getTranslator();
|
||||
private final Component tree;
|
||||
|
||||
public DesignPanel(final BasicFrame parent, final OpenRocketDocument document, final ComponentTree tree) {
|
||||
super(JSplitPane.HORIZONTAL_SPLIT, true);
|
||||
setResizeWeight(0.5);
|
||||
this.tree = tree;
|
||||
|
||||
// Upper-left segment, component tree
|
||||
JPanel panel = new JPanel(new MigLayout("fill, flowy", "[grow][grow 0]","[grow]"));
|
||||
|
||||
// Remove JTree key events that interfere with menu accelerators
|
||||
InputMap im = SwingUtilities.getUIInputMap(tree, JComponent.WHEN_FOCUSED);
|
||||
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_X, SHORTCUT_KEY), null);
|
||||
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_C, SHORTCUT_KEY), null);
|
||||
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_V, SHORTCUT_KEY), null);
|
||||
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_A, SHORTCUT_KEY), null);
|
||||
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_S, SHORTCUT_KEY), null);
|
||||
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_O, SHORTCUT_KEY), null);
|
||||
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_N, SHORTCUT_KEY), null);
|
||||
|
||||
// Visually select all child components of a stage/rocket/podset when it is selected
|
||||
tree.getSelectionModel().addTreeSelectionListener(new TreeSelectionListener() {
|
||||
@Override
|
||||
public void valueChanged(TreeSelectionEvent e) {
|
||||
if (tree == null || tree.getSelectionPaths() == null || tree.getSelectionPaths().length == 0
|
||||
|| parent.getRocketPanel() == null) return;
|
||||
|
||||
// Get all the components that need to be selected = currently selected components + children of stages/boosters/podsets
|
||||
List<RocketComponent> children = new ArrayList<>(Arrays.asList(parent.getRocketPanel().getFigure().getSelection()));
|
||||
for (TreePath p : tree.getSelectionPaths()) {
|
||||
if (p != null) {
|
||||
RocketComponent c = (RocketComponent) p.getLastPathComponent();
|
||||
if (c instanceof AxialStage || c instanceof Rocket || c instanceof PodSet) {
|
||||
Iterator<RocketComponent> iter = c.iterator(false);
|
||||
while (iter.hasNext()) {
|
||||
RocketComponent child = iter.next();
|
||||
children.add(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Select all the child components
|
||||
if (parent.getRocketPanel().getFigure() != null && parent.getRocketPanel().getFigure3d() != null) {
|
||||
parent.getRocketPanel().getFigure().setSelection(children.toArray(new RocketComponent[0]));
|
||||
parent.getRocketPanel().getFigure3d().setSelection(children.toArray(new RocketComponent[0]));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Double-click opens config dialog
|
||||
MouseListener ml = new MouseAdapter() {
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
int selRow = tree.getRowForLocation(e.getX(), e.getY());
|
||||
TreePath selPath = tree.getPathForLocation(e.getX(), e.getY());
|
||||
if (selRow != -1) {
|
||||
if (selPath == null) return;
|
||||
|
||||
// Double-click
|
||||
if ((e.getButton() == MouseEvent.BUTTON1) && (e.getClickCount() == 2) && !ComponentConfigDialog.isDialogVisible()) {
|
||||
RocketComponent component = (RocketComponent) selPath.getLastPathComponent();
|
||||
|
||||
// Multi-component edit if shift/meta key is pressed
|
||||
if ((e.isShiftDown() || e.isMetaDown()) && tree.getSelectionPaths() != null) {
|
||||
// Add the other selected components as listeners to the last selected component
|
||||
for (TreePath p : tree.getSelectionPaths()) {
|
||||
if (p != null) {
|
||||
if (p.getLastPathComponent() == component) continue;
|
||||
RocketComponent c = (RocketComponent) p.getLastPathComponent();
|
||||
c.clearConfigListeners();
|
||||
component.addConfigListener(c);
|
||||
}
|
||||
}
|
||||
|
||||
// Add the selection path to the tree selection
|
||||
List<TreePath> paths = new LinkedList<>(Arrays.asList(tree.getSelectionPaths()));
|
||||
paths.add(selPath);
|
||||
tree.setSelectionPaths(paths.toArray(new TreePath[0]));
|
||||
}
|
||||
|
||||
ComponentConfigDialog.showDialog(parent, document, component);
|
||||
}
|
||||
// Context menu
|
||||
else if ((e.getButton() == MouseEvent.BUTTON3) && (e.getClickCount() == 1)) {
|
||||
if (!tree.isPathSelected(selPath)) {
|
||||
// Select new path
|
||||
tree.setSelectionPath(selPath);
|
||||
}
|
||||
|
||||
parent.doComponentTreePopup(e);
|
||||
}
|
||||
} else { // Clicked on blank space
|
||||
tree.clearSelection();
|
||||
}
|
||||
}
|
||||
};
|
||||
tree.addMouseListener(ml);
|
||||
|
||||
// Update dialog when selection is changed
|
||||
tree.getSelectionModel().addTreeSelectionListener(new TreeSelectionListener() {
|
||||
@Override
|
||||
public void valueChanged(TreeSelectionEvent e) {
|
||||
// Scroll tree to the selected item
|
||||
TreePath[] paths = tree.getSelectionModel().getSelectionPaths();
|
||||
if (paths == null || paths.length == 0)
|
||||
return;
|
||||
|
||||
for (TreePath path : paths) {
|
||||
tree.scrollPathToVisible(path);
|
||||
}
|
||||
|
||||
if (!ComponentConfigDialog.isDialogVisible())
|
||||
return;
|
||||
else
|
||||
ComponentConfigDialog.disposeDialog();
|
||||
|
||||
RocketComponent c = (RocketComponent) paths[0].getLastPathComponent();
|
||||
c.clearConfigListeners();
|
||||
for (int i = 1; i < paths.length; i++) {
|
||||
RocketComponent listener = (RocketComponent) paths[i].getLastPathComponent();
|
||||
listener.clearConfigListeners();
|
||||
c.addConfigListener(listener);
|
||||
}
|
||||
ComponentConfigDialog.showDialog(parent, document, c);
|
||||
}
|
||||
});
|
||||
|
||||
// Place tree inside scroll pane
|
||||
JScrollPane scroll = new JScrollPane(tree);
|
||||
panel.add(scroll, "spany, grow, wrap");
|
||||
|
||||
|
||||
// Buttons
|
||||
JButton button = new SelectColorButton(parent.getRocketActions().getMoveUpAction());
|
||||
panel.add(button, "sizegroup buttons, aligny 65%");
|
||||
|
||||
button = new SelectColorButton(parent.getRocketActions().getMoveDownAction());
|
||||
panel.add(button, "sizegroup buttons, aligny 0%");
|
||||
|
||||
button = new SelectColorButton(parent.getRocketActions().getEditAction());
|
||||
button.setIcon(null);
|
||||
button.setMnemonic(0);
|
||||
panel.add(button, "sizegroup buttons, gaptop 20%");
|
||||
|
||||
button = new SelectColorButton(parent.getRocketActions().getDuplicateAction());
|
||||
button.setIcon(null);
|
||||
button.setMnemonic(0);
|
||||
panel.add(button, "sizegroup buttons");
|
||||
|
||||
button = new SelectColorButton(parent.getRocketActions().getDeleteAction());
|
||||
button.setIcon(null);
|
||||
button.setMnemonic(0);
|
||||
panel.add(button, "sizegroup buttons");
|
||||
|
||||
this.setLeftComponent(panel);
|
||||
|
||||
|
||||
// Upper-right segment, component addition buttons
|
||||
|
||||
panel = new JPanel(new MigLayout("fill, insets 0", "[0::]"));
|
||||
|
||||
scroll = new JScrollPane(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
|
||||
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
|
||||
scroll.setViewportView(new ComponentAddButtons(document, tree.getSelectionModel(),
|
||||
scroll.getViewport()));
|
||||
scroll.setBorder(null);
|
||||
scroll.setViewportBorder(null);
|
||||
|
||||
TitledBorder border = BorderFactory.createTitledBorder(trans.get("BasicFrame.title.Addnewcomp"));
|
||||
GUIUtil.changeFontStyle(border, Font.BOLD);
|
||||
scroll.setBorder(border);
|
||||
|
||||
panel.add(scroll, "grow");
|
||||
|
||||
this.setRightComponent(panel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Focus on the component tree.
|
||||
*/
|
||||
public void takeTheSpotlight() {
|
||||
tree.requestFocusInWindow();
|
||||
}
|
||||
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package net.sf.openrocket.gui.main.flightconfigpanel;
|
||||
package net.sf.openrocket.gui.main;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.MouseEvent;
|
||||
@ -20,7 +20,10 @@ import net.miginfocom.swing.MigLayout;
|
||||
import net.sf.openrocket.document.OpenRocketDocument;
|
||||
import net.sf.openrocket.document.Simulation;
|
||||
import net.sf.openrocket.gui.dialogs.flightconfiguration.RenameConfigDialog;
|
||||
import net.sf.openrocket.gui.main.BasicFrame;
|
||||
import net.sf.openrocket.gui.main.flightconfigpanel.FlightConfigurablePanel;
|
||||
import net.sf.openrocket.gui.main.flightconfigpanel.MotorConfigurationPanel;
|
||||
import net.sf.openrocket.gui.main.flightconfigpanel.RecoveryConfigurationPanel;
|
||||
import net.sf.openrocket.gui.main.flightconfigpanel.SeparationConfigurationPanel;
|
||||
import net.sf.openrocket.l10n.Translator;
|
||||
import net.sf.openrocket.rocketcomponent.ComponentChangeEvent;
|
||||
import net.sf.openrocket.rocketcomponent.FlightConfigurableComponent;
|
||||
@ -111,20 +114,30 @@ public class FlightConfigurationPanel extends JPanel implements StateChangeListe
|
||||
this.add(duplicateConfButton, "wrap");
|
||||
|
||||
tabs.addChangeListener(new ChangeListener() {
|
||||
private FlightConfigurablePanel<?> previousPanel = motorConfigurationPanel;
|
||||
@Override
|
||||
public void stateChanged(ChangeEvent e) {
|
||||
// Trigger a selection of the motor/recovery/configuration item
|
||||
FlightConfigurablePanel<?> panel = null;
|
||||
switch (tabs.getSelectedIndex()) {
|
||||
case MOTOR_TAB_INDEX:
|
||||
motorConfigurationPanel.updateButtonState();
|
||||
panel = motorConfigurationPanel;
|
||||
break;
|
||||
case RECOVERY_TAB_INDEX:
|
||||
recoveryConfigurationPanel.updateButtonState();
|
||||
panel = recoveryConfigurationPanel;
|
||||
break;
|
||||
case SEPARATION_TAB_INDEX:
|
||||
separationConfigurationPanel.updateButtonState();
|
||||
panel = separationConfigurationPanel;
|
||||
break;
|
||||
}
|
||||
|
||||
// Update the panel selection, focus, and button state
|
||||
if (panel == null) return;
|
||||
synchronizePanelSelection(previousPanel, panel);
|
||||
panel.updateButtonState();
|
||||
panel.takeTheSpotlight();
|
||||
panel.updateRocketViewSelection();
|
||||
previousPanel = panel;
|
||||
}
|
||||
});
|
||||
|
||||
@ -230,6 +243,7 @@ public class FlightConfigurationPanel extends JPanel implements StateChangeListe
|
||||
}
|
||||
|
||||
configurationChanged(ComponentChangeEvent.NONFUNCTIONAL_CHANGE);
|
||||
takeTheSpotlight();
|
||||
}
|
||||
|
||||
public void doPopupConfig(MouseEvent e) {
|
||||
@ -294,6 +308,19 @@ public class FlightConfigurationPanel extends JPanel implements StateChangeListe
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronize the table row selection of a target panel with the selection in the source panel.
|
||||
*/
|
||||
private void synchronizePanelSelection(FlightConfigurablePanel<?> source, FlightConfigurablePanel<?> target) {
|
||||
if (source == null || target == null) return;
|
||||
List<FlightConfigurationId> fids = source.getSelectedConfigurationIds();
|
||||
if (fids == null || fids.isEmpty()) {
|
||||
target.clearSelection();
|
||||
} else {
|
||||
target.setSelectedConfigurationIds(fids);
|
||||
}
|
||||
}
|
||||
|
||||
private List<FlightConfigurationId> getSelectedConfigurationIds() {
|
||||
switch (tabs.getSelectedIndex()) {
|
||||
case MOTOR_TAB_INDEX:
|
||||
@ -366,4 +393,24 @@ public class FlightConfigurationPanel extends JPanel implements StateChangeListe
|
||||
newOrDuplicateConfigAction(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Focus on the table of the config panel that is currently opened.
|
||||
*/
|
||||
public void takeTheSpotlight() {
|
||||
switch (tabs.getSelectedIndex()) {
|
||||
case MOTOR_TAB_INDEX:
|
||||
motorConfigurationPanel.takeTheSpotlight();
|
||||
motorConfigurationPanel.updateRocketViewSelection();
|
||||
break;
|
||||
case RECOVERY_TAB_INDEX:
|
||||
recoveryConfigurationPanel.takeTheSpotlight();
|
||||
recoveryConfigurationPanel.updateRocketViewSelection();
|
||||
break;
|
||||
case SEPARATION_TAB_INDEX:
|
||||
separationConfigurationPanel.takeTheSpotlight();
|
||||
separationConfigurationPanel.updateRocketViewSelection();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
@ -608,7 +608,7 @@ public class RocketActions {
|
||||
parentFrame.selectTab(BasicFrame.SIMULATION_TAB);
|
||||
} else {
|
||||
deleteComponentAction.actionPerformed(e);
|
||||
parentFrame.selectTab(BasicFrame.COMPONENT_TAB);
|
||||
parentFrame.selectTab(BasicFrame.DESIGN_TAB);
|
||||
}
|
||||
}
|
||||
|
||||
@ -662,7 +662,7 @@ public class RocketActions {
|
||||
|
||||
OpenRocketClipboard.setClipboard(copiedComponents);
|
||||
delete(components);
|
||||
parentFrame.selectTab(BasicFrame.COMPONENT_TAB);
|
||||
parentFrame.selectTab(BasicFrame.DESIGN_TAB);
|
||||
} else if (isSimulationSelected()) {
|
||||
|
||||
Simulation[] simsCopy = new Simulation[sims.length];
|
||||
@ -719,7 +719,7 @@ public class RocketActions {
|
||||
List<RocketComponent> copiedComponents = new LinkedList<>(copyComponentsMaintainParent(components));
|
||||
|
||||
OpenRocketClipboard.setClipboard(copiedComponents);
|
||||
parentFrame.selectTab(BasicFrame.COMPONENT_TAB);
|
||||
parentFrame.selectTab(BasicFrame.DESIGN_TAB);
|
||||
} else if (sims != null && sims.length > 0) {
|
||||
Simulation[] simsCopy = new Simulation[sims.length];
|
||||
for (int i=0; i < sims.length; i++) {
|
||||
@ -799,7 +799,7 @@ public class RocketActions {
|
||||
|
||||
selectionModel.setSelectedComponents(successfullyPasted);
|
||||
|
||||
parentFrame.selectTab(BasicFrame.COMPONENT_TAB);
|
||||
parentFrame.selectTab(BasicFrame.DESIGN_TAB);
|
||||
|
||||
} else if (sims != null) {
|
||||
|
||||
@ -896,7 +896,7 @@ public class RocketActions {
|
||||
|
||||
selectionModel.setSelectedComponents(duplicateComponents);
|
||||
|
||||
parentFrame.selectTab(BasicFrame.COMPONENT_TAB);
|
||||
parentFrame.selectTab(BasicFrame.DESIGN_TAB);
|
||||
} else if (sims != null && sims.length > 0) {
|
||||
ArrayList<Simulation> copySims = new ArrayList<Simulation>();
|
||||
|
||||
|
@ -107,6 +107,8 @@ public class SimulationPanel extends JPanel {
|
||||
private final SimulationAction duplicateSimulationAction;
|
||||
private final SimulationAction deleteSimulationAction;
|
||||
|
||||
private int[] previousSelection = null;
|
||||
|
||||
public SimulationPanel(OpenRocketDocument doc) {
|
||||
super(new MigLayout("fill", "[grow][][][][][][grow]"));
|
||||
|
||||
@ -165,6 +167,7 @@ public class SimulationPanel extends JPanel {
|
||||
simulationTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
|
||||
simulationTable.setDefaultRenderer(Object.class, new JLabelRenderer());
|
||||
simulationTableModel.setColumnWidths(simulationTable.getColumnModel());
|
||||
simulationTable.setFillsViewportHeight(true);
|
||||
|
||||
// Context menu
|
||||
pm = new JPopupMenu();
|
||||
@ -193,7 +196,18 @@ public class SimulationPanel extends JPanel {
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
int selectedRow = simulationTable.getSelectedRow();
|
||||
|
||||
if (e.getButton() == MouseEvent.BUTTON1 && e.getClickCount() == 2) {
|
||||
if (e.getButton() == MouseEvent.BUTTON1) {
|
||||
// Clear the table selection when clicked outside the table rows.
|
||||
if (e.getClickCount() == 1) {
|
||||
int row = simulationTable.rowAtPoint(e.getPoint());
|
||||
int column = simulationTable.columnAtPoint(e.getPoint());
|
||||
|
||||
if (row == -1 || column == -1) {
|
||||
simulationTable.clearSelection();
|
||||
}
|
||||
}
|
||||
// Edit the simulation or plot/export
|
||||
else if (e.getClickCount() == 2) {
|
||||
int selected = simulationTable.convertRowIndexToModel(selectedRow);
|
||||
|
||||
int column = simulationTable.columnAtPoint(e.getPoint());
|
||||
@ -205,7 +219,10 @@ public class SimulationPanel extends JPanel {
|
||||
|
||||
openDialog(document.getSimulations().get(selected));
|
||||
}
|
||||
} else if (e.getButton() == MouseEvent.BUTTON3 && e.getClickCount() == 1) {
|
||||
}
|
||||
}
|
||||
// Show context menu
|
||||
else if (e.getButton() == MouseEvent.BUTTON3 && e.getClickCount() == 1) {
|
||||
// Get the row that the right-click action happened on
|
||||
int r = simulationTable.rowAtPoint(e.getPoint());
|
||||
|
||||
@ -263,6 +280,10 @@ public class SimulationPanel extends JPanel {
|
||||
updateButtonStates();
|
||||
}
|
||||
|
||||
public void updatePreviousSelection() {
|
||||
this.previousSelection = simulationTable.getSelectedRows();
|
||||
}
|
||||
|
||||
private void newSimulation() {
|
||||
Simulation sim = new Simulation(document.getRocket());
|
||||
sim.setName(document.getNextSimulationName());
|
||||
@ -294,6 +315,7 @@ public class SimulationPanel extends JPanel {
|
||||
}
|
||||
|
||||
fireMaintainSelection();
|
||||
takeTheSpotlight();
|
||||
|
||||
openDialog(true, sim);
|
||||
}
|
||||
@ -343,6 +365,7 @@ public class SimulationPanel extends JPanel {
|
||||
document.removeSimulation(selection[i]);
|
||||
}
|
||||
simulationTableModel.fireTableDataChanged();
|
||||
takeTheSpotlight();
|
||||
}
|
||||
|
||||
private void runSimulation() {
|
||||
@ -354,6 +377,7 @@ public class SimulationPanel extends JPanel {
|
||||
SimulationPanel.this), document, sims).setVisible(true);
|
||||
log.info("Running simulations took " + (System.currentTimeMillis() - t) + " ms");
|
||||
fireMaintainSelection();
|
||||
takeTheSpotlight();
|
||||
}
|
||||
|
||||
public void editSimulation() {
|
||||
@ -490,11 +514,13 @@ public class SimulationPanel extends JPanel {
|
||||
}
|
||||
d.setVisible(true);
|
||||
fireMaintainSelection();
|
||||
takeTheSpotlight();
|
||||
}
|
||||
|
||||
private void openDialog(final Simulation sim) {
|
||||
boolean plotMode = false;
|
||||
if (sim.hasSimulationData() && (sim.getStatus() == Status.UPTODATE || sim.getStatus() == Status.EXTERNAL)) {
|
||||
if (sim.hasSimulationData() && (sim.getStatus() == Status.UPTODATE || sim.getStatus() == Status.LOADED
|
||||
|| sim.getStatus() == Status.EXTERNAL)) {
|
||||
plotMode = true;
|
||||
}
|
||||
openDialog(plotMode, sim);
|
||||
@ -987,6 +1013,24 @@ public class SimulationPanel extends JPanel {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Focus on the simulation table and maintain the previous row selection(s).
|
||||
*/
|
||||
public void takeTheSpotlight() {
|
||||
simulationTable.requestFocusInWindow();
|
||||
if (simulationTable.getSelectedRows().length > 0) {
|
||||
return;
|
||||
}
|
||||
if (previousSelection == null || previousSelection.length == 0) {
|
||||
simulationTable.setRowSelectionInterval(0, 0);
|
||||
} else {
|
||||
simulationTable.clearSelection();
|
||||
for (int row : previousSelection) {
|
||||
simulationTable.addRowSelectionInterval(row, row);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class NextRowAction extends AbstractAction {
|
||||
private final JTable table;
|
||||
private final boolean cycle;
|
||||
@ -1048,6 +1092,5 @@ public class SimulationPanel extends JPanel {
|
||||
table.getSelectionModel().setSelectionInterval(nextRow, nextRow);
|
||||
table.getColumnModel().getSelectionModel().setSelectionInterval(0, 0);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -3,8 +3,10 @@ package net.sf.openrocket.gui.main.flightconfigpanel;
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Font;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.JComponent;
|
||||
@ -20,6 +22,7 @@ import javax.swing.event.ListSelectionListener;
|
||||
import javax.swing.table.AbstractTableModel;
|
||||
import javax.swing.table.DefaultTableCellRenderer;
|
||||
|
||||
import net.sf.openrocket.gui.main.FlightConfigurationPanel;
|
||||
import net.sf.openrocket.util.ArrayList;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@ -71,7 +74,7 @@ public abstract class FlightConfigurablePanel<T extends FlightConfigurableCompon
|
||||
updateButtonState();
|
||||
}
|
||||
|
||||
protected abstract void updateButtonState();
|
||||
public abstract void updateButtonState();
|
||||
|
||||
@Override
|
||||
public void componentChanged(ComponentChangeEvent e) {
|
||||
@ -87,6 +90,7 @@ public abstract class FlightConfigurablePanel<T extends FlightConfigurableCompon
|
||||
*/
|
||||
private final JTable doTableInitialization() {
|
||||
JTable table = this.initializeTable();
|
||||
table.setFillsViewportHeight(true);
|
||||
FlightConfigurationId current = this.rocket.getSelectedConfiguration().getFlightConfigurationID();
|
||||
int col = (table.getColumnCount() > 1) ? table.getColumnCount() - 1 : 0;
|
||||
for (int row = 0; row < table.getRowCount(); row++) {
|
||||
@ -99,7 +103,7 @@ public abstract class FlightConfigurablePanel<T extends FlightConfigurableCompon
|
||||
return table;
|
||||
}
|
||||
|
||||
protected final void synchronizeConfigurationSelection() {
|
||||
public final void synchronizeConfigurationSelection() {
|
||||
FlightConfigurationId currentRocketFCID = rocket.getSelectedConfiguration().getFlightConfigurationID();
|
||||
FlightConfigurationId selectedFCID = getSelectedConfigurationId();
|
||||
|
||||
@ -134,6 +138,7 @@ public abstract class FlightConfigurablePanel<T extends FlightConfigurableCompon
|
||||
return;
|
||||
}
|
||||
table.changeSelection(row, col, true, false);
|
||||
table.requestFocusInWindow();
|
||||
}
|
||||
|
||||
protected void installTableListener() {
|
||||
@ -145,6 +150,11 @@ public abstract class FlightConfigurablePanel<T extends FlightConfigurableCompon
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't update the flight configuration for multi-selections
|
||||
if (table.getSelectionModel().getSelectedItemsCount() > 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Find the selected row and set it as the current selected configuration
|
||||
* for the rocket. This will propagate the event to ensure that other
|
||||
* pieces of the UI are updated and match the table selection.
|
||||
@ -162,6 +172,27 @@ public abstract class FlightConfigurablePanel<T extends FlightConfigurableCompon
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
// Clear the table selection when clicked outside the table rows.
|
||||
table.addMouseListener(new MouseAdapter() {
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
if (e.getButton() == MouseEvent.BUTTON1 && e.getClickCount() == 1) {
|
||||
int row = table.rowAtPoint(e.getPoint());
|
||||
int col = table.columnAtPoint(e.getPoint());
|
||||
if (row == -1 || col == -1) {
|
||||
clearSelection();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
table.getColumnModel().getSelectionModel().addListSelectionListener(new ListSelectionListener() {
|
||||
@Override
|
||||
public void valueChanged(ListSelectionEvent e) {
|
||||
updateRocketViewSelection(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@ -171,6 +202,20 @@ public abstract class FlightConfigurablePanel<T extends FlightConfigurableCompon
|
||||
*/
|
||||
protected abstract JTable initializeTable();
|
||||
|
||||
public void clearSelection() {
|
||||
table.clearSelection();
|
||||
}
|
||||
|
||||
public void updateRocketViewSelection() {
|
||||
ListSelectionEvent e = new ListSelectionEvent(this, 0, 0, false);
|
||||
updateRocketViewSelection(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the selection in the rocket design view, based on the currently selected motor, recovery device, or stage.
|
||||
*/
|
||||
public abstract void updateRocketViewSelection(ListSelectionEvent e);
|
||||
|
||||
protected T getSelectedComponent() {
|
||||
|
||||
int col = table.convertColumnIndexToModel(table.getSelectedColumn());
|
||||
@ -226,7 +271,7 @@ public abstract class FlightConfigurablePanel<T extends FlightConfigurableCompon
|
||||
return FlightConfigurationId.ERROR_FCID;
|
||||
}
|
||||
|
||||
protected List<FlightConfigurationId> getSelectedConfigurationIds() {
|
||||
public List<FlightConfigurationId> getSelectedConfigurationIds() {
|
||||
int col = table.convertColumnIndexToModel(table.getSelectedColumn());
|
||||
int[] rows = Arrays.stream(table.getSelectedRows()).map(table::convertRowIndexToModel).toArray();
|
||||
if (Arrays.stream(rows).min().isEmpty() || Arrays.stream(rows).min().getAsInt() < 0 || col < 0 ||
|
||||
@ -251,6 +296,29 @@ public abstract class FlightConfigurablePanel<T extends FlightConfigurableCompon
|
||||
return Ids;
|
||||
}
|
||||
|
||||
/**
|
||||
* Select the rows of the table that correspond to the given FlightConfigurationIds. The second column of the table
|
||||
* will be used for the selection.
|
||||
* @param fids flight configuration ids to select
|
||||
*/
|
||||
public void setSelectedConfigurationIds(List<FlightConfigurationId> fids) {
|
||||
if (fids == null || fids.isEmpty() || table.getColumnCount() == 0) return;
|
||||
|
||||
if (getSelectedConfigurationIds() != null && new HashSet<>(getSelectedConfigurationIds()).containsAll(fids)) return;
|
||||
|
||||
table.clearSelection();
|
||||
for (FlightConfigurationId id : fids) {
|
||||
if (id == FlightConfigurationId.DEFAULT_VALUE_FCID) continue;
|
||||
for (int rowNum = 0; rowNum < table.getRowCount(); rowNum++) {
|
||||
FlightConfigurationId rowFCID = rocket.getId(rowNum );
|
||||
if (rowFCID.equals(id)) {
|
||||
table.changeSelection(rowNum, 1, true, false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract class FlightConfigurableCellRenderer extends DefaultTableCellRenderer {
|
||||
|
||||
@Override
|
||||
@ -330,4 +398,11 @@ public abstract class FlightConfigurablePanel<T extends FlightConfigurableCompon
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Focus on the table
|
||||
*/
|
||||
public void takeTheSpotlight() {
|
||||
table.requestFocusInWindow();
|
||||
}
|
||||
|
||||
}
|
@ -3,8 +3,6 @@ package net.sf.openrocket.gui.main.flightconfigpanel;
|
||||
import java.awt.CardLayout;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.FocusEvent;
|
||||
import java.awt.event.FocusListener;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
@ -33,6 +31,7 @@ import net.miginfocom.swing.MigLayout;
|
||||
import net.sf.openrocket.gui.dialogs.flightconfiguration.IgnitionSelectionDialog;
|
||||
import net.sf.openrocket.gui.dialogs.flightconfiguration.MotorMountConfigurationPanel;
|
||||
import net.sf.openrocket.gui.dialogs.motor.MotorChooserDialog;
|
||||
import net.sf.openrocket.gui.main.FlightConfigurationPanel;
|
||||
import net.sf.openrocket.gui.widgets.SelectColorButton;
|
||||
import net.sf.openrocket.motor.IgnitionEvent;
|
||||
import net.sf.openrocket.motor.Motor;
|
||||
@ -65,7 +64,7 @@ public class MotorConfigurationPanel extends FlightConfigurablePanel<MotorMount>
|
||||
private final JPopupMenu popupMenuFull; // popup menu containing all the options
|
||||
|
||||
|
||||
MotorConfigurationPanel(final FlightConfigurationPanel flightConfigurationPanel, Rocket rocket) {
|
||||
public MotorConfigurationPanel(final FlightConfigurationPanel flightConfigurationPanel, Rocket rocket) {
|
||||
super(flightConfigurationPanel, rocket);
|
||||
|
||||
motorChooserDialog = new MotorChooserDialog(SwingUtilities.getWindowAncestor(flightConfigurationPanel));
|
||||
@ -250,35 +249,11 @@ public class MotorConfigurationPanel extends FlightConfigurablePanel<MotorMount>
|
||||
return configurationTable;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void installTableListener() {
|
||||
super.installTableListener();
|
||||
|
||||
table.getColumnModel().getSelectionModel().addListSelectionListener(new ListSelectionListener() {
|
||||
@Override
|
||||
public void valueChanged(ListSelectionEvent e) {
|
||||
updateComponentSelection(e);
|
||||
}
|
||||
});
|
||||
|
||||
table.addFocusListener(new FocusListener() {
|
||||
@Override
|
||||
public void focusGained(FocusEvent e) {
|
||||
updateComponentSelection(new ListSelectionEvent(this, 0, 0, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void focusLost(FocusEvent e) {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void doPopupFull(MouseEvent e) {
|
||||
popupMenuFull.show(e.getComponent(), e.getX(), e.getY());
|
||||
}
|
||||
|
||||
public void updateComponentSelection(ListSelectionEvent e) {
|
||||
public void updateRocketViewSelection(ListSelectionEvent e) {
|
||||
if (e.getValueIsAdjusting()) {
|
||||
return;
|
||||
}
|
||||
@ -294,7 +269,7 @@ public class MotorConfigurationPanel extends FlightConfigurablePanel<MotorMount>
|
||||
flightConfigurationPanel.setSelectedComponents(components);
|
||||
}
|
||||
|
||||
protected void updateButtonState() {
|
||||
public void updateButtonState() {
|
||||
if( configurationTableModel.getColumnCount() > 1 ) {
|
||||
showContent();
|
||||
|
||||
@ -356,6 +331,8 @@ public class MotorConfigurationPanel extends FlightConfigurablePanel<MotorMount>
|
||||
|
||||
if (update) {
|
||||
fireTableDataChanged(ComponentChangeEvent.MOTOR_CHANGE);
|
||||
} else {
|
||||
table.requestFocusInWindow();
|
||||
}
|
||||
}
|
||||
|
||||
@ -420,6 +397,8 @@ public class MotorConfigurationPanel extends FlightConfigurablePanel<MotorMount>
|
||||
|
||||
if (update) {
|
||||
fireTableDataChanged(ComponentChangeEvent.MOTOR_CHANGE);
|
||||
} else {
|
||||
table.requestFocusInWindow();
|
||||
}
|
||||
}
|
||||
|
||||
@ -448,6 +427,8 @@ public class MotorConfigurationPanel extends FlightConfigurablePanel<MotorMount>
|
||||
|
||||
if (update) {
|
||||
fireTableDataChanged(ComponentChangeEvent.MOTOR_CHANGE);
|
||||
} else {
|
||||
table.requestFocusInWindow();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,6 @@
|
||||
package net.sf.openrocket.gui.main.flightconfigpanel;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.FocusEvent;
|
||||
import java.awt.event.FocusListener;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
@ -25,6 +23,7 @@ import javax.swing.event.ListSelectionListener;
|
||||
|
||||
import net.sf.openrocket.formatting.RocketDescriptor;
|
||||
import net.sf.openrocket.gui.dialogs.flightconfiguration.DeploymentSelectionDialog;
|
||||
import net.sf.openrocket.gui.main.FlightConfigurationPanel;
|
||||
import net.sf.openrocket.l10n.Translator;
|
||||
import net.sf.openrocket.rocketcomponent.*;
|
||||
import net.sf.openrocket.rocketcomponent.DeploymentConfiguration.DeployEvent;
|
||||
@ -43,7 +42,7 @@ public class RecoveryConfigurationPanel extends FlightConfigurablePanel<Recovery
|
||||
private final JPopupMenu popupMenuFull; // popup menu containing all the options
|
||||
|
||||
|
||||
RecoveryConfigurationPanel(FlightConfigurationPanel flightConfigurationPanel, Rocket rocket) {
|
||||
public RecoveryConfigurationPanel(FlightConfigurationPanel flightConfigurationPanel, Rocket rocket) {
|
||||
super(flightConfigurationPanel,rocket);
|
||||
|
||||
JScrollPane scroll = new JScrollPane(table);
|
||||
@ -165,30 +164,6 @@ public class RecoveryConfigurationPanel extends FlightConfigurablePanel<Recovery
|
||||
return recoveryTable;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void installTableListener() {
|
||||
super.installTableListener();
|
||||
|
||||
table.getColumnModel().getSelectionModel().addListSelectionListener(new ListSelectionListener() {
|
||||
@Override
|
||||
public void valueChanged(ListSelectionEvent e) {
|
||||
updateComponentSelection(e);
|
||||
}
|
||||
});
|
||||
|
||||
table.addFocusListener(new FocusListener() {
|
||||
@Override
|
||||
public void focusGained(FocusEvent e) {
|
||||
updateComponentSelection(new ListSelectionEvent(this, 0, 0, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void focusLost(FocusEvent e) {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void selectDeployment() {
|
||||
List<RecoveryDevice> devices = getSelectedComponents();
|
||||
List<FlightConfigurationId> fcIds = getSelectedConfigurationIds();
|
||||
@ -235,6 +210,8 @@ public class RecoveryConfigurationPanel extends FlightConfigurablePanel<Recovery
|
||||
|
||||
if (update) {
|
||||
fireTableDataChanged(ComponentChangeEvent.AERODYNAMIC_CHANGE);
|
||||
} else {
|
||||
table.requestFocusInWindow();
|
||||
}
|
||||
|
||||
}
|
||||
@ -259,6 +236,8 @@ public class RecoveryConfigurationPanel extends FlightConfigurablePanel<Recovery
|
||||
}
|
||||
if (update) {
|
||||
fireTableDataChanged(ComponentChangeEvent.AERODYNAMIC_CHANGE);
|
||||
} else {
|
||||
table.requestFocusInWindow();
|
||||
}
|
||||
}
|
||||
|
||||
@ -266,7 +245,7 @@ public class RecoveryConfigurationPanel extends FlightConfigurablePanel<Recovery
|
||||
popupMenuFull.show(e.getComponent(), e.getX(), e.getY());
|
||||
}
|
||||
|
||||
public void updateComponentSelection(ListSelectionEvent e) {
|
||||
public void updateRocketViewSelection(ListSelectionEvent e) {
|
||||
if (e.getValueIsAdjusting() || getSelectedComponents() == null) {
|
||||
return;
|
||||
}
|
||||
|
@ -1,8 +1,6 @@
|
||||
package net.sf.openrocket.gui.main.flightconfigpanel;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.FocusEvent;
|
||||
import java.awt.event.FocusListener;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
@ -25,6 +23,7 @@ import javax.swing.event.ListSelectionListener;
|
||||
|
||||
import net.sf.openrocket.formatting.RocketDescriptor;
|
||||
import net.sf.openrocket.gui.dialogs.flightconfiguration.SeparationSelectionDialog;
|
||||
import net.sf.openrocket.gui.main.FlightConfigurationPanel;
|
||||
import net.sf.openrocket.l10n.Translator;
|
||||
import net.sf.openrocket.rocketcomponent.AxialStage;
|
||||
import net.sf.openrocket.rocketcomponent.ComponentChangeEvent;
|
||||
@ -48,7 +47,7 @@ public class SeparationConfigurationPanel extends FlightConfigurablePanel<AxialS
|
||||
private final JPopupMenu popupMenuFull; // popup menu containing all the options
|
||||
|
||||
|
||||
SeparationConfigurationPanel(FlightConfigurationPanel flightConfigurationPanel, Rocket rocket) {
|
||||
public SeparationConfigurationPanel(FlightConfigurationPanel flightConfigurationPanel, Rocket rocket) {
|
||||
super(flightConfigurationPanel,rocket);
|
||||
|
||||
JScrollPane scroll = new JScrollPane(table);
|
||||
@ -174,30 +173,6 @@ public class SeparationConfigurationPanel extends FlightConfigurablePanel<AxialS
|
||||
return separationTable;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void installTableListener() {
|
||||
super.installTableListener();
|
||||
|
||||
table.getColumnModel().getSelectionModel().addListSelectionListener(new ListSelectionListener() {
|
||||
@Override
|
||||
public void valueChanged(ListSelectionEvent e) {
|
||||
updateComponentSelection(e);
|
||||
}
|
||||
});
|
||||
|
||||
table.addFocusListener(new FocusListener() {
|
||||
@Override
|
||||
public void focusGained(FocusEvent e) {
|
||||
updateComponentSelection(new ListSelectionEvent(this, 0, 0, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void focusLost(FocusEvent e) {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void selectSeparation() {
|
||||
List<AxialStage> stages = getSelectedComponents();
|
||||
List<FlightConfigurationId> fcIds = getSelectedConfigurationIds();
|
||||
@ -245,6 +220,8 @@ public class SeparationConfigurationPanel extends FlightConfigurablePanel<AxialS
|
||||
|
||||
if (update) {
|
||||
fireTableDataChanged(ComponentChangeEvent.AEROMASS_CHANGE);
|
||||
} else {
|
||||
table.requestFocusInWindow();
|
||||
}
|
||||
}
|
||||
|
||||
@ -269,6 +246,8 @@ public class SeparationConfigurationPanel extends FlightConfigurablePanel<AxialS
|
||||
|
||||
if (update) {
|
||||
fireTableDataChanged(ComponentChangeEvent.AEROMASS_CHANGE);
|
||||
} else {
|
||||
table.requestFocusInWindow();
|
||||
}
|
||||
}
|
||||
|
||||
@ -276,7 +255,7 @@ public class SeparationConfigurationPanel extends FlightConfigurablePanel<AxialS
|
||||
popupMenuFull.show(e.getComponent(), e.getX(), e.getY());
|
||||
}
|
||||
|
||||
public void updateComponentSelection(ListSelectionEvent e) {
|
||||
public void updateRocketViewSelection(ListSelectionEvent e) {
|
||||
if (e.getValueIsAdjusting() || getSelectedComponents() == null) {
|
||||
return;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user