Merge pull request #1450 from SiboVG/extend-multi-select
Extend multi-component selection for different-typed components
This commit is contained in:
commit
f1a203ea6c
@ -949,8 +949,12 @@ CenteringRingCfg.tab.Generalproperties = General properties
|
|||||||
|
|
||||||
!ComponentConfigDialog
|
!ComponentConfigDialog
|
||||||
ComponentCfgDlg.configuration = configuration
|
ComponentCfgDlg.configuration = configuration
|
||||||
ComponentCfgDlg.configuration1 =
|
ComponentCfgDlg.MultiComponent = Multi-component
|
||||||
|
ComponentCfgDlg.MultiComponentConfig = Multi-component configuration
|
||||||
|
ComponentCfgDlg.MultiComponentEdit = Multi-component edit
|
||||||
|
ComponentCfgDlg.MultiComponentEdit.ttip = <html>You are editing the following components:<br>
|
||||||
ComponentCfgDlg.Modify = Modify
|
ComponentCfgDlg.Modify = Modify
|
||||||
|
ComponentCfgDlg.ModifyComponents = Modify components
|
||||||
|
|
||||||
!StageConfig
|
!StageConfig
|
||||||
StageConfig.tab.Separation = Separation
|
StageConfig.tab.Separation = Separation
|
||||||
|
|||||||
@ -678,7 +678,6 @@ CenteringRingCfg.tab.Generalproperties = Obecn
|
|||||||
|
|
||||||
!ComponentConfigDialog
|
!ComponentConfigDialog
|
||||||
ComponentCfgDlg.configuration = konfigurace
|
ComponentCfgDlg.configuration = konfigurace
|
||||||
ComponentCfgDlg.configuration1 =
|
|
||||||
ComponentCfgDlg.Modify = Uprav
|
ComponentCfgDlg.Modify = Uprav
|
||||||
|
|
||||||
!StageConfig
|
!StageConfig
|
||||||
|
|||||||
@ -734,7 +734,6 @@ CenteringRingCfg.tab.Generalproperties = Allgemeine Eigenschaften
|
|||||||
|
|
||||||
!ComponentConfigDialog
|
!ComponentConfigDialog
|
||||||
ComponentCfgDlg.configuration = Konfiguration
|
ComponentCfgDlg.configuration = Konfiguration
|
||||||
ComponentCfgDlg.configuration1 =
|
|
||||||
ComponentCfgDlg.Modify = Verändern
|
ComponentCfgDlg.Modify = Verändern
|
||||||
|
|
||||||
!StageConfig
|
!StageConfig
|
||||||
|
|||||||
@ -130,8 +130,7 @@ CompassSelectionButton.lbl.W = O
|
|||||||
|
|
||||||
ComponentCfgDlg.Modify = Modificar
|
ComponentCfgDlg.Modify = Modificar
|
||||||
!ComponentConfigDialog
|
!ComponentConfigDialog
|
||||||
ComponentCfgDlg.configuration =
|
ComponentCfgDlg.configuration = Configuraci\u00f3n
|
||||||
ComponentCfgDlg.configuration1 = Configuraci\u00f3n
|
|
||||||
|
|
||||||
ComponentIcons.Bodytube = Cuerpo tubular
|
ComponentIcons.Bodytube = Cuerpo tubular
|
||||||
ComponentIcons.Bulkhead = Disco de enganche
|
ComponentIcons.Bulkhead = Disco de enganche
|
||||||
|
|||||||
@ -121,7 +121,6 @@ CompassSelectionButton.lbl.W = O
|
|||||||
ComponentCfgDlg.Modify = Modifier
|
ComponentCfgDlg.Modify = Modifier
|
||||||
!ComponentConfigDialog
|
!ComponentConfigDialog
|
||||||
ComponentCfgDlg.configuration = configuration
|
ComponentCfgDlg.configuration = configuration
|
||||||
ComponentCfgDlg.configuration1 = configuration
|
|
||||||
|
|
||||||
ComponentIcons.Bodytube = Tube
|
ComponentIcons.Bodytube = Tube
|
||||||
ComponentIcons.Bulkhead = Cloison
|
ComponentIcons.Bulkhead = Cloison
|
||||||
|
|||||||
@ -736,7 +736,6 @@ CenteringRingCfg.tab.Generalproperties = Proprieta' generali
|
|||||||
|
|
||||||
!ComponentConfigDialog
|
!ComponentConfigDialog
|
||||||
ComponentCfgDlg.configuration = (configurazione)
|
ComponentCfgDlg.configuration = (configurazione)
|
||||||
ComponentCfgDlg.configuration1 =
|
|
||||||
ComponentCfgDlg.Modify = Modifica
|
ComponentCfgDlg.Modify = Modifica
|
||||||
|
|
||||||
!StageConfig
|
!StageConfig
|
||||||
|
|||||||
@ -766,7 +766,6 @@ CenteringRingCfg.tab.Generalproperties = \u4E00\u822C
|
|||||||
|
|
||||||
!ComponentConfigDialog
|
!ComponentConfigDialog
|
||||||
ComponentCfgDlg.configuration = \u30B3\u30F3\u30D5\u30A3\u30AE\u30E5\u30EC\u30FC\u30B7\u30E7\u30F3
|
ComponentCfgDlg.configuration = \u30B3\u30F3\u30D5\u30A3\u30AE\u30E5\u30EC\u30FC\u30B7\u30E7\u30F3
|
||||||
ComponentCfgDlg.configuration1 =
|
|
||||||
ComponentCfgDlg.Modify = \u5909\u66F4
|
ComponentCfgDlg.Modify = \u5909\u66F4
|
||||||
|
|
||||||
!StageConfig
|
!StageConfig
|
||||||
|
|||||||
@ -889,7 +889,6 @@ CenteringRingCfg.tab.Generalproperties = Algemene eigenschappen
|
|||||||
|
|
||||||
!ComponentConfigDialog
|
!ComponentConfigDialog
|
||||||
ComponentCfgDlg.configuration = configuratie
|
ComponentCfgDlg.configuration = configuratie
|
||||||
ComponentCfgDlg.configuration1 =
|
|
||||||
ComponentCfgDlg.Modify = Wijzigen
|
ComponentCfgDlg.Modify = Wijzigen
|
||||||
|
|
||||||
!StageConfig
|
!StageConfig
|
||||||
|
|||||||
@ -680,7 +680,6 @@ update.dlg.latestVersion = Korzystasz z najnowszej wersji OpenRocket: %s.
|
|||||||
|
|
||||||
!ComponentConfigDialog
|
!ComponentConfigDialog
|
||||||
ComponentCfgDlg.configuration = konfiguracja
|
ComponentCfgDlg.configuration = konfiguracja
|
||||||
ComponentCfgDlg.configuration1 =
|
|
||||||
ComponentCfgDlg.Modify = Zmodyfikuj
|
ComponentCfgDlg.Modify = Zmodyfikuj
|
||||||
|
|
||||||
!StageConfig
|
!StageConfig
|
||||||
|
|||||||
@ -951,7 +951,6 @@ CenteringRingCfg.tab.Generalproperties = \u041E\u0441\u043D\u043E\u0432\u043D\u0
|
|||||||
|
|
||||||
!ComponentConfigDialog
|
!ComponentConfigDialog
|
||||||
ComponentCfgDlg.configuration = \u043F\u0430\u0440\u0430\u043C\u0435\u0442\u0440\u044B
|
ComponentCfgDlg.configuration = \u043F\u0430\u0440\u0430\u043C\u0435\u0442\u0440\u044B
|
||||||
ComponentCfgDlg.configuration1 =
|
|
||||||
ComponentCfgDlg.Modify = \u0418\u0437\u043C\u0435\u043D\u0438\u0442\u044C
|
ComponentCfgDlg.Modify = \u0418\u0437\u043C\u0435\u043D\u0438\u0442\u044C
|
||||||
|
|
||||||
!StageConfig
|
!StageConfig
|
||||||
|
|||||||
@ -838,7 +838,6 @@ CenteringRingCfg.tab.Generalproperties = General properties
|
|||||||
|
|
||||||
!ComponentConfigDialog
|
!ComponentConfigDialog
|
||||||
ComponentCfgDlg.configuration = configuration
|
ComponentCfgDlg.configuration = configuration
|
||||||
ComponentCfgDlg.configuration1 =
|
|
||||||
ComponentCfgDlg.Modify = Modify
|
ComponentCfgDlg.Modify = Modify
|
||||||
|
|
||||||
!StageConfig
|
!StageConfig
|
||||||
|
|||||||
@ -1,10 +1,14 @@
|
|||||||
package net.sf.openrocket.appearance;
|
package net.sf.openrocket.appearance;
|
||||||
|
|
||||||
import net.sf.openrocket.appearance.Decal.EdgeMode;
|
import net.sf.openrocket.appearance.Decal.EdgeMode;
|
||||||
|
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
||||||
import net.sf.openrocket.util.AbstractChangeSource;
|
import net.sf.openrocket.util.AbstractChangeSource;
|
||||||
import net.sf.openrocket.util.Color;
|
import net.sf.openrocket.util.Color;
|
||||||
import net.sf.openrocket.util.Coordinate;
|
import net.sf.openrocket.util.Coordinate;
|
||||||
|
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use this class to build an immutable Appearance object in a friendly way. Set
|
* Use this class to build an immutable Appearance object in a friendly way. Set
|
||||||
* the various values one at a time with the setter methods and then call
|
* the various values one at a time with the setter methods and then call
|
||||||
@ -28,6 +32,13 @@ public class AppearanceBuilder extends AbstractChangeSource {
|
|||||||
private Decal.EdgeMode edgeMode;
|
private Decal.EdgeMode edgeMode;
|
||||||
|
|
||||||
private boolean batch;
|
private boolean batch;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of appearance builders that will set their appearance properties to the same as the current appearance
|
||||||
|
*/
|
||||||
|
private final Map<RocketComponent, AppearanceBuilder> configListeners = new LinkedHashMap<>();
|
||||||
|
// If true, appearance change events will not be fired
|
||||||
|
private boolean bypassAppearanceChangeEvent = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default constructor
|
* Default constructor
|
||||||
@ -59,7 +70,9 @@ public class AppearanceBuilder extends AbstractChangeSource {
|
|||||||
rotation = 0;
|
rotation = 0;
|
||||||
image = null;
|
image = null;
|
||||||
edgeMode = EdgeMode.REPEAT;
|
edgeMode = EdgeMode.REPEAT;
|
||||||
fireChangeEvent();//shouldn't this fire change event?
|
if (!bypassAppearanceChangeEvent) {
|
||||||
|
fireChangeEvent();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -88,6 +101,9 @@ public class AppearanceBuilder extends AbstractChangeSource {
|
|||||||
* @param d The decal
|
* @param d The decal
|
||||||
*/
|
*/
|
||||||
public void setDecal(Decal d){
|
public void setDecal(Decal d){
|
||||||
|
for (AppearanceBuilder listener : configListeners.values()) {
|
||||||
|
listener.setDecal(d);
|
||||||
|
}
|
||||||
if (d != null) {
|
if (d != null) {
|
||||||
setOffset(d.getOffset().x, d.getOffset().y);
|
setOffset(d.getOffset().x, d.getOffset().y);
|
||||||
setCenter(d.getCenter().x, d.getCenter().y);
|
setCenter(d.getCenter().x, d.getCenter().y);
|
||||||
@ -96,7 +112,9 @@ public class AppearanceBuilder extends AbstractChangeSource {
|
|||||||
setEdgeMode(d.getEdgeMode());
|
setEdgeMode(d.getEdgeMode());
|
||||||
setImage(d.getImage());
|
setImage(d.getImage());
|
||||||
}
|
}
|
||||||
fireChangeEvent();
|
if (!bypassAppearanceChangeEvent) {
|
||||||
|
fireChangeEvent();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -137,9 +155,13 @@ public class AppearanceBuilder extends AbstractChangeSource {
|
|||||||
* @param paint the new color
|
* @param paint the new color
|
||||||
*/
|
*/
|
||||||
public void setPaint(Color paint) {
|
public void setPaint(Color paint) {
|
||||||
|
for (AppearanceBuilder listener : configListeners.values()) {
|
||||||
|
listener.setPaint(paint);
|
||||||
|
}
|
||||||
this.paint = paint;
|
this.paint = paint;
|
||||||
fireChangeEvent();
|
if (!bypassAppearanceChangeEvent) {
|
||||||
|
fireChangeEvent();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -158,8 +180,13 @@ public class AppearanceBuilder extends AbstractChangeSource {
|
|||||||
* @param shine the new shine for template
|
* @param shine the new shine for template
|
||||||
*/
|
*/
|
||||||
public void setShine(double shine) {
|
public void setShine(double shine) {
|
||||||
|
for (AppearanceBuilder listener : configListeners.values()) {
|
||||||
|
listener.setShine(shine);
|
||||||
|
}
|
||||||
this.shine = shine;
|
this.shine = shine;
|
||||||
fireChangeEvent();
|
if (!bypassAppearanceChangeEvent) {
|
||||||
|
fireChangeEvent();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -179,6 +206,9 @@ public class AppearanceBuilder extends AbstractChangeSource {
|
|||||||
* @param opacity new opacity value expressed in a percentage, where 0 is fully transparent and 1 is fully opaque
|
* @param opacity new opacity value expressed in a percentage, where 0 is fully transparent and 1 is fully opaque
|
||||||
*/
|
*/
|
||||||
public void setOpacity(double opacity) {
|
public void setOpacity(double opacity) {
|
||||||
|
for (AppearanceBuilder listener : configListeners.values()) {
|
||||||
|
listener.setOpacity(opacity);
|
||||||
|
}
|
||||||
if (this.paint == null) {
|
if (this.paint == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -186,8 +216,10 @@ public class AppearanceBuilder extends AbstractChangeSource {
|
|||||||
// Clamp opacity between 0 and 1
|
// Clamp opacity between 0 and 1
|
||||||
opacity = Math.max(0, Math.min(1, opacity));
|
opacity = Math.max(0, Math.min(1, opacity));
|
||||||
|
|
||||||
this.paint.setAlpha((int) (opacity * 255));
|
// Instead of simply setting the alpha, we need to create a new color with the new alpha value, otherwise undoing
|
||||||
fireChangeEvent();
|
// the setOpacity will not work correctly. (don't ask me why)
|
||||||
|
Color c = new Color(paint.getRed(), paint.getGreen(), paint.getBlue(), (int) (opacity * 255));
|
||||||
|
setPaint(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -207,8 +239,13 @@ public class AppearanceBuilder extends AbstractChangeSource {
|
|||||||
* @param offsetU the new offset to be used
|
* @param offsetU the new offset to be used
|
||||||
*/
|
*/
|
||||||
public void setOffsetU(double offsetU) {
|
public void setOffsetU(double offsetU) {
|
||||||
|
for (AppearanceBuilder listener : configListeners.values()) {
|
||||||
|
listener.setOffsetU(offsetU);
|
||||||
|
}
|
||||||
this.offsetU = offsetU;
|
this.offsetU = offsetU;
|
||||||
fireChangeEvent();
|
if (!bypassAppearanceChangeEvent) {
|
||||||
|
fireChangeEvent();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -227,8 +264,13 @@ public class AppearanceBuilder extends AbstractChangeSource {
|
|||||||
* @param offsetV the new offset to be used
|
* @param offsetV the new offset to be used
|
||||||
*/
|
*/
|
||||||
public void setOffsetV(double offsetV) {
|
public void setOffsetV(double offsetV) {
|
||||||
|
for (AppearanceBuilder listener : configListeners.values()) {
|
||||||
|
listener.setOffsetV(offsetV);
|
||||||
|
}
|
||||||
this.offsetV = offsetV;
|
this.offsetV = offsetV;
|
||||||
fireChangeEvent();
|
if (!bypassAppearanceChangeEvent) {
|
||||||
|
fireChangeEvent();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -259,8 +301,13 @@ public class AppearanceBuilder extends AbstractChangeSource {
|
|||||||
* @param centerU value of axis U for center
|
* @param centerU value of axis U for center
|
||||||
*/
|
*/
|
||||||
public void setCenterU(double centerU) {
|
public void setCenterU(double centerU) {
|
||||||
|
for (AppearanceBuilder listener : configListeners.values()) {
|
||||||
|
listener.setCenterU(centerU);
|
||||||
|
}
|
||||||
this.centerU = centerU;
|
this.centerU = centerU;
|
||||||
fireChangeEvent();
|
if (!bypassAppearanceChangeEvent) {
|
||||||
|
fireChangeEvent();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -276,11 +323,16 @@ public class AppearanceBuilder extends AbstractChangeSource {
|
|||||||
* set a new value for axis V for center in template
|
* set a new value for axis V for center in template
|
||||||
* fires change event
|
* fires change event
|
||||||
*
|
*
|
||||||
* @param centerU value of axis V for center
|
* @return value of axis V for center
|
||||||
*/
|
*/
|
||||||
public void setCenterV(double centerV) {
|
public void setCenterV(double centerV) {
|
||||||
|
for (AppearanceBuilder listener : configListeners.values()) {
|
||||||
|
listener.setCenterV(centerV);
|
||||||
|
}
|
||||||
this.centerV = centerV;
|
this.centerV = centerV;
|
||||||
fireChangeEvent();
|
if (!bypassAppearanceChangeEvent) {
|
||||||
|
fireChangeEvent();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -311,8 +363,13 @@ public class AppearanceBuilder extends AbstractChangeSource {
|
|||||||
* @param scaleU new value of scalling in axis U
|
* @param scaleU new value of scalling in axis U
|
||||||
*/
|
*/
|
||||||
public void setScaleU(double scaleU) {
|
public void setScaleU(double scaleU) {
|
||||||
|
for (AppearanceBuilder listener : configListeners.values()) {
|
||||||
|
listener.setScaleU(scaleU);
|
||||||
|
}
|
||||||
this.scaleU = scaleU;
|
this.scaleU = scaleU;
|
||||||
fireChangeEvent();
|
if (!bypassAppearanceChangeEvent) {
|
||||||
|
fireChangeEvent();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -331,8 +388,13 @@ public class AppearanceBuilder extends AbstractChangeSource {
|
|||||||
* @param scaleV new value of scalling in axis V
|
* @param scaleV new value of scalling in axis V
|
||||||
*/
|
*/
|
||||||
public void setScaleV(double scaleV) {
|
public void setScaleV(double scaleV) {
|
||||||
|
for (AppearanceBuilder listener : configListeners.values()) {
|
||||||
|
listener.setScaleV(scaleV);
|
||||||
|
}
|
||||||
this.scaleV = scaleV;
|
this.scaleV = scaleV;
|
||||||
fireChangeEvent();
|
if (!bypassAppearanceChangeEvent) {
|
||||||
|
fireChangeEvent();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -379,7 +441,7 @@ public class AppearanceBuilder extends AbstractChangeSource {
|
|||||||
* sets a new value of axis Y for scalling in template
|
* sets a new value of axis Y for scalling in template
|
||||||
* fires change event
|
* fires change event
|
||||||
*
|
*
|
||||||
* @param scaleX the new value for axis Y
|
* @param scaleY the new value for axis Y
|
||||||
*/
|
*/
|
||||||
public void setScaleY(double scaleY) {
|
public void setScaleY(double scaleY) {
|
||||||
setScaleV(1.0 / scaleY);
|
setScaleV(1.0 / scaleY);
|
||||||
@ -401,14 +463,19 @@ public class AppearanceBuilder extends AbstractChangeSource {
|
|||||||
* @param rotation the new value for rotation in template
|
* @param rotation the new value for rotation in template
|
||||||
*/
|
*/
|
||||||
public void setRotation(double rotation) {
|
public void setRotation(double rotation) {
|
||||||
|
for (AppearanceBuilder listener : configListeners.values()) {
|
||||||
|
listener.setRotation(rotation);
|
||||||
|
}
|
||||||
this.rotation = rotation;
|
this.rotation = rotation;
|
||||||
fireChangeEvent();
|
if (!bypassAppearanceChangeEvent) {
|
||||||
|
fireChangeEvent();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gets the current image in template
|
* gets the current image in template
|
||||||
*
|
*
|
||||||
* @param the current image in template
|
* @return the current image in template
|
||||||
*/
|
*/
|
||||||
public DecalImage getImage() {
|
public DecalImage getImage() {
|
||||||
return image;
|
return image;
|
||||||
@ -421,8 +488,13 @@ public class AppearanceBuilder extends AbstractChangeSource {
|
|||||||
* @param image the new image to be used as template
|
* @param image the new image to be used as template
|
||||||
*/
|
*/
|
||||||
public void setImage(DecalImage image) {
|
public void setImage(DecalImage image) {
|
||||||
|
for (AppearanceBuilder listener : configListeners.values()) {
|
||||||
|
listener.setImage(image);
|
||||||
|
}
|
||||||
this.image = image;
|
this.image = image;
|
||||||
fireChangeEvent();
|
if (!bypassAppearanceChangeEvent) {
|
||||||
|
fireChangeEvent();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -441,8 +513,13 @@ public class AppearanceBuilder extends AbstractChangeSource {
|
|||||||
* @param edgeMode the new edgeMode to be used
|
* @param edgeMode the new edgeMode to be used
|
||||||
*/
|
*/
|
||||||
public void setEdgeMode(Decal.EdgeMode edgeMode) {
|
public void setEdgeMode(Decal.EdgeMode edgeMode) {
|
||||||
|
for (AppearanceBuilder listener : configListeners.values()) {
|
||||||
|
listener.setEdgeMode(edgeMode);
|
||||||
|
}
|
||||||
this.edgeMode = edgeMode;
|
this.edgeMode = edgeMode;
|
||||||
fireChangeEvent();
|
if (!bypassAppearanceChangeEvent) {
|
||||||
|
fireChangeEvent();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -455,15 +532,55 @@ public class AppearanceBuilder extends AbstractChangeSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* function that garantees that chenges event only occurs after all changes are made
|
* function that guarantees that changes event only occurs after all changes are made
|
||||||
*
|
*
|
||||||
* param r the functor to be executed
|
* param r the functor to be executed
|
||||||
*/
|
*/
|
||||||
public void batch(Runnable r) {
|
public void batch(Runnable r) {
|
||||||
|
for (AppearanceBuilder listener : configListeners.values()) {
|
||||||
|
listener.batch(r);
|
||||||
|
}
|
||||||
batch = true;
|
batch = true;
|
||||||
r.run();
|
r.run();
|
||||||
batch = false;
|
batch = false;
|
||||||
fireChangeEvent();
|
if (!bypassAppearanceChangeEvent) {
|
||||||
|
fireChangeEvent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a new config listener that will undergo the same configuration changes as this AppearanceBuilder.
|
||||||
|
* @param component the component to add as a config listener
|
||||||
|
* @param ab new AppearanceBuilder config listener
|
||||||
|
* @return true if listener was successfully added, false if not
|
||||||
|
*/
|
||||||
|
public boolean addConfigListener(RocketComponent component, AppearanceBuilder ab) {
|
||||||
|
if (component == null || ab == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
configListeners.put(component, ab);
|
||||||
|
ab.setBypassChangeEvent(true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeConfigListener(RocketComponent listener) {
|
||||||
|
configListeners.remove(listener);
|
||||||
|
listener.setBypassChangeEvent(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearConfigListeners() {
|
||||||
|
for (AppearanceBuilder listener : configListeners.values()) {
|
||||||
|
listener.setBypassChangeEvent(false);
|
||||||
|
}
|
||||||
|
configListeners.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<RocketComponent, AppearanceBuilder> getConfigListeners() {
|
||||||
|
return configListeners;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBypassChangeEvent(boolean newValue) {
|
||||||
|
this.bypassAppearanceChangeEvent = newValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -123,7 +123,7 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
|
|||||||
private Appearance appearance = null;
|
private Appearance appearance = null;
|
||||||
|
|
||||||
// If true, component change events will not be fired
|
// If true, component change events will not be fired
|
||||||
private boolean ignoreComponentChange = false;
|
private boolean bypassComponentChangeEvent = false;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -464,10 +464,6 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
|
|||||||
* @param appearance
|
* @param appearance
|
||||||
*/
|
*/
|
||||||
public void setAppearance(Appearance appearance) {
|
public void setAppearance(Appearance appearance) {
|
||||||
for (RocketComponent listener : configListeners) {
|
|
||||||
listener.setAppearance(appearance);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.appearance = appearance;
|
this.appearance = appearance;
|
||||||
if (this.appearance != null) {
|
if (this.appearance != null) {
|
||||||
Decal d = this.appearance.getTexture();
|
Decal d = this.appearance.getTexture();
|
||||||
@ -581,9 +577,9 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
|
|||||||
*/
|
*/
|
||||||
public final void setMassOverridden(boolean o) {
|
public final void setMassOverridden(boolean o) {
|
||||||
for (RocketComponent listener : configListeners) {
|
for (RocketComponent listener : configListeners) {
|
||||||
listener.setIgnoreComponentChange(false);
|
listener.setBypassChangeEvent(false);
|
||||||
listener.setMassOverridden(o);
|
listener.setMassOverridden(o);
|
||||||
listener.setIgnoreComponentChange(false);
|
listener.setBypassChangeEvent(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (massOverridden == o) {
|
if (massOverridden == o) {
|
||||||
@ -655,9 +651,9 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
|
|||||||
*/
|
*/
|
||||||
public final void setCGOverridden(boolean o) {
|
public final void setCGOverridden(boolean o) {
|
||||||
for (RocketComponent listener : configListeners) {
|
for (RocketComponent listener : configListeners) {
|
||||||
listener.setIgnoreComponentChange(false);
|
listener.setBypassChangeEvent(false);
|
||||||
listener.setCGOverridden(o);
|
listener.setCGOverridden(o);
|
||||||
listener.setIgnoreComponentChange(true);
|
listener.setBypassChangeEvent(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cgOverridden == o) {
|
if (cgOverridden == o) {
|
||||||
@ -806,9 +802,9 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
|
|||||||
*/
|
*/
|
||||||
public final void setName(String name) {
|
public final void setName(String name) {
|
||||||
for (RocketComponent listener : configListeners) {
|
for (RocketComponent listener : configListeners) {
|
||||||
listener.setIgnoreComponentChange(false);
|
listener.setBypassChangeEvent(false);
|
||||||
listener.setName(name);
|
listener.setName(name);
|
||||||
listener.setIgnoreComponentChange(true);
|
listener.setBypassChangeEvent(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.name.equals(name)) {
|
if (this.name.equals(name)) {
|
||||||
@ -1671,6 +1667,24 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether all components in the list have the same class as this component.
|
||||||
|
* @param components list to check
|
||||||
|
* @return true if all components are of the same class, false if not
|
||||||
|
*/
|
||||||
|
public boolean checkAllClassesEqual(List<RocketComponent> components) {
|
||||||
|
if (components == null || components.size() == 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
Class<? extends RocketComponent> myClass = this.getClass();
|
||||||
|
for (RocketComponent c : components) {
|
||||||
|
if (!c.getClass().equals(myClass)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the root component of the component tree.
|
* Get the root component of the component tree.
|
||||||
@ -1936,7 +1950,7 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
|
|||||||
*/
|
*/
|
||||||
protected void fireComponentChangeEvent(ComponentChangeEvent e) {
|
protected void fireComponentChangeEvent(ComponentChangeEvent e) {
|
||||||
checkState();
|
checkState();
|
||||||
if (parent == null || ignoreComponentChange) {
|
if (parent == null || bypassComponentChangeEvent) {
|
||||||
/* Ignore if root invalid. */
|
/* Ignore if root invalid. */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1955,37 +1969,36 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
|
|||||||
fireComponentChangeEvent(new ComponentChangeEvent(this, type));
|
fireComponentChangeEvent(new ComponentChangeEvent(this, type));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setIgnoreComponentChange(boolean newValue) {
|
public void setBypassChangeEvent(boolean newValue) {
|
||||||
this.ignoreComponentChange = newValue;
|
this.bypassComponentChangeEvent = newValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getIgnoreComponentChange() {
|
public boolean getBypassComponentChangeEvent() {
|
||||||
return this.ignoreComponentChange;
|
return this.bypassComponentChangeEvent;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a new config listener that will undergo the same configuration changes as this.component. Listener must be
|
* Add a new config listener that will undergo the same configuration changes as this.component.
|
||||||
* of the same class as this.component.
|
|
||||||
* @param listener new config listener
|
* @param listener new config listener
|
||||||
* @return true if listener was successfully added, false if not
|
* @return true if listener was successfully added, false if not
|
||||||
*/
|
*/
|
||||||
public boolean addConfigListener(RocketComponent listener) {
|
public boolean addConfigListener(RocketComponent listener) {
|
||||||
if (listener == null || !this.getClass().equals(listener.getClass())) {
|
if (listener == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
configListeners.add(listener);
|
configListeners.add(listener);
|
||||||
listener.setIgnoreComponentChange(true);
|
listener.setBypassChangeEvent(true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeConfigListener(RocketComponent listener) {
|
public void removeConfigListener(RocketComponent listener) {
|
||||||
configListeners.remove(listener);
|
configListeners.remove(listener);
|
||||||
listener.setIgnoreComponentChange(false);
|
listener.setBypassChangeEvent(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clearConfigListeners() {
|
public void clearConfigListeners() {
|
||||||
for (RocketComponent listener : configListeners) {
|
for (RocketComponent listener : configListeners) {
|
||||||
listener.setIgnoreComponentChange(false);
|
listener.setBypassChangeEvent(false);
|
||||||
}
|
}
|
||||||
configListeners.clear();
|
configListeners.clear();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
package net.sf.openrocket.gui.components;
|
package net.sf.openrocket.gui.components;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
import java.awt.Font;
|
import java.awt.Font;
|
||||||
|
|
||||||
import javax.swing.JLabel;
|
import javax.swing.JLabel;
|
||||||
@ -87,11 +88,9 @@ public class StyledLabel extends JLabel {
|
|||||||
|
|
||||||
private void checkPreferredSize(float size, Style style) {
|
private void checkPreferredSize(float size, Style style) {
|
||||||
String str = this.getText();
|
String str = this.getText();
|
||||||
if (str.startsWith("<html>") && str.indexOf("<br") < 0) {
|
if (str.startsWith("<html>") && !str.contains("<br")) {
|
||||||
StyledLabel label = new StyledLabel("plaintext", size, style);
|
StyledLabel label = new StyledLabel("plaintext", size, style);
|
||||||
label.validate();
|
label.validate();
|
||||||
//System.out.println("Plain-text label: " + label.getPreferredSize());
|
|
||||||
//System.out.println("HTML label: " + this.getPreferredSize());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,4 +107,8 @@ public class StyledLabel extends JLabel {
|
|||||||
font = font.deriveFont(style.getFontStyle());
|
font = font.deriveFont(style.getFontStyle());
|
||||||
this.setFont(font);
|
this.setFont(font);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setFontColor(Color color) {
|
||||||
|
this.setForeground(color);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -107,6 +107,15 @@ public class AppearancePanel extends JPanel {
|
|||||||
|
|
||||||
private static final JColorChooser colorChooser = new JColorChooser();
|
private static final JColorChooser colorChooser = new JColorChooser();
|
||||||
|
|
||||||
|
public void clearConfigListeners() {
|
||||||
|
if (ab != null) {
|
||||||
|
ab.clearConfigListeners();
|
||||||
|
}
|
||||||
|
if (insideAb != null) {
|
||||||
|
insideAb.clearConfigListeners();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private class ColorActionListener implements ActionListener {
|
private class ColorActionListener implements ActionListener {
|
||||||
private final String valueName;
|
private final String valueName;
|
||||||
private final Object o;
|
private final Object o;
|
||||||
@ -198,23 +207,44 @@ public class AppearancePanel extends JPanel {
|
|||||||
|
|
||||||
previousUserSelectedAppearance = c.getAppearance();
|
previousUserSelectedAppearance = c.getAppearance();
|
||||||
if (previousUserSelectedAppearance == null) {
|
if (previousUserSelectedAppearance == null) {
|
||||||
previousUserSelectedAppearance = new AppearanceBuilder()
|
previousUserSelectedAppearance = new AppearanceBuilder().getAppearance();
|
||||||
.getAppearance();
|
|
||||||
ab = new AppearanceBuilder(defaultAppearance);
|
ab = new AppearanceBuilder(defaultAppearance);
|
||||||
} else {
|
} else {
|
||||||
ab = new AppearanceBuilder(previousUserSelectedAppearance);
|
ab = new AppearanceBuilder(previousUserSelectedAppearance);
|
||||||
}
|
}
|
||||||
|
for (RocketComponent listener : c.getConfigListeners()) {
|
||||||
|
Appearance a = listener.getAppearance();
|
||||||
|
AppearanceBuilder appearanceBuilder = new AppearanceBuilder(a);
|
||||||
|
ab.addConfigListener(listener, appearanceBuilder);
|
||||||
|
}
|
||||||
|
|
||||||
if (c instanceof InsideColorComponent) {
|
// Check if all InsideColorComponent
|
||||||
|
boolean allInsideColor = c instanceof InsideColorComponent;
|
||||||
|
if (allInsideColor) {
|
||||||
|
for (RocketComponent listener : c.getConfigListeners()) {
|
||||||
|
if (!(listener instanceof InsideColorComponent)) {
|
||||||
|
allInsideColor = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (allInsideColor) {
|
||||||
previousUserSelectedInsideAppearance = ((InsideColorComponent) c).getInsideColorComponentHandler()
|
previousUserSelectedInsideAppearance = ((InsideColorComponent) c).getInsideColorComponentHandler()
|
||||||
.getInsideAppearance();
|
.getInsideAppearance();
|
||||||
if (previousUserSelectedInsideAppearance == null) {
|
if (previousUserSelectedInsideAppearance == null) {
|
||||||
previousUserSelectedInsideAppearance = new AppearanceBuilder()
|
previousUserSelectedInsideAppearance = new AppearanceBuilder().getAppearance();
|
||||||
.getAppearance();
|
|
||||||
insideAb = new AppearanceBuilder(defaultAppearance);
|
insideAb = new AppearanceBuilder(defaultAppearance);
|
||||||
} else {
|
} else {
|
||||||
insideAb = new AppearanceBuilder(previousUserSelectedInsideAppearance);
|
insideAb = new AppearanceBuilder(previousUserSelectedInsideAppearance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (RocketComponent listener : c.getConfigListeners()) {
|
||||||
|
Appearance a = ((InsideColorComponent) listener).getInsideColorComponentHandler()
|
||||||
|
.getInsideAppearance();
|
||||||
|
AppearanceBuilder appearanceBuilder = new AppearanceBuilder(a);
|
||||||
|
insideAb.addConfigListener(listener, appearanceBuilder);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
net.sf.openrocket.util.Color figureColor = c.getColor();
|
net.sf.openrocket.util.Color figureColor = c.getColor();
|
||||||
@ -317,7 +347,7 @@ public class AppearancePanel extends JPanel {
|
|||||||
add(new JSeparator(SwingConstants.HORIZONTAL), "span, wrap, growx");
|
add(new JSeparator(SwingConstants.HORIZONTAL), "span, wrap, growx");
|
||||||
|
|
||||||
// Display a tabbed panel for choosing the outside and inside appearance, if the object is of type InsideColorComponent
|
// Display a tabbed panel for choosing the outside and inside appearance, if the object is of type InsideColorComponent
|
||||||
if (c instanceof InsideColorComponent) {
|
if (allInsideColor) {
|
||||||
InsideColorComponentHandler handler = ((InsideColorComponent)c).getInsideColorComponentHandler();
|
InsideColorComponentHandler handler = ((InsideColorComponent)c).getInsideColorComponentHandler();
|
||||||
|
|
||||||
// Get translator keys
|
// Get translator keys
|
||||||
@ -444,6 +474,20 @@ public class AppearancePanel extends JPanel {
|
|||||||
DecalModel decalModel = new DecalModel(panel, document, builder);
|
DecalModel decalModel = new DecalModel(panel, document, builder);
|
||||||
JComboBox<DecalImage> textureDropDown = new JComboBox<DecalImage>(decalModel);
|
JComboBox<DecalImage> textureDropDown = new JComboBox<DecalImage>(decalModel);
|
||||||
|
|
||||||
|
// We need to add this action listener that triggers a decalModel update when the same item is selected, because
|
||||||
|
// for multi-comp edits, the listeners' decals may not be updated otherwise
|
||||||
|
textureDropDown.addActionListener(new ActionListener() {
|
||||||
|
private DecalImage previousSelection = (DecalImage) decalModel.getSelectedItem();
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
DecalImage decal = (DecalImage) textureDropDown.getSelectedItem();
|
||||||
|
if (decal == previousSelection) {
|
||||||
|
decalModel.setSelectedItem(decal);
|
||||||
|
}
|
||||||
|
previousSelection = decal;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
JButton colorButton = new SelectColorButton(new ColorIcon(builder.getPaint()));
|
JButton colorButton = new SelectColorButton(new ColorIcon(builder.getPaint()));
|
||||||
|
|
||||||
colorButton.addActionListener(new ColorActionListener(builder, "Paint"));
|
colorButton.addActionListener(new ColorActionListener(builder, "Paint"));
|
||||||
@ -464,13 +508,31 @@ public class AppearancePanel extends JPanel {
|
|||||||
previousUserSelectedInsideAppearance = (builder == null) ? null
|
previousUserSelectedInsideAppearance = (builder == null) ? null
|
||||||
: builder.getAppearance();
|
: builder.getAppearance();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set the listeners' appearance to the default appearance
|
||||||
|
for (RocketComponent listener : builder.getConfigListeners().keySet()) {
|
||||||
|
builder.getConfigListeners().get(listener).setAppearance(defaultAppearance);
|
||||||
|
listener.setAppearance(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set this component's appearance to the default appearance
|
||||||
builder.setAppearance(defaultAppearance);
|
builder.setAppearance(defaultAppearance);
|
||||||
c.setAppearance(null);
|
c.setAppearance(null);
|
||||||
} else {
|
} else {
|
||||||
if (!insideBuilder)
|
if (!insideBuilder) {
|
||||||
|
// Set the listeners' appearance to the previous user selected appearance
|
||||||
|
for (AppearanceBuilder listener : builder.getConfigListeners().values()) {
|
||||||
|
listener.setAppearance(previousUserSelectedAppearance);
|
||||||
|
}
|
||||||
builder.setAppearance(previousUserSelectedAppearance);
|
builder.setAppearance(previousUserSelectedAppearance);
|
||||||
else
|
}
|
||||||
|
else {
|
||||||
|
// Set the listeners' inside appearance to the previous user selected appearance
|
||||||
|
for (AppearanceBuilder listener : builder.getConfigListeners().values()) {
|
||||||
|
listener.setAppearance(previousUserSelectedInsideAppearance);
|
||||||
|
}
|
||||||
builder.setAppearance(previousUserSelectedInsideAppearance);
|
builder.setAppearance(previousUserSelectedInsideAppearance);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -551,9 +613,9 @@ public class AppearancePanel extends JPanel {
|
|||||||
mDefault.addEnableComponent(spinShine, false);
|
mDefault.addEnableComponent(spinShine, false);
|
||||||
mDefault.addEnableComponent(unitShine, false);
|
mDefault.addEnableComponent(unitShine, false);
|
||||||
|
|
||||||
panel.add(spinShine, "split 3, w 50");
|
panel.add(spinShine, "split 3, w 60");
|
||||||
panel.add(unitShine);
|
panel.add(unitShine);
|
||||||
panel.add(slideShine, "w 50");
|
panel.add(slideShine, "w 50, growx");
|
||||||
|
|
||||||
// Offset
|
// Offset
|
||||||
panel.add(new JLabel(trans.get("AppearanceCfg.lbl.texture.offset")));
|
panel.add(new JLabel(trans.get("AppearanceCfg.lbl.texture.offset")));
|
||||||
@ -585,9 +647,9 @@ public class AppearancePanel extends JPanel {
|
|||||||
mDefault.addEnableComponent(spinOpacity, false);
|
mDefault.addEnableComponent(spinOpacity, false);
|
||||||
mDefault.addEnableComponent(unitOpacity, false);
|
mDefault.addEnableComponent(unitOpacity, false);
|
||||||
|
|
||||||
panel.add(spinOpacity, "split 3, w 50");
|
panel.add(spinOpacity, "split 3, w 60");
|
||||||
panel.add(unitOpacity);
|
panel.add(unitOpacity);
|
||||||
panel.add(slideOpacity, "w 50");
|
panel.add(slideOpacity, "w 50, growx");
|
||||||
|
|
||||||
// Rotation
|
// Rotation
|
||||||
panel.add(new JLabel(trans.get("AppearanceCfg.lbl.texture.rotation")));
|
panel.add(new JLabel(trans.get("AppearanceCfg.lbl.texture.rotation")));
|
||||||
@ -622,10 +684,24 @@ public class AppearancePanel extends JPanel {
|
|||||||
opacityModel.stateChanged(null);
|
opacityModel.stateChanged(null);
|
||||||
lastOpacity = builder.getOpacity();
|
lastOpacity = builder.getOpacity();
|
||||||
}
|
}
|
||||||
if (!insideBuilder)
|
if (!insideBuilder) {
|
||||||
|
// Set the listeners' outside appearance
|
||||||
|
for (RocketComponent listener : builder.getConfigListeners().keySet()) {
|
||||||
|
listener.setAppearance(builder.getConfigListeners().get(listener).getAppearance());
|
||||||
|
}
|
||||||
|
// Set this component's outside appearance
|
||||||
c.setAppearance(builder.getAppearance());
|
c.setAppearance(builder.getAppearance());
|
||||||
else
|
}
|
||||||
((InsideColorComponent)c).getInsideColorComponentHandler().setInsideAppearance(builder.getAppearance());
|
else {
|
||||||
|
// Set the listeners' inside appearance
|
||||||
|
for (RocketComponent listener : builder.getConfigListeners().keySet()) {
|
||||||
|
if (!(listener instanceof InsideColorComponent)) continue;
|
||||||
|
((InsideColorComponent) listener).getInsideColorComponentHandler()
|
||||||
|
.setInsideAppearance(builder.getConfigListeners().get(listener).getAppearance());
|
||||||
|
}
|
||||||
|
// Set this component's inside appearance
|
||||||
|
((InsideColorComponent) c).getInsideColorComponentHandler().setInsideAppearance(builder.getAppearance());
|
||||||
|
}
|
||||||
decalModel.refresh();
|
decalModel.refresh();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@ -14,8 +14,10 @@ import net.sf.openrocket.document.OpenRocketDocument;
|
|||||||
import net.sf.openrocket.gui.util.GUIUtil;
|
import net.sf.openrocket.gui.util.GUIUtil;
|
||||||
import net.sf.openrocket.gui.util.SwingPreferences;
|
import net.sf.openrocket.gui.util.SwingPreferences;
|
||||||
import net.sf.openrocket.l10n.Translator;
|
import net.sf.openrocket.l10n.Translator;
|
||||||
|
import net.sf.openrocket.rocketcomponent.AxialStage;
|
||||||
import net.sf.openrocket.rocketcomponent.ComponentChangeEvent;
|
import net.sf.openrocket.rocketcomponent.ComponentChangeEvent;
|
||||||
import net.sf.openrocket.rocketcomponent.ComponentChangeListener;
|
import net.sf.openrocket.rocketcomponent.ComponentChangeListener;
|
||||||
|
import net.sf.openrocket.rocketcomponent.Rocket;
|
||||||
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
||||||
import net.sf.openrocket.startup.Application;
|
import net.sf.openrocket.startup.Application;
|
||||||
import net.sf.openrocket.util.BugException;
|
import net.sf.openrocket.util.BugException;
|
||||||
@ -25,7 +27,7 @@ import net.sf.openrocket.util.Reflection;
|
|||||||
* A dialog that contains the configuration elements of one component.
|
* A dialog that contains the configuration elements of one component.
|
||||||
* The contents of the dialog are instantiated from CONFIGDIALOGPACKAGE according
|
* The contents of the dialog are instantiated from CONFIGDIALOGPACKAGE according
|
||||||
* to the current component.
|
* to the current component.
|
||||||
*
|
*
|
||||||
* @author Sampo Niskanen <sampo.niskanen@iki.fi>
|
* @author Sampo Niskanen <sampo.niskanen@iki.fi>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -33,26 +35,26 @@ public class ComponentConfigDialog extends JDialog implements ComponentChangeLis
|
|||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
private static final String CONFIGDIALOGPACKAGE = "net.sf.openrocket.gui.configdialog";
|
private static final String CONFIGDIALOGPACKAGE = "net.sf.openrocket.gui.configdialog";
|
||||||
private static final String CONFIGDIALOGPOSTFIX = "Config";
|
private static final String CONFIGDIALOGPOSTFIX = "Config";
|
||||||
|
|
||||||
// Static Value -- This is a singleton value, and we should only have zero or one active at any time
|
// Static Value -- This is a singleton value, and we should only have zero or one active at any time
|
||||||
private static ComponentConfigDialog dialog = null;
|
private static ComponentConfigDialog dialog = null;
|
||||||
|
|
||||||
private OpenRocketDocument document = null;
|
|
||||||
private RocketComponent component = null;
|
|
||||||
private RocketComponentConfig configurator = null;
|
|
||||||
|
|
||||||
|
private OpenRocketDocument document = null;
|
||||||
|
protected RocketComponent component = null;
|
||||||
|
private RocketComponentConfig configurator = null;
|
||||||
|
protected static boolean clearConfigListeners = true;
|
||||||
private static String previousSelectedTab = null; // Name of the previous selected tab
|
private static String previousSelectedTab = null; // Name of the previous selected tab
|
||||||
|
|
||||||
|
|
||||||
private final Window parent;
|
private final Window parent;
|
||||||
private static final Translator trans = Application.getTranslator();
|
private static final Translator trans = Application.getTranslator();
|
||||||
|
|
||||||
private ComponentConfigDialog(Window parent, OpenRocketDocument document, RocketComponent component,
|
private ComponentConfigDialog(Window parent, OpenRocketDocument document, RocketComponent component) {
|
||||||
List<RocketComponent> listeners) {
|
|
||||||
super(parent);
|
super(parent);
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
|
|
||||||
setComponent(document, component);
|
setComponent(document, component);
|
||||||
|
|
||||||
GUIUtil.setDisposableDialogOptions(this, null);
|
GUIUtil.setDisposableDialogOptions(this, null);
|
||||||
GUIUtil.rememberWindowPosition(this);
|
GUIUtil.rememberWindowPosition(this);
|
||||||
|
|
||||||
@ -63,33 +65,28 @@ public class ComponentConfigDialog extends JDialog implements ComponentChangeLis
|
|||||||
* In fact, it should trigger for any method of closing the dialog.
|
* In fact, it should trigger for any method of closing the dialog.
|
||||||
*/
|
*/
|
||||||
public void windowClosed(WindowEvent e){
|
public void windowClosed(WindowEvent e){
|
||||||
|
configurator.clearConfigListeners();
|
||||||
configurator.invalidate();
|
configurator.invalidate();
|
||||||
document.getRocket().removeComponentChangeListener(ComponentConfigDialog.this);
|
document.getRocket().removeComponentChangeListener(ComponentConfigDialog.this);
|
||||||
ComponentConfigDialog.this.dispose();
|
ComponentConfigDialog.this.dispose();
|
||||||
component.clearConfigListeners();
|
if (clearConfigListeners) {
|
||||||
|
component.clearConfigListeners();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void windowClosing(WindowEvent e){}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void windowOpened(WindowEvent e) {
|
public void windowOpened(WindowEvent e) {
|
||||||
super.windowOpened(e);
|
super.windowOpened(e);
|
||||||
// Add config listeners
|
clearConfigListeners = true;
|
||||||
component.clearConfigListeners();
|
|
||||||
if (listeners != null) {
|
|
||||||
for (RocketComponent listener : listeners) {
|
|
||||||
component.addConfigListener(listener);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the component being configured. The listening connections of the old configurator
|
* Set the component being configured. The listening connections of the old configurator
|
||||||
* will be removed and the new ones created.
|
* will be removed and the new ones created.
|
||||||
*
|
*
|
||||||
* @param component Component to configure.
|
* @param component Component to configure.
|
||||||
*/
|
*/
|
||||||
private void setComponent(OpenRocketDocument document, RocketComponent component) {
|
private void setComponent(OpenRocketDocument document, RocketComponent component) {
|
||||||
@ -97,24 +94,43 @@ public class ComponentConfigDialog extends JDialog implements ComponentChangeLis
|
|||||||
// Remove listeners by setting all applicable models to null
|
// Remove listeners by setting all applicable models to null
|
||||||
GUIUtil.setNullModels(configurator); // null-safe
|
GUIUtil.setNullModels(configurator); // null-safe
|
||||||
}
|
}
|
||||||
|
|
||||||
this.document = document;
|
this.document = document;
|
||||||
this.component = component;
|
this.component = component;
|
||||||
this.document.getRocket().addComponentChangeListener(this);
|
this.document.getRocket().addComponentChangeListener(this);
|
||||||
|
|
||||||
configurator = getDialogContents();
|
configurator = getDialogContents();
|
||||||
this.setContentPane(configurator);
|
this.setContentPane(configurator);
|
||||||
configurator.updateFields();
|
configurator.updateFields();
|
||||||
|
|
||||||
// Set the selected tab
|
List<RocketComponent> listeners = component.getConfigListeners();
|
||||||
configurator.setSelectedTab(previousSelectedTab);
|
|
||||||
|
// Set the default tab to 'Appearance' for a different-type multi-comp dialog (this is the most prominent use case)
|
||||||
|
if (listeners != null && listeners.size() > 0 && !component.checkAllClassesEqual(listeners)) {
|
||||||
|
configurator.setSelectedTabIndex(1);
|
||||||
|
} else {
|
||||||
|
configurator.setSelectedTab(previousSelectedTab);
|
||||||
|
}
|
||||||
|
|
||||||
//// configuration
|
//// configuration
|
||||||
setTitle(trans.get("ComponentCfgDlg.configuration1") + " " + component.getComponentName() + " " + trans.get("ComponentCfgDlg.configuration"));
|
if (component.checkAllClassesEqual(listeners)) {
|
||||||
|
if (listeners != null && listeners.size() > 0) {
|
||||||
|
setTitle("(" + trans.get("ComponentCfgDlg.MultiComponent") + ") " +
|
||||||
|
component.getComponentName() + " " + trans.get("ComponentCfgDlg.configuration"));
|
||||||
|
} else {
|
||||||
|
setTitle(component.getComponentName() + " " + trans.get("ComponentCfgDlg.configuration"));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setTitle(trans.get("ComponentCfgDlg.MultiComponentConfig"));
|
||||||
|
}
|
||||||
|
|
||||||
this.pack();
|
this.pack();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public RocketComponent getComponent() {
|
||||||
|
return component;
|
||||||
|
}
|
||||||
|
|
||||||
public static ComponentConfigDialog getDialog() {
|
public static ComponentConfigDialog getDialog() {
|
||||||
return dialog;
|
return dialog;
|
||||||
}
|
}
|
||||||
@ -124,32 +140,36 @@ public class ComponentConfigDialog extends JDialog implements ComponentChangeLis
|
|||||||
* Return the configurator panel of the current component.
|
* Return the configurator panel of the current component.
|
||||||
*/
|
*/
|
||||||
private RocketComponentConfig getDialogContents() {
|
private RocketComponentConfig getDialogContents() {
|
||||||
Constructor<? extends RocketComponentConfig> c =
|
List<RocketComponent> listeners = component.getConfigListeners();
|
||||||
|
boolean isSameClass = component.checkAllClassesEqual(listeners);
|
||||||
|
if (!isSameClass) {
|
||||||
|
return new RocketComponentConfig(document, component);
|
||||||
|
}
|
||||||
|
|
||||||
|
Constructor<? extends RocketComponentConfig> constructor =
|
||||||
findDialogContentsConstructor(component);
|
findDialogContentsConstructor(component);
|
||||||
if (c != null) {
|
if (constructor != null) {
|
||||||
try {
|
try {
|
||||||
return c.newInstance(document, component);
|
return constructor.newInstance(document, component);
|
||||||
} catch (InstantiationException e) {
|
} catch (InstantiationException | IllegalAccessException e) {
|
||||||
throw new BugException("BUG in constructor reflection", e);
|
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
throw new BugException("BUG in constructor reflection", e);
|
throw new BugException("BUG in constructor reflection", e);
|
||||||
} catch (InvocationTargetException e) {
|
} catch (InvocationTargetException e) {
|
||||||
throw Reflection.handleWrappedException(e);
|
throw Reflection.handleWrappedException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Should never be reached, since RocketComponentConfig should catch all
|
// Should never be reached, since RocketComponentConfig should catch all
|
||||||
// components without their own configurator.
|
// components without their own configurator.
|
||||||
throw new BugException("Unable to find any configurator for " + component);
|
throw new BugException("Unable to find any configurator for " + component);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void componentChanged(ComponentChangeEvent e) {
|
public void componentChanged(ComponentChangeEvent e) {
|
||||||
if (e.isTreeChange() || e.isUndoChange()) {
|
if (e.isTreeChange() || e.isUndoChange()) {
|
||||||
|
|
||||||
// Hide dialog in case of tree or undo change
|
// Hide dialog in case of tree or undo change
|
||||||
disposeDialog();
|
disposeDialog();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
* TODO: HIGH: The line below has caused a NullPointerException (without null check)
|
* TODO: HIGH: The line below has caused a NullPointerException (without null check)
|
||||||
@ -161,10 +181,10 @@ public class ComponentConfigDialog extends JDialog implements ComponentChangeLis
|
|||||||
configurator.updateFields();
|
configurator.updateFields();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds the Constructor of the given component's config dialog panel in
|
* Finds the Constructor of the given component's config dialog panel in
|
||||||
* CONFIGDIALOGPACKAGE.
|
* CONFIGDIALOGPACKAGE.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@ -172,10 +192,10 @@ public class ComponentConfigDialog extends JDialog implements ComponentChangeLis
|
|||||||
Class<?> currentclass;
|
Class<?> currentclass;
|
||||||
String currentclassname;
|
String currentclassname;
|
||||||
String configclassname;
|
String configclassname;
|
||||||
|
|
||||||
Class<?> configclass;
|
Class<?> configclass;
|
||||||
Constructor<? extends RocketComponentConfig> c;
|
Constructor<? extends RocketComponentConfig> c;
|
||||||
|
|
||||||
currentclass = component.getClass();
|
currentclass = component.getClass();
|
||||||
while ((currentclass != null) && (currentclass != Object.class)) {
|
while ((currentclass != null) && (currentclass != Object.class)) {
|
||||||
currentclassname = currentclass.getCanonicalName();
|
currentclassname = currentclass.getCanonicalName();
|
||||||
@ -184,7 +204,7 @@ public class ComponentConfigDialog extends JDialog implements ComponentChangeLis
|
|||||||
currentclassname = currentclassname.substring(index + 1);
|
currentclassname = currentclassname.substring(index + 1);
|
||||||
configclassname = CONFIGDIALOGPACKAGE + "." + currentclassname +
|
configclassname = CONFIGDIALOGPACKAGE + "." + currentclassname +
|
||||||
CONFIGDIALOGPOSTFIX;
|
CONFIGDIALOGPOSTFIX;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
configclass = Class.forName(configclassname);
|
configclass = Class.forName(configclassname);
|
||||||
c = (Constructor<? extends RocketComponentConfig>)
|
c = (Constructor<? extends RocketComponentConfig>)
|
||||||
@ -192,69 +212,57 @@ public class ComponentConfigDialog extends JDialog implements ComponentChangeLis
|
|||||||
return c;
|
return c;
|
||||||
} catch (Exception ignore) {
|
} catch (Exception ignore) {
|
||||||
}
|
}
|
||||||
|
|
||||||
currentclass = currentclass.getSuperclass();
|
currentclass = currentclass.getSuperclass();
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
////////// Static dialog /////////
|
////////// Static dialog /////////
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A singleton configuration dialog. Will create and show a new dialog if one has not
|
* A singleton configuration dialog. Will create and show a new dialog if one has not
|
||||||
* previously been used, or update the dialog and show it if a previous one exists.
|
* previously been used, or update the dialog and show it if a previous one exists.
|
||||||
*
|
*
|
||||||
* @param document the document to configure.
|
* @param document the document to configure.
|
||||||
* @param component the component to configure.
|
* @param component the component to configure.
|
||||||
* @param listeners config listeners for the component
|
|
||||||
* @param rememberPreviousTab if true, the previous tab will be remembered and used for the new dialog
|
* @param rememberPreviousTab if true, the previous tab will be remembered and used for the new dialog
|
||||||
*/
|
*/
|
||||||
public static void showDialog(Window parent, OpenRocketDocument document,
|
public static void showDialog(Window parent, OpenRocketDocument document, RocketComponent component, boolean rememberPreviousTab) {
|
||||||
RocketComponent component, List<RocketComponent> listeners, boolean rememberPreviousTab) {
|
|
||||||
if (dialog != null) {
|
if (dialog != null) {
|
||||||
previousSelectedTab = dialog.getSelectedTabName();
|
// Don't remember the previous tab for rockets or stages, because this will leave you in the override tab for
|
||||||
|
// the next component, which is generally not what you want.
|
||||||
|
if (dialog.getComponent() instanceof Rocket ||
|
||||||
|
(dialog.getComponent() instanceof AxialStage && !(component instanceof AxialStage))) {
|
||||||
|
previousSelectedTab = null;
|
||||||
|
} else {
|
||||||
|
previousSelectedTab = dialog.getSelectedTabName();
|
||||||
|
}
|
||||||
|
// If the component is the same as the ComponentConfigDialog component, and the dialog is still visible,
|
||||||
|
// that means that the user did a ctr/cmd click on a new component => don't remove the config listeners of component
|
||||||
|
if (component == dialog.getComponent()) {
|
||||||
|
ComponentConfigDialog.clearConfigListeners = false;
|
||||||
|
}
|
||||||
dialog.dispose();
|
dialog.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
final SwingPreferences preferences = (SwingPreferences) Application.getPreferences();
|
final SwingPreferences preferences = (SwingPreferences) Application.getPreferences();
|
||||||
if (preferences.isAlwaysOpenLeftmostTab() || !rememberPreviousTab) {
|
if (preferences.isAlwaysOpenLeftmostTab() || !rememberPreviousTab) {
|
||||||
previousSelectedTab = null;
|
previousSelectedTab = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
dialog = new ComponentConfigDialog(parent, document, component, listeners);
|
dialog = new ComponentConfigDialog(parent, document, component);
|
||||||
dialog.setVisible(true);
|
dialog.setVisible(true);
|
||||||
|
|
||||||
////Modify
|
////Modify
|
||||||
document.addUndoPosition(trans.get("ComponentCfgDlg.Modify") + " " + component.getComponentName());
|
if (component.getConfigListeners().size() == 0) {
|
||||||
}
|
document.addUndoPosition(trans.get("ComponentCfgDlg.Modify") + " " + component.getComponentName());
|
||||||
|
} else {
|
||||||
/**
|
document.addUndoPosition(trans.get("ComponentCfgDlg.ModifyComponents"));
|
||||||
* A singleton configuration dialog. Will create and show a new dialog if one has not
|
}
|
||||||
* previously been used, or update the dialog and show it if a previous one exists.
|
|
||||||
* By default, the previous tab is remembered.
|
|
||||||
*
|
|
||||||
* @param document the document to configure.
|
|
||||||
* @param component the component to configure.
|
|
||||||
* @param listeners config listeners for the component
|
|
||||||
*/
|
|
||||||
public static void showDialog(Window parent, OpenRocketDocument document,
|
|
||||||
RocketComponent component, List<RocketComponent> listeners) {
|
|
||||||
ComponentConfigDialog.showDialog(parent, document, component, listeners, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A singleton configuration dialog. Will create and show a new dialog if one has not
|
|
||||||
* previously been used, or update the dialog and show it if a previous one exists.
|
|
||||||
*
|
|
||||||
* @param document the document to configure.
|
|
||||||
* @param component the component to configure.
|
|
||||||
* @param rememberPreviousTab if true, the previous tab will be remembered and used for the new dialog
|
|
||||||
*/
|
|
||||||
public static void showDialog(Window parent, OpenRocketDocument document,
|
|
||||||
RocketComponent component, boolean rememberPreviousTab) {
|
|
||||||
ComponentConfigDialog.showDialog(parent, document, component, null, rememberPreviousTab);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -265,26 +273,20 @@ public class ComponentConfigDialog extends JDialog implements ComponentChangeLis
|
|||||||
* @param document the document to configure.
|
* @param document the document to configure.
|
||||||
* @param component the component to configure.
|
* @param component the component to configure.
|
||||||
*/
|
*/
|
||||||
public static void showDialog(Window parent, OpenRocketDocument document,
|
public static void showDialog(Window parent, OpenRocketDocument document, RocketComponent component) {
|
||||||
RocketComponent component) {
|
ComponentConfigDialog.showDialog(parent, document, component, true);
|
||||||
ComponentConfigDialog.showDialog(parent, document, component, null, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void showDialog(RocketComponent component, List<RocketComponent> listeners, boolean rememberPreviousTab) {
|
static void showDialog(RocketComponent component, boolean rememberPreviousTab) {
|
||||||
showDialog(dialog.parent, dialog.document, component, listeners, rememberPreviousTab);
|
showDialog(dialog.parent, dialog.document, component, rememberPreviousTab);
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* package */
|
|
||||||
static void showDialog(RocketComponent component, List<RocketComponent> listeners) {
|
|
||||||
showDialog(dialog.parent, dialog.document, component, listeners, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* package */
|
/* package */
|
||||||
static void showDialog(RocketComponent component) {
|
static void showDialog(RocketComponent component) {
|
||||||
ComponentConfigDialog.showDialog(component, null);
|
showDialog(dialog.parent, dialog.document, component, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Disposes the configuration dialog. May be used even if not currently visible.
|
* Disposes the configuration dialog. May be used even if not currently visible.
|
||||||
*/
|
*/
|
||||||
@ -293,8 +295,8 @@ public class ComponentConfigDialog extends JDialog implements ComponentChangeLis
|
|||||||
dialog.dispose();
|
dialog.dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether the singleton configuration dialog is currently visible or not.
|
* Returns whether the singleton configuration dialog is currently visible or not.
|
||||||
*/
|
*/
|
||||||
@ -302,6 +304,10 @@ public class ComponentConfigDialog extends JDialog implements ComponentChangeLis
|
|||||||
return (dialog != null) && (dialog.isVisible());
|
return (dialog != null) && (dialog.isVisible());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getSelectedTabIndex() {
|
||||||
|
return configurator.getSelectedTabIndex();
|
||||||
|
}
|
||||||
|
|
||||||
public String getSelectedTabName() {
|
public String getSelectedTabName() {
|
||||||
if (configurator != null) {
|
if (configurator != null) {
|
||||||
return configurator.getSelectedTabName();
|
return configurator.getSelectedTabName();
|
||||||
|
|||||||
@ -82,17 +82,10 @@ public abstract class FinSetConfig extends RocketComponentConfig {
|
|||||||
//// Convert fin set
|
//// Convert fin set
|
||||||
document.addUndoPosition(trans.get("FinSetConfig.Convertfinset"));
|
document.addUndoPosition(trans.get("FinSetConfig.Convertfinset"));
|
||||||
|
|
||||||
List<RocketComponent> listeners = new ArrayList<>();
|
|
||||||
for (RocketComponent listener : component.getConfigListeners()) {
|
|
||||||
if (listener instanceof FinSet) {
|
|
||||||
listeners.add(FreeformFinSet.convertFinSet((FinSet) listener));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RocketComponent freeform =
|
RocketComponent freeform =
|
||||||
FreeformFinSet.convertFinSet((FinSet) component);
|
FreeformFinSet.convertFinSet((FinSet) component);
|
||||||
|
|
||||||
ComponentConfigDialog.showDialog(freeform, listeners);
|
ComponentConfigDialog.showDialog(freeform);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package net.sf.openrocket.gui.configdialog;
|
package net.sf.openrocket.gui.configdialog;
|
||||||
|
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Container;
|
import java.awt.Container;
|
||||||
import java.awt.event.*;
|
import java.awt.event.*;
|
||||||
@ -39,7 +40,6 @@ import net.sf.openrocket.gui.widgets.SelectColorButton;
|
|||||||
import net.sf.openrocket.l10n.Translator;
|
import net.sf.openrocket.l10n.Translator;
|
||||||
import net.sf.openrocket.material.Material;
|
import net.sf.openrocket.material.Material;
|
||||||
import net.sf.openrocket.preset.ComponentPreset;
|
import net.sf.openrocket.preset.ComponentPreset;
|
||||||
import net.sf.openrocket.rocketcomponent.ComponentAssembly;
|
|
||||||
import net.sf.openrocket.rocketcomponent.*;
|
import net.sf.openrocket.rocketcomponent.*;
|
||||||
import net.sf.openrocket.rocketcomponent.ExternalComponent.Finish;
|
import net.sf.openrocket.rocketcomponent.ExternalComponent.Finish;
|
||||||
import net.sf.openrocket.rocketcomponent.position.AxialMethod;
|
import net.sf.openrocket.rocketcomponent.position.AxialMethod;
|
||||||
@ -66,22 +66,42 @@ public class RocketComponentConfig extends JPanel {
|
|||||||
private final TextFieldListener textFieldListener;
|
private final TextFieldListener textFieldListener;
|
||||||
|
|
||||||
private JPanel buttonPanel;
|
private JPanel buttonPanel;
|
||||||
|
private AppearancePanel appearancePanel = null;
|
||||||
|
|
||||||
private JLabel infoLabel;
|
private JLabel infoLabel;
|
||||||
|
private StyledLabel multiCompEditLabel;
|
||||||
|
|
||||||
|
private boolean allSameType; // Checks whether all listener components are of the same type as <component>
|
||||||
|
private boolean allMassive; // Checks whether all listener components, and this component, are massive
|
||||||
|
|
||||||
public RocketComponentConfig(OpenRocketDocument document, RocketComponent component) {
|
public RocketComponentConfig(OpenRocketDocument document, RocketComponent component) {
|
||||||
setLayout(new MigLayout("fill, gap 4!, ins panel", "[]:5[]", "[growprio 5]5![fill, grow, growprio 500]5![growprio 5]"));
|
setLayout(new MigLayout("fill, gap 4!, ins panel", "[]:5[]", "[growprio 5]5![fill, grow, growprio 500]5![growprio 5]"));
|
||||||
|
|
||||||
this.document = document;
|
this.document = document;
|
||||||
this.component = component;
|
this.component = component;
|
||||||
|
|
||||||
|
// Check the listeners for the same type and massive status
|
||||||
|
allSameType = true;
|
||||||
|
allMassive = component.isMassive();
|
||||||
|
List<RocketComponent> listeners = component.getConfigListeners();
|
||||||
|
if (listeners != null && listeners.size() > 0) {
|
||||||
|
allSameType = component.checkAllClassesEqual(listeners);
|
||||||
|
if (allMassive) { // Only check if <component> is already massive
|
||||||
|
for (RocketComponent listener : listeners) {
|
||||||
|
if (!listener.isMassive()) {
|
||||||
|
allMassive = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//// Component name:
|
//// Component name:
|
||||||
JLabel label = new JLabel(trans.get("RocketCompCfg.lbl.Componentname"));
|
JLabel label = new JLabel(trans.get("RocketCompCfg.lbl.Componentname"));
|
||||||
//// The component name.
|
//// The component name.
|
||||||
label.setToolTipText(trans.get("RocketCompCfg.ttip.Thecomponentname"));
|
label.setToolTipText(trans.get("RocketCompCfg.ttip.Thecomponentname"));
|
||||||
this.add(label, "spanx, height 32!, split");
|
this.add(label, "spanx, height 32!, split");
|
||||||
|
|
||||||
componentNameField = new JTextField(15);
|
componentNameField = new JTextField(15);
|
||||||
textFieldListener = new TextFieldListener();
|
textFieldListener = new TextFieldListener();
|
||||||
componentNameField.addActionListener(textFieldListener);
|
componentNameField.addActionListener(textFieldListener);
|
||||||
@ -89,34 +109,34 @@ public class RocketComponentConfig extends JPanel {
|
|||||||
//// The component name.
|
//// The component name.
|
||||||
componentNameField.setToolTipText(trans.get("RocketCompCfg.ttip.Thecomponentname"));
|
componentNameField.setToolTipText(trans.get("RocketCompCfg.ttip.Thecomponentname"));
|
||||||
this.add(componentNameField, "growx");
|
this.add(componentNameField, "growx");
|
||||||
|
|
||||||
if (component.getPresetType() != null) {
|
if (allSameType && component.getPresetType() != null) {
|
||||||
// If the component supports a preset, show the preset selection box.
|
// If the component supports a preset, show the preset selection box.
|
||||||
presetModel = new PresetModel(this, document, component);
|
presetModel = new PresetModel(this, document, component);
|
||||||
presetComboBox = new JComboBox(presetModel);
|
presetComboBox = new JComboBox(presetModel);
|
||||||
presetComboBox.setEditable(false);
|
presetComboBox.setEditable(false);
|
||||||
this.add(presetComboBox, "");
|
this.add(presetComboBox, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
tabbedPane = new JTabbedPane();
|
tabbedPane = new JTabbedPane();
|
||||||
this.add(tabbedPane, "newline, span, growx, growy 100, wrap");
|
this.add(tabbedPane, "newline, span, growx, growy 100, wrap");
|
||||||
|
|
||||||
//// Override and Mass and CG override options
|
//// Override and Mass and CG override options
|
||||||
tabbedPane.addTab(trans.get("RocketCompCfg.tab.Override"), null, overrideTab(),
|
tabbedPane.addTab(trans.get("RocketCompCfg.tab.Override"), null, overrideTab(),
|
||||||
trans.get("RocketCompCfg.tab.MassandCGoverride"));
|
trans.get("RocketCompCfg.tab.MassandCGoverride"));
|
||||||
if (component.isMassive()) {
|
if (allMassive) {
|
||||||
//// Appearance options
|
//// Appearance options
|
||||||
tabbedPane.addTab(trans.get("RocketCompCfg.tab.Appearance"), null, new AppearancePanel(document, component),
|
appearancePanel = new AppearancePanel(document, component);
|
||||||
|
tabbedPane.addTab(trans.get("RocketCompCfg.tab.Appearance"), null, appearancePanel,
|
||||||
"Appearance Tool Tip");
|
"Appearance Tool Tip");
|
||||||
}
|
}
|
||||||
|
|
||||||
//// Comment and Specify a comment for the component
|
//// Comment and Specify a comment for the component
|
||||||
tabbedPane.addTab(trans.get("RocketCompCfg.tab.Comment"), null, commentTab(),
|
tabbedPane.addTab(trans.get("RocketCompCfg.tab.Comment"), null, commentTab(),
|
||||||
trans.get("RocketCompCfg.tab.Specifyacomment"));
|
trans.get("RocketCompCfg.tab.Specifyacomment"));
|
||||||
|
|
||||||
addButtons();
|
addButtons();
|
||||||
|
|
||||||
updateFields();
|
updateFields();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,6 +148,12 @@ public class RocketComponentConfig extends JPanel {
|
|||||||
|
|
||||||
buttonPanel = new JPanel(new MigLayout("fillx, ins 5"));
|
buttonPanel = new JPanel(new MigLayout("fillx, ins 5"));
|
||||||
|
|
||||||
|
//// Multi-comp edit label
|
||||||
|
multiCompEditLabel = new StyledLabel(" ", -1, Style.BOLD);
|
||||||
|
//multiCompEditLabel.setFontColor(new Color(0, 0, 239));
|
||||||
|
multiCompEditLabel.setFontColor(new Color(170, 0, 100));
|
||||||
|
buttonPanel.add(multiCompEditLabel, "split 2");
|
||||||
|
|
||||||
//// Mass:
|
//// Mass:
|
||||||
infoLabel = new StyledLabel(" ", -1);
|
infoLabel = new StyledLabel(" ", -1);
|
||||||
buttonPanel.add(infoLabel, "growx");
|
buttonPanel.add(infoLabel, "growx");
|
||||||
@ -159,16 +185,17 @@ public class RocketComponentConfig extends JPanel {
|
|||||||
public void updateFields() {
|
public void updateFields() {
|
||||||
// Component name
|
// Component name
|
||||||
componentNameField.setText(component.getName());
|
componentNameField.setText(component.getName());
|
||||||
|
|
||||||
// Info label
|
// Info label
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
if (component.getPresetComponent() != null) {
|
if (allSameType && component.getPresetComponent() != null) {
|
||||||
ComponentPreset preset = component.getPresetComponent();
|
ComponentPreset preset = component.getPresetComponent();
|
||||||
sb.append(preset.getManufacturer() + " " + preset.getPartNo() + " ");
|
sb.append(preset.getManufacturer() + " " + preset.getPartNo() + " ");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (component.isMassive()) {
|
List<RocketComponent> listeners = component.getConfigListeners();
|
||||||
|
if (allMassive && (listeners == null || listeners.size() == 0)) { // TODO: support aggregate mass display for current component and listeners?
|
||||||
sb.append(trans.get("RocketCompCfg.lbl.Componentmass") + " ");
|
sb.append(trans.get("RocketCompCfg.lbl.Componentmass") + " ");
|
||||||
sb.append(UnitGroup.UNITS_MASS.getDefaultUnit().toStringUnit(
|
sb.append(UnitGroup.UNITS_MASS.getDefaultUnit().toStringUnit(
|
||||||
component.getComponentMass()));
|
component.getComponentMass()));
|
||||||
@ -193,8 +220,31 @@ public class RocketComponentConfig extends JPanel {
|
|||||||
} else {
|
} else {
|
||||||
infoLabel.setText("");
|
infoLabel.setText("");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Multi-comp edit label
|
||||||
|
if (listeners != null && listeners.size() > 0) {
|
||||||
|
multiCompEditLabel.setText(trans.get("ComponentCfgDlg.MultiComponentEdit"));
|
||||||
|
|
||||||
|
StringBuilder components = new StringBuilder(trans.get("ComponentCfgDlg.MultiComponentEdit.ttip"));
|
||||||
|
components.append(component.getName()).append(", ");
|
||||||
|
for (int i = 0; i < listeners.size(); i++) {
|
||||||
|
if (i < listeners.size() - 1) {
|
||||||
|
components.append(listeners.get(i).getName()).append(", ");
|
||||||
|
} else {
|
||||||
|
components.append(listeners.get(i).getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
multiCompEditLabel.setToolTipText(components.toString());
|
||||||
|
} else {
|
||||||
|
multiCompEditLabel.setText("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearConfigListeners() {
|
||||||
|
if (appearancePanel != null) {
|
||||||
|
appearancePanel.clearConfigListeners();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected JPanel materialPanel(Material.Type type) {
|
protected JPanel materialPanel(Material.Type type) {
|
||||||
////Component material: and Component finish:
|
////Component material: and Component finish:
|
||||||
@ -269,6 +319,10 @@ public class RocketComponentConfig extends JPanel {
|
|||||||
return subPanel;
|
return subPanel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getSelectedTabIndex() {
|
||||||
|
return tabbedPane.getSelectedIndex();
|
||||||
|
}
|
||||||
|
|
||||||
public String getSelectedTabName() {
|
public String getSelectedTabName() {
|
||||||
if (tabbedPane != null) {
|
if (tabbedPane != null) {
|
||||||
return tabbedPane.getTitleAt(tabbedPane.getSelectedIndex());
|
return tabbedPane.getTitleAt(tabbedPane.getSelectedIndex());
|
||||||
@ -277,6 +331,12 @@ public class RocketComponentConfig extends JPanel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setSelectedTabIndex(int index) {
|
||||||
|
if (tabbedPane != null) {
|
||||||
|
tabbedPane.setSelectedIndex(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void setSelectedTab(String tabName) {
|
public void setSelectedTab(String tabName) {
|
||||||
if (tabbedPane != null) {
|
if (tabbedPane != null) {
|
||||||
for (int i = 0; i < tabbedPane.getTabCount(); i++) {
|
for (int i = 0; i < tabbedPane.getTabCount(); i++) {
|
||||||
|
|||||||
@ -338,16 +338,16 @@ public class BasicFrame extends JFrame {
|
|||||||
|
|
||||||
if (!ComponentConfigDialog.isDialogVisible())
|
if (!ComponentConfigDialog.isDialogVisible())
|
||||||
return;
|
return;
|
||||||
|
else
|
||||||
|
ComponentConfigDialog.disposeDialog();
|
||||||
|
|
||||||
RocketComponent c = (RocketComponent) paths[0].getLastPathComponent();
|
RocketComponent c = (RocketComponent) paths[0].getLastPathComponent();
|
||||||
List<RocketComponent> listeners = new ArrayList<>();
|
c.clearConfigListeners();
|
||||||
for (int i = 1; i < paths.length; i++) {
|
for (int i = 1; i < paths.length; i++) {
|
||||||
RocketComponent listener = (RocketComponent) paths[i].getLastPathComponent();
|
RocketComponent listener = (RocketComponent) paths[i].getLastPathComponent();
|
||||||
if (listener.getClass().equals(c.getClass())) {
|
c.addConfigListener(listener);
|
||||||
listeners.add((RocketComponent) paths[i].getLastPathComponent());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ComponentConfigDialog.showDialog(BasicFrame.this,
|
ComponentConfigDialog.showDialog(BasicFrame.this, BasicFrame.this.document, c);
|
||||||
BasicFrame.this.document, c, listeners);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -1332,7 +1332,6 @@ public class BasicFrame extends JFrame {
|
|||||||
*
|
*
|
||||||
* @param worker the OpenFileWorker that loads the file.
|
* @param worker the OpenFileWorker that loads the file.
|
||||||
* @param displayName the file name to display in dialogs.
|
* @param displayName the file name to display in dialogs.
|
||||||
* @param file the File to set the document to (may be null).
|
|
||||||
* @param parent
|
* @param parent
|
||||||
* @param openRocketConfigDialog if true, will open the configuration dialog of the rocket. This is useful for examples.
|
* @param openRocketConfigDialog if true, will open the configuration dialog of the rocket. This is useful for examples.
|
||||||
* @return
|
* @return
|
||||||
|
|||||||
@ -5,7 +5,6 @@ import java.awt.Toolkit;
|
|||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.KeyEvent;
|
import java.awt.event.KeyEvent;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -879,16 +878,17 @@ public class RocketActions {
|
|||||||
List<RocketComponent> components = selectionModel.getSelectedComponents();
|
List<RocketComponent> components = selectionModel.getSelectedComponents();
|
||||||
Simulation[] sims = selectionModel.getSelectedSimulations();
|
Simulation[] sims = selectionModel.getSelectedSimulations();
|
||||||
|
|
||||||
if ((components != null) && (components.size() > 0) && checkAllClassesEqual(components)) {
|
if ((components != null) && (components.size() > 0)) {
|
||||||
// Do nothing if the config dialog is already visible
|
|
||||||
if (ComponentConfigDialog.isDialogVisible())
|
if (ComponentConfigDialog.isDialogVisible())
|
||||||
return;
|
ComponentConfigDialog.disposeDialog();
|
||||||
|
|
||||||
List<RocketComponent> listeners = null;
|
RocketComponent component = components.get(0);
|
||||||
if (components.size() > 1) {
|
if (components.size() > 1) {
|
||||||
listeners = components.subList(1, components.size());
|
for (int i = 1; i < components.size(); i++) {
|
||||||
|
component.addConfigListener(components.get(i));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ComponentConfigDialog.showDialog(parentFrame, document, components.get(0), listeners);
|
ComponentConfigDialog.showDialog(parentFrame, document, component);
|
||||||
} else if (sims != null && sims.length > 0 && (simulationPanel != null)) {
|
} else if (sims != null && sims.length > 0 && (simulationPanel != null)) {
|
||||||
simulationPanel.editSimulation();
|
simulationPanel.editSimulation();
|
||||||
}
|
}
|
||||||
@ -898,25 +898,7 @@ public class RocketActions {
|
|||||||
public void clipboardChanged() {
|
public void clipboardChanged() {
|
||||||
List<RocketComponent> components = selectionModel.getSelectedComponents();
|
List<RocketComponent> components = selectionModel.getSelectedComponents();
|
||||||
|
|
||||||
this.setEnabled(checkAllClassesEqual(components) || isSimulationSelected());
|
this.setEnabled((components != null && components.size() > 0) || isSimulationSelected());
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks whether all components in the list have the same class
|
|
||||||
* @param components list to check
|
|
||||||
* @return true if all components are of the same class, false if not
|
|
||||||
*/
|
|
||||||
private boolean checkAllClassesEqual(List<RocketComponent> components) {
|
|
||||||
if (components == null || components.size() == 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Class<? extends RocketComponent> myClass = components.get(0).getClass();
|
|
||||||
for (int i = 1; i < components.size(); i++) {
|
|
||||||
if (!components.get(i).getClass().equals(myClass)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user