Merge pull request #2571 from neilweinstock/freeform-edit

Angle constraints in fin editor
This commit is contained in:
Sibo Van Gool 2024-10-14 17:02:52 +02:00 committed by GitHub
commit 039759079b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 203 additions and 105 deletions

View File

@ -1342,10 +1342,10 @@ FreeformFinSetCfg.lbl.Fincant = Fin cant:
FreeformFinSetCfg.lbl.ttip.Fincant = The angle that the fins are canted with respect to the rocket body.
FreeformFinSetCfg.lbl.FincrossSection = Fin cross section:
FreeformFinSetCfg.lbl.Thickness = Thickness:
FreeformFinSetConfig.lbl.doubleClick1 = Double-click
FreeformFinSetConfig.lbl.doubleClick2 = to edit
FreeformFinSetConfig.lbl.clickDrag = Click+drag: Add and move points
FreeformFinSetConfig.lbl.ctrlClick = Ctrl+click: Delete point
FreeformFinSetConfig.lbl.clickDrag = Click+drag: Add and move points
FreeformFinSetConfig.lbl.shiftClickDrag = Shift+click+drag: Lock angle to previous point
FreeformFinSetConfig.lbl.ctrlShiftClickDrag = Ctrl+shift+click+drag: Lock angle to following point
FreeformFinSetConfig.lbl.scaleFin = Scale Fin
FreeformFinSetConfig.lbl.exportCSV = Export CSV
FreeformFinSetConfig.lbl.deletePoint = Delete point

View File

@ -1033,9 +1033,6 @@ FreeformFinSetCfg.lbl.Posrelativeto = :الموقع بالنسبة إلى
FreeformFinSetCfg.lbl.plus = plus
FreeformFinSetCfg.lbl.FincrossSection = :المقطع العرضي للزعنفة
FreeformFinSetCfg.lbl.Thickness = :السماكة
! doubleClick1 + 2 form the message "Double-click to edit", split approximately at the middle
FreeformFinSetConfig.lbl.doubleClick1 = نقرتين
FreeformFinSetConfig.lbl.doubleClick2 = للتعديل
FreeformFinSetConfig.lbl.clickDrag = أنقر وإسحب: لإضافة وتحريك نقاط
FreeformFinSetConfig.lbl.ctrlClick = مفتاح التحكم مع النقر: لحذف نقطة
FreeformFinSetConfig.lbl.scaleFin = حَجِّمْ الزعنفة

View File

@ -715,9 +715,6 @@ FreeformFinSetCfg.lbl.Posrelativeto = Pozice vzhledem k:
FreeformFinSetCfg.lbl.plus = plus
FreeformFinSetCfg.lbl.FincrossSection = Hrany stabilizátoru:
FreeformFinSetCfg.lbl.Thickness = Tlou\u0161tka:
! doubleClick1 + 2 form the message "Double-click to edit", split approximately at the middle
FreeformFinSetConfig.lbl.doubleClick1 = Dvoj klik
FreeformFinSetConfig.lbl.doubleClick2 = k editaci
FreeformFinSetConfig.lbl.clickDrag = Klik a táhnout: Pridej a presun body
FreeformFinSetConfig.lbl.ctrlClick = Ctrl+klik: Odstran bod
FreeformFinSetConfig.lbl.scaleFin = Merítko stabilizátoru

View File

@ -772,9 +772,6 @@ FreeformFinSetCfg.lbl.Posrelativeto = Position relativ zu:
FreeformFinSetCfg.lbl.plus = plus
FreeformFinSetCfg.lbl.FincrossSection = Querschnitt:
FreeformFinSetCfg.lbl.Thickness = Wandstärke:
! doubleClick1 + 2 form the message "Doppelklick zum Bearbeiten", ungefähr in der Mitte teilen
FreeformFinSetConfig.lbl.doubleClick1 = Doppelklick
FreeformFinSetConfig.lbl.doubleClick2 = zum Bearbeiten
FreeformFinSetConfig.lbl.clickDrag = Klicken+Ziehen: Punkte bewegen und hinzufügen
FreeformFinSetConfig.lbl.ctrlClick = Strg+Klick: Punkt löschen
FreeformFinSetConfig.lbl.scaleFin = Leitwerk skalieren

View File

@ -374,9 +374,6 @@ FreeformFinSetCfg.tab.ttip.General = Propiedades generales
FreeformFinSetConfig.lbl.clickDrag = Click (sobre l\u00ednea)+arrastrar: Agregar punto
FreeformFinSetConfig.lbl.ctrlClick = Control+Click (sobre punto): Eliminar punto
!DobleClic 1 + 2 en el mensaje "Doble-Click para editar", corta aproximadamente por la mitad
FreeformFinSetConfig.lbl.doubleClick1 = Doble Click en la lista
FreeformFinSetConfig.lbl.doubleClick2 = para editar
FreeformFinSetConfig.lbl.scaleFin = Dimensionar
GeneralOptimizationDialog.basicSimulationName = Simulaci\u00f3n b\u00e1sica

View File

@ -365,9 +365,6 @@ FreeformFinSetCfg.tab.ttip.General = Propri\u00E9t\u00E9s g\u00E9n\u00E9rales
FreeformFinSetConfig.lbl.clickDrag = Cliquer+d\u00E9placer: Ajouter et d\u00E9placer des points
FreeformFinSetConfig.lbl.ctrlClick = Ctrl+cliquer: Enlever un point
! doubleClick1 + 2 form the message "Double-click to edit", split approximately at the middle
FreeformFinSetConfig.lbl.doubleClick1 = Double-cliquer
FreeformFinSetConfig.lbl.doubleClick2 = pour modifier
FreeformFinSetConfig.lbl.scaleFin = Redimensionner les ailerons
GeneralOptimizationDialog.basicSimulationName = Simulation simple

View File

@ -774,9 +774,6 @@ FreeformFinSetCfg.lbl.Posrelativeto = Posizione relativa a :
FreeformFinSetCfg.lbl.plus = pi\u00f9
FreeformFinSetCfg.lbl.FincrossSection = Sezione delle pinne
FreeformFinSetCfg.lbl.Thickness = Spessore:
! doubleClick1 + 2 form the message "Double-click to edit", split approximately at the middle
FreeformFinSetConfig.lbl.doubleClick1 = Doppio-click
FreeformFinSetConfig.lbl.doubleClick2 = per modificare
FreeformFinSetConfig.lbl.clickDrag = Click+muovi: aggiunge e muove punti
FreeformFinSetConfig.lbl.ctrlClick = Ctrl+click: rimuove punti
FreeformFinSetConfig.lbl.scaleFin = Scala pinna

View File

@ -804,9 +804,6 @@ FreeformFinSetCfg.lbl.Posrelativeto = \u4F4D\u7F6E\uFF1A
FreeformFinSetCfg.lbl.plus = \u30D7\u30E9\u30B9
FreeformFinSetCfg.lbl.FincrossSection = \u30D5\u30A3\u30F3\u65AD\u9762\u7A4D\uFF1A
FreeformFinSetCfg.lbl.Thickness = \u539A\u3055\uFF1A
! doubleClick1 + 2 form the message "Double-click to edit", split approximately at the middle
FreeformFinSetConfig.lbl.doubleClick1 = \u30C0\u30D6\u30EB\u30AF\u30EA\u30C3\u30AF\u3067
FreeformFinSetConfig.lbl.doubleClick2 = \u7DE8\u96C6
FreeformFinSetConfig.lbl.clickDrag = Click+drag: \u30DD\u30A4\u30F3\u30C8\u306E\u8FFD\u52A0\u3068\u79FB\u52D5
FreeformFinSetConfig.lbl.ctrlClick = Ctrl+click: \u30DD\u30A4\u30F3\u30C8\u306E\u524A\u9664
FreeformFinSetConfig.lbl.scaleFin = Scale Fin

View File

@ -984,9 +984,6 @@ FreeformFinSetCfg.lbl.Posrelativeto = Positie relatief t.o.v.:
FreeformFinSetCfg.lbl.plus = plus
FreeformFinSetCfg.lbl.FincrossSection = Vindoorsnede:
FreeformFinSetCfg.lbl.Thickness = Dikte:
! doubleClick1 + 2 form the message "Double-click to edit", split approximately at the middle
FreeformFinSetConfig.lbl.doubleClick1 = Dubbelklik op
FreeformFinSetConfig.lbl.doubleClick2 = om te bewerken
FreeformFinSetConfig.lbl.clickDrag = Klik+sleep: Punten toevoegen en verplaatsen
FreeformFinSetConfig.lbl.ctrlClick = Ctrl+klik: Verwijder punt
FreeformFinSetConfig.lbl.scaleFin = Schaal vin

View File

@ -719,9 +719,6 @@ ComponentInfo.EngineBlock = <b>Blokada silnika</b> unieruchamia silnik wewn\u01
FreeformFinSetCfg.lbl.plus = plus
FreeformFinSetCfg.lbl.FincrossSection = Przekrój statecznika:
FreeformFinSetCfg.lbl.Thickness = Grubo\u015B\u0107:
! doubleClick1 + 2 form the message "Double-click to edit", split approximately at the middle
FreeformFinSetConfig.lbl.doubleClick1 = Kliknij dwukrotnie
FreeformFinSetConfig.lbl.doubleClick2 = aby edytowa\u0107
FreeformFinSetConfig.lbl.clickDrag = Kliknij i przeci\u0105gnij: Dodaj i przesuwaj punkty
FreeformFinSetConfig.lbl.ctrlClick = Ctrl+klik: Usu\u0144 punkt
FreeformFinSetConfig.lbl.scaleFin = Skaluj statecznik

View File

@ -354,9 +354,6 @@ FreeformFinSetCfg.tab.ttip.General = Propriedades gerais
FreeformFinSetConfig.lbl.clickDrag = Clique+arraste: Adicionar e mover pontos
FreeformFinSetConfig.lbl.ctrlClick = Ctrl+clique em: Remover ponto
# doubleClick1 + 2 form the message "Double-click to edit", split approximately at the middle
FreeformFinSetConfig.lbl.doubleClick1 = Duplo clique
FreeformFinSetConfig.lbl.doubleClick2 = editar
FreeformFinSetConfig.lbl.scaleFin = Escala da aleta
GeneralOptimizationDialog.basicSimulationName = Simula\u00e7\u00e3o b\u00e1sica

View File

@ -1013,9 +1013,6 @@ FreeformFinSetCfg.lbl.Posrelativeto = \u041F\u043E\u043B\u043E\u0436\u0435\u043D
FreeformFinSetCfg.lbl.plus = \u043F\u043B\u044E\u0441
FreeformFinSetCfg.lbl.FincrossSection = \u041F\u0440\u043E\u0444\u0438\u043B\u044C \u0441\u0442\u0430\u0431\u0438\u043B\u0438\u0437\u0430\u0442\u043E\u0440\u0430:
FreeformFinSetCfg.lbl.Thickness = \u0422\u043E\u043B\u0449\u0438\u043D\u0430:
! doubleClick1 + 2 form the message "Double-click to edit", split approximately at the middle
FreeformFinSetConfig.lbl.doubleClick1 = \u0414\u0432\u043E\u0439\u043D\u043E\u0439 \u043A\u043B\u0438\u043A
FreeformFinSetConfig.lbl.doubleClick2 = \u0434\u043B\u044F \u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u044F
FreeformFinSetConfig.lbl.clickDrag = \u041A\u043B\u0438\u043A+\u0442\u0430\u0449\u0438\u0442\u044C: \u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C \u0438 \u0434\u0432\u0438\u0433\u0430\u0442\u044C \u0442\u043E\u0447\u043A\u0438
FreeformFinSetConfig.lbl.ctrlClick = Ctrl+\u043A\u043B\u0438\u043A: \u0423\u0434\u0430\u043B\u0438\u0442\u044C \u0442\u043E\u0447\u043A\u0443
FreeformFinSetConfig.lbl.scaleFin = \u041C\u0430\u0441\u0448\u0442\u0430\u0431 \u0441\u0442\u0430\u0431\u0438\u043B\u0438\u0437\u0430\u0442\u043E\u0440\u0430

View File

@ -1225,8 +1225,6 @@ FreeformFinSetCfg.lbl.Fincant = \u041d\u0430\u0445\u0438\u043b \u043a\u0456\u043
FreeformFinSetCfg.lbl.ttip.Fincant = \u041a\u0443\u0442, \u043f\u0456\u0434 \u044f\u043a\u0438\u043c \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u043d\u0430\u0445\u0438\u043b\u0435\u043d\u043e \u0432\u0456\u0434\u043d\u043e\u0441\u043d\u043e \u043a\u043e\u0440\u043f\u0443\u0441\u0443 \u0440\u0430\u043a\u0435\u0442\u0438.
FreeformFinSetCfg.lbl.FincrossSection = \u041f\u0435\u0440\u0435\u0440\u0456\u0437 \u043a\u0456\u043b\u044c\u043a\u043e\u0441\u0442\u0456:
FreeformFinSetCfg.lbl.Thickness = \u0422\u043e\u0432\u0449\u0438\u043d\u0430:
FreeformFinSetConfig.lbl.doubleClick1 = \u0414\u0432\u0456\u0447\u0456 \u043a\u043b\u0456\u043a\u043d\u0456\u0442\u044c
FreeformFinSetConfig.lbl.doubleClick2 = \u0449\u043e\u0431 \u0440\u0435\u0434\u0430\u0433\u0443\u0432\u0430\u0442\u0438
FreeformFinSetConfig.lbl.clickDrag = \u041a\u043b\u0456\u043a+\u043f\u0435\u0440\u0435\u0442\u044f\u0433\u0443\u0432\u0430\u043d\u043d\u044f: \u0414\u043e\u0434\u0430\u0442\u0438 \u0442\u0430 \u043f\u0435\u0440\u0435\u043c\u0456\u0441\u0442\u0438\u0442\u0438 \u0442\u043e\u0447\u043a\u0438
FreeformFinSetConfig.lbl.ctrlClick = Ctrl+\u043a\u043b\u0456\u043a: \u0412\u0438\u0434\u0430\u043b\u0438\u0442\u0438 \u0442\u043e\u0447\u043a\u0443
FreeformFinSetConfig.lbl.scaleFin = \u041c\u0430\u0441\u0448\u0442\u0430\u0431\u0443\u0432\u0430\u0442\u0438 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c

View File

@ -391,9 +391,6 @@ FreeformFinSetCfg.tab.ttip.General = \u5E38\u89C4\u5C5E\u6027
FreeformFinSetConfig.lbl.clickDrag = \u5355\u51FB+\u62D6\u62FD: \u6DFB\u52A0,\u79FB\u52A8\u70B9
FreeformFinSetConfig.lbl.ctrlClick = Ctrl+\u5355\u51FB: \u5220\u9664\u70B9
! doubleClick1 + 2 form the message "Double-click to edit", split approximately at the middle
FreeformFinSetConfig.lbl.doubleClick1 = \u53CC\u51FB
FreeformFinSetConfig.lbl.doubleClick2 = \u7F16\u8F91
FreeformFinSetConfig.lbl.scaleFin = \u7F29\u653E\u7A33\u5B9A\u7FFC
GeneralOptimizationDialog.basicSimulationName = \u57FA\u672C\u4EFF\u771F

View File

@ -1,10 +1,13 @@
package info.openrocket.swing.gui.configdialog;
import java.awt.Component;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentEvent;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Point2D;
@ -19,6 +22,7 @@ import java.util.ArrayList;
import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.DefaultCellEditor;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JDialog;
@ -31,6 +35,7 @@ import javax.swing.JScrollPane;
import javax.swing.JSpinner;
import javax.swing.JSplitPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.event.ListSelectionEvent;
@ -230,11 +235,40 @@ public class FreeformFinSetConfig extends FinSetConfig {
// Create the table
tableModel = new FinPointTableModel();
table = new JTable(tableModel);
table = new JTable(tableModel) {
@Override
public void changeSelection(int row, int column, boolean toggle, boolean extend) {
super.changeSelection(row, column, toggle, extend);
if (isCellEditable(row, column)) {
editCellAt(row, column);
Component editor = getEditorComponent();
if (editor != null) {
editor.requestFocus();
}
}
}
};
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
for (int i = 0; i < Columns.values().length; i++) {
table.getColumnModel().getColumn(i).setPreferredWidth(Columns.values()[i].getWidth());
}
// Set custom editor for highlighting all text
DefaultCellEditor editor = new DefaultCellEditor(new JTextField()) {
@Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
JTextField textField = (JTextField) super.getTableCellEditorComponent(table, value, isSelected, row, column);
SwingUtilities.invokeLater(textField::selectAll);
return textField;
}
};
// Apply the editor to all columns
for (int i = 0; i < table.getColumnCount(); i++) {
table.getColumnModel().getColumn(i).setCellEditor(editor);
}
table.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
@ -264,6 +298,17 @@ public class FreeformFinSetConfig extends FinSetConfig {
}
});
JScrollPane tablePane = new JScrollPane(table);
// Remove focus from table when interacting on the figure
figurePane.addFocusListener(new FocusAdapter() {
@Override
public void focusGained(FocusEvent e) {
if (table.isEditing()) {
table.getCellEditor().stopCellEditing();
}
table.clearSelection();
}
});
JButton scaleButton = new JButton(trans.get("FreeformFinSetConfig.lbl.scaleFin"));
scaleButton.addActionListener(new ActionListener() {
@ -337,9 +382,10 @@ public class FreeformFinSetConfig extends FinSetConfig {
order.add(table);
// row of text directly below figure
panel.add(new StyledLabel(trans.get("lbl.doubleClick1")+" "+trans.get("FreeformFinSetConfig.lbl.doubleClick2"), -2), "spanx 3");
panel.add(new StyledLabel(trans.get("FreeformFinSetConfig.lbl.clickDrag"), -2), "spanx 3");
panel.add(new StyledLabel(trans.get("FreeformFinSetConfig.lbl.ctrlClick"), -2), "spanx 3, wrap");
panel.add(new StyledLabel(trans.get("FreeformFinSetConfig.lbl.ctrlClick"), -2), "spanx 2");
panel.add(new StyledLabel(trans.get("FreeformFinSetConfig.lbl.clickDrag"), -2), "spanx 2, wrap");
panel.add(new StyledLabel(trans.get("FreeformFinSetConfig.lbl.shiftClickDrag"), -2), "spanx 2");
panel.add(new StyledLabel(trans.get("FreeformFinSetConfig.lbl.ctrlShiftClickDrag"), -2), "spanx 2, wrap");
// row of controls at the bottom of the tab:
panel.add(selector.getAsPanel(), "aligny bottom, gap unrel");
@ -501,6 +547,7 @@ public class FreeformFinSetConfig extends FinSetConfig {
@Override
public void mousePressed(MouseEvent event) {
requestFocusInWindow();
final FreeformFinSet finset = (FreeformFinSet) component;
final int pressIndex = getPoint(event);
@ -534,13 +581,26 @@ public class FreeformFinSetConfig extends FinSetConfig {
@Override
public void mouseDragged(MouseEvent event) {
int mods = event.getModifiersEx();
if (dragIndex < 0 || (mods & (ANY_MASK | MouseEvent.BUTTON1_DOWN_MASK)) != MouseEvent.BUTTON1_DOWN_MASK) {
if (dragIndex < 0) {
super.mouseDragged(event);
return;
}
Point2D.Double point = getCoordinates(event);
final FreeformFinSet finset = (FreeformFinSet) component;
// If shift is held down, apply snapping
if ((mods & MouseEvent.SHIFT_DOWN_MASK) != 0) {
int lockIndex = getLockIndex(mods);
if (lockIndex != -1) {
point = snapPoint(point, finset.getFinPoints()[lockIndex]);
int highlightIndex = getHighlightIndex(lockIndex);
figure.setHighlightIndex(highlightIndex);
}
}
try {
finset.setPoint(dragIndex, point.x, point.y);
} catch (IllegalFinPointException e) {
@ -552,29 +612,65 @@ public class FreeformFinSetConfig extends FinSetConfig {
updateFields();
// if point is within borders of figure _AND_ outside borders of the ScrollPane's view:
final Rectangle dragRectangle = viewport.getViewRect();
final Point canvasPoint = new Point( dragPoint.x + dragRectangle.x, dragPoint.y + dragRectangle.y);
if( (figure.getBorderWidth() < canvasPoint.x) && (canvasPoint.x < (figure.getWidth() - figure.getBorderWidth()))
&& (figure.getBorderHeight() < canvasPoint.y) && (canvasPoint.y < (figure.getHeight() - figure.getBorderHeight())))
{
boolean hitBorder = false;
if(dragPoint.x < figure.getBorderWidth()){
hitBorder = true;
dragRectangle.x += dragPoint.x - figure.getBorderWidth();
} else if(dragPoint.x >(dragRectangle.width -figure.getBorderWidth())) {
hitBorder = true;
dragRectangle.x += dragPoint.x - (dragRectangle.width - figure.getBorderWidth());
}
// Handle scrolling if point is dragged out of view
handleScrolling();
}
if (dragPoint.y<figure.getBorderHeight()) {
hitBorder = true;
dragRectangle.y += dragPoint.y - figure.getBorderHeight();
} else if(dragPoint.y >(dragRectangle.height -figure.getBorderHeight())) {
hitBorder = true;
dragRectangle.y += dragPoint.y - (dragRectangle.height - figure.getBorderHeight());
}
/**
* Get the index of the point that the current point should lock to.
* @param mods The modifiers of the mouse event
* @return The index of the point to lock to, or -1 if no point should be locked to
*/
private int getLockIndex(int mods) {
int length = ((FreeformFinSet) component).getFinPoints().length;
if ((mods & MouseEvent.CTRL_DOWN_MASK) != 0) {
return (dragIndex > 0 && dragIndex < length - 1) ? dragIndex + 1 : -1;
} else {
return (dragIndex < length - 1 && dragIndex > 0) ? dragIndex - 1 : -1;
}
}
private int getHighlightIndex(int lockIndex) {
return (lockIndex == dragIndex + 1) ? dragIndex : lockIndex;
}
private Point2D.Double snapPoint(Point2D.Double point, Coordinate lockPoint) {
Point2D.Double snappedPoint = new Point2D.Double(point.x, point.y);
double diffX = point.x - lockPoint.x;
double diffY = point.y - lockPoint.y;
double distanceX = Math.abs(diffX);
double distanceY = Math.abs(diffY);
// Calculate distance to 45 or 135 degree line
double a = 1;
double b = (Math.signum(diffX) == Math.signum(diffY)) ? -1 : 1;
double c = -(a * lockPoint.x + b * lockPoint.y);
double distanceDiag = Math.abs(a * point.x + b * point.y + c) / Math.sqrt(2);
// Snap to the closest constraint
if (distanceX <= distanceY && distanceX <= distanceDiag) {
// Snap horizontal
snappedPoint.x = lockPoint.x;
} else if (distanceY <= distanceX && distanceY <= distanceDiag) {
// Snap vertical
snappedPoint.y = lockPoint.y;
} else {
// Snap diagonal (45 degrees)
double avgDist = (Math.abs(diffX) + Math.abs(diffY)) / 2;
snappedPoint.x = lockPoint.x + Math.signum(diffX) * avgDist;
snappedPoint.y = lockPoint.y + Math.signum(diffY) * avgDist;
}
return snappedPoint;
}
private void handleScrolling() {
Rectangle dragRectangle = viewport.getViewRect();
Point canvasPoint = new Point(dragPoint.x + dragRectangle.x, dragPoint.y + dragRectangle.y);
if (isPointWithinFigureBounds(canvasPoint)) {
boolean hitBorder = updateScrollPosition(dragRectangle);
if (hitBorder) {
super.setFitting(false);
selector.update();
@ -584,56 +680,47 @@ public class FreeformFinSetConfig extends FinSetConfig {
}
}
@Override
public void componentResized(ComponentEvent e) {
if (fit) {
// if we're fitting the whole figure in the ScrollPane, the parent behavior is fine
super.componentResized(e);
} else if (0 > dragIndex) {
// if we're not _currently_ dragging a point, the parent behavior is fine
super.componentResized(e);
} else {
// currently dragging a point.
// ... and if we drag out-of-bounds, we want to move the viewport to keep up
boolean hitBorder = false;
final Rectangle dragRectangle = viewport.getViewRect();
private boolean isPointWithinFigureBounds(Point point) {
return figure.getBorderWidth() < point.x && point.x < (figure.getWidth() - figure.getBorderWidth())
&& figure.getBorderHeight() < point.y && point.y < (figure.getHeight() - figure.getBorderHeight());
}
if(dragPoint.x<figure.getBorderWidth()){
hitBorder = true;
dragRectangle.x += dragPoint.x - figure.getBorderWidth();
} else if(dragPoint.x >(dragRectangle.width -figure.getBorderWidth())) {
hitBorder = true;
dragRectangle.x += dragPoint.x - (dragRectangle.width - figure.getBorderWidth());
}
private boolean updateScrollPosition(Rectangle dragRectangle) {
boolean hitBorder = false;
if (dragPoint.y<figure.getBorderHeight()) {
hitBorder = true;
dragRectangle.y += dragPoint.y - figure.getBorderHeight();
} else if(dragPoint.y >(dragRectangle.height -figure.getBorderHeight())) {
hitBorder = true;
dragRectangle.y += dragPoint.y - (dragRectangle.height - figure.getBorderHeight());
}
if (hitBorder) {
super.setFitting(false);
selector.update();
figure.scrollRectToVisible(dragRectangle);
revalidate();
}
if (dragPoint.x < figure.getBorderWidth()) {
hitBorder = true;
dragRectangle.x += dragPoint.x - figure.getBorderWidth();
} else if (dragPoint.x > (dragRectangle.width - figure.getBorderWidth())) {
hitBorder = true;
dragRectangle.x += dragPoint.x - (dragRectangle.width - figure.getBorderWidth());
}
if (dragPoint.y < figure.getBorderHeight()) {
hitBorder = true;
dragRectangle.y += dragPoint.y - figure.getBorderHeight();
} else if (dragPoint.y > (dragRectangle.height - figure.getBorderHeight())) {
hitBorder = true;
dragRectangle.y += dragPoint.y - (dragRectangle.height - figure.getBorderHeight());
}
return hitBorder;
}
@Override
public void mouseReleased(MouseEvent event) {
dragIndex = -1;
dragPoint = null;
figure.setHighlightIndex(-1);
figure.updateFigure();
super.mouseReleased(event);
}
@Override
public void mouseClicked(MouseEvent event) {
int mods = event.getModifiersEx();
if(( event.getButton() == MouseEvent.BUTTON1) && (0 < (MouseEvent.CTRL_DOWN_MASK & mods))) {
int mods = event.getModifiersEx();
if ((event.getButton() == MouseEvent.BUTTON1) && (0 < (MouseEvent.CTRL_DOWN_MASK & mods))) {
int clickIndex = getPoint(event);
if ( 0 < clickIndex) {
// if ctrl+click, delete point
@ -646,8 +733,7 @@ public class FreeformFinSetConfig extends FinSetConfig {
return;
}
}
super.mouseClicked(event);
super.mouseClicked(event);
}
private int getPoint(MouseEvent event) {

View File

@ -39,6 +39,7 @@ public class FinPointFigure extends AbstractScaleFigure {
private static final int LINE_WIDTH_FIN_PIXELS = 1;
private static final int LINE_WIDTH_BODY_PIXELS = 2;
private static final int LINE_WIDTH_HIGHLIGHT_PIXELS = 3;
// the size of the boxes around each fin point vertex
private static final int LINE_WIDTH_BOX_PIXELS = 1;
@ -59,6 +60,7 @@ public class FinPointFigure extends AbstractScaleFigure {
private Rectangle2D.Double[] finPointHandles = null;
private int selectedIndex = -1;
private int highlightIndex = -1; // The first index of the segment to highlight when snapping to a fin point
private static Color backgroundColor;
private static Color finPointBodyLineColor;
@ -66,6 +68,7 @@ public class FinPointFigure extends AbstractScaleFigure {
private static Color finPointGridMinorLineColor;
private static Color finPointPointColor;
private static Color finPointSelectedPointColor;
private static Color finPointSnapHighlightColor;
static {
initColors();
@ -92,6 +95,7 @@ public class FinPointFigure extends AbstractScaleFigure {
finPointGridMinorLineColor = GUIUtil.getUITheme().getFinPointGridMinorLineColor();
finPointPointColor = GUIUtil.getUITheme().getFinPointPointColor();
finPointSelectedPointColor = GUIUtil.getUITheme().getFinPointSelectedPointColor();
finPointSnapHighlightColor = GUIUtil.getUITheme().getFinPointSnapHighlightColor();
}
@Override
@ -124,6 +128,7 @@ public class FinPointFigure extends AbstractScaleFigure {
paintRocketBody(g2);
paintFinShape(g2);
paintHighlight(g2);
paintFinHandles(g2);
}
@ -261,6 +266,26 @@ public class FinPointFigure extends AbstractScaleFigure {
g2.setColor(finPointBodyLineColor);
g2.draw(shape);
}
/**
* Paints the highlight line between the two points when snapping to a fin point.
* @param g2 The graphics context to paint to.
*/
private void paintHighlight(final Graphics2D g2) {
final Coordinate[] points = finset.getFinPointsWithRoot();
if (highlightIndex < 0 || highlightIndex > points.length - 1) {
return;
}
Coordinate start = points[highlightIndex];
Coordinate end = points[highlightIndex+1];
final float highlightWidth_m = (float) (LINE_WIDTH_HIGHLIGHT_PIXELS / scale );
g2.setStroke(new BasicStroke(highlightWidth_m));
g2.setColor(finPointSnapHighlightColor);
g2.draw(new Line2D.Double(start.x, start.y, end.x, end.y));
}
private void paintFinHandles(final Graphics2D g2) {
// Excludes fin tab points
@ -438,4 +463,8 @@ public class FinPointFigure extends AbstractScaleFigure {
this.selectedIndex = newIndex;
}
public void setHighlightIndex(final int newIndex) {
this.highlightIndex = newIndex;
}
}

View File

@ -93,6 +93,7 @@ public class UITheme {
Color getFinPointPointColor();
Color getFinPointSelectedPointColor();
Color getFinPointBodyLineColor();
Color getFinPointSnapHighlightColor();
Icon getMassOverrideIcon();
Icon getMassOverrideSubcomponentIcon();
@ -404,6 +405,11 @@ public class UITheme {
return Color.BLACK;
}
@Override
public Color getFinPointSnapHighlightColor() {
return Color.RED;
}
@Override
public Icon getMassOverrideIcon() {
return Icons.MASS_OVERRIDE_LIGHT;
@ -805,6 +811,11 @@ public class UITheme {
return Color.WHITE;
}
@Override
public Color getFinPointSnapHighlightColor() {
return new Color(255, 58, 58, 255);
}
@Override
public Icon getMassOverrideIcon() {
return Icons.MASS_OVERRIDE_DARK;
@ -1206,6 +1217,11 @@ public class UITheme {
return Color.WHITE;
}
@Override
public Color getFinPointSnapHighlightColor() {
return new Color(241, 77, 77, 255);
}
@Override
public Icon getMassOverrideIcon() {
return Icons.MASS_OVERRIDE_DARK;
@ -1626,6 +1642,11 @@ public class UITheme {
return getCurrentTheme().getFinPointBodyLineColor();
}
@Override
public Color getFinPointSnapHighlightColor() {
return getCurrentTheme().getFinPointBodyLineColor();
}
@Override
public Icon getMassOverrideIcon() {
return getCurrentTheme().getMassOverrideIcon();