351 lines
11 KiB
Java
351 lines
11 KiB
Java
package dev.bytevibe.hyperpoint;
|
|
|
|
import java.io.IOException;
|
|
import java.net.URL;
|
|
import java.util.ResourceBundle;
|
|
|
|
import javafx.fxml.FXML;
|
|
import javafx.fxml.FXMLLoader;
|
|
import javafx.fxml.Initializable;
|
|
import javafx.scene.control.Button;
|
|
import javafx.scene.control.ColorPicker;
|
|
import javafx.scene.control.ComboBox;
|
|
import javafx.scene.control.Label;
|
|
import javafx.scene.control.Slider;
|
|
import javafx.scene.control.Spinner;
|
|
import javafx.scene.control.TextField;
|
|
import javafx.scene.layout.VBox;
|
|
import javafx.scene.paint.Color;
|
|
|
|
/**
|
|
* 属性编辑面板,用于编辑选中对象的属性
|
|
* 使用FXML加载UI布局
|
|
*/
|
|
public class PropertyPanel extends VBox implements Initializable {
|
|
@FXML
|
|
private Label objectTypeLabel;
|
|
@FXML
|
|
private Label positionLabel;
|
|
@FXML
|
|
private TextField textContentField;
|
|
@FXML
|
|
private ComboBox<String> fontFamilyCombo;
|
|
@FXML
|
|
private Spinner<Double> fontSizeSpinner;
|
|
@FXML
|
|
private ComboBox<String> fontStyleCombo;
|
|
@FXML
|
|
private ColorPicker textColorPicker;
|
|
@FXML
|
|
private ColorPicker fillColorPicker;
|
|
@FXML
|
|
private ColorPicker strokeColorPicker;
|
|
@FXML
|
|
private Spinner<Double> strokeWidthSpinner;
|
|
@FXML
|
|
private Button deleteButton;
|
|
@FXML
|
|
private Slider rotationSlider;
|
|
@FXML
|
|
private Label rotationValueLabel;
|
|
|
|
private DrawingCanvas canvas;
|
|
|
|
public PropertyPanel(DrawingCanvas canvas) {
|
|
this.canvas = canvas;
|
|
loadFXML();
|
|
}
|
|
|
|
/**
|
|
* 加载FXML文件
|
|
*/
|
|
private void loadFXML() {
|
|
try {
|
|
FXMLLoader loader = new FXMLLoader(getClass().getResource("propertyPanel.fxml"));
|
|
loader.setRoot(this);
|
|
loader.setController(this);
|
|
loader.load();
|
|
} catch (IOException e) {
|
|
System.err.println("无法加载propertyPanel.fxml文件");
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void initialize(URL url, ResourceBundle resourceBundle) {
|
|
// 初始化字体列表
|
|
fontFamilyCombo.getItems().addAll(
|
|
"Arial",
|
|
"Times New Roman",
|
|
"Courier New",
|
|
"Verdana",
|
|
"Georgia"
|
|
);
|
|
|
|
// 初始化风格列表
|
|
fontStyleCombo.getItems().addAll(
|
|
"NORMAL",
|
|
"BOLD",
|
|
"ITALIC",
|
|
"BOLD_ITALIC"
|
|
);
|
|
|
|
// 初始化旋转控制
|
|
rotationSlider.setMin(0);
|
|
rotationSlider.setMax(360);
|
|
rotationSlider.setValue(0);
|
|
rotationSlider.setMajorTickUnit(15);
|
|
rotationSlider.setMajorTickUnit(90);
|
|
rotationSlider.setShowTickMarks(true);
|
|
rotationSlider.setShowTickLabels(true);
|
|
|
|
rotationSlider.valueProperty().addListener((obs, oldVal, newVal) -> {
|
|
updateRotation();
|
|
rotationValueLabel.setText(String.format("%.0f°", newVal));
|
|
});
|
|
|
|
// 设置默认值
|
|
fontFamilyCombo.setValue("Arial");
|
|
fontStyleCombo.setValue("NORMAL");
|
|
textColorPicker.setValue(Color.BLACK);
|
|
fillColorPicker.setValue(Color.WHITE);
|
|
strokeColorPicker.setValue(Color.BLACK);
|
|
|
|
// 添加事件监听
|
|
textContentField.setOnKeyReleased(e -> updateTextContent());
|
|
fontFamilyCombo.setOnAction(e -> updateTextStyle());
|
|
fontSizeSpinner.valueProperty().addListener((obs, oldVal, newVal) -> updateTextStyle());
|
|
fontStyleCombo.setOnAction(e -> updateTextStyle());
|
|
textColorPicker.setOnAction(e -> updateTextColor());
|
|
fillColorPicker.setOnAction(e -> updateFillColor());
|
|
strokeColorPicker.setOnAction(e -> updateStrokeColor());
|
|
strokeWidthSpinner.valueProperty().addListener((obs, oldVal, newVal) -> updateStrokeWidth());
|
|
deleteButton.setOnAction(e -> deleteSelectedObject());
|
|
|
|
// 默认隐藏所有编辑控件
|
|
setEditingVisible(false);
|
|
|
|
// 监听canvas的选择变化
|
|
canvas.setOnSelectionChanged(this::updatePropertyPanel);
|
|
}
|
|
|
|
/**
|
|
* 更新属性面板显示
|
|
*/
|
|
private void updatePropertyPanel() {
|
|
DrawableObject selected = canvas.getSelectedObject();
|
|
if (selected == null) {
|
|
setEditingVisible(false);
|
|
rotationSlider.setDisable(true);
|
|
objectTypeLabel.setText("未选中对象");
|
|
return;
|
|
}
|
|
|
|
objectTypeLabel.setText("选中: " + selected.getTypeName());
|
|
positionLabel.setText(String.format("X: %.0f, Y: %.0f", selected.getX(), selected.getY()));
|
|
|
|
// 清除之前的监听
|
|
textContentField.setOnKeyReleased(null);
|
|
|
|
if (selected instanceof TextObject) {
|
|
TextObject textObj = (TextObject) selected;
|
|
textContentField.setText(textObj.getText());
|
|
fontFamilyCombo.setValue(textObj.getFontFamily());
|
|
fontSizeSpinner.getValueFactory().setValue(textObj.getFontSize());
|
|
fontStyleCombo.setValue(textObj.getFontStyle());
|
|
textColorPicker.setValue(Color.web("#" + textObj.getTextColor()));
|
|
|
|
showTextControls();
|
|
} else if (selected instanceof ShapeObject) {
|
|
ShapeObject shapeObj = (ShapeObject) selected;
|
|
fillColorPicker.setValue(Color.web("#" + shapeObj.getFillColor()));
|
|
strokeColorPicker.setValue(Color.web("#" + shapeObj.getStrokeColor()));
|
|
strokeWidthSpinner.getValueFactory().setValue(shapeObj.getStrokeWidth());
|
|
|
|
showShapeControls();
|
|
} else if (selected instanceof ImageObject) {
|
|
showImageControls();
|
|
}
|
|
|
|
rotationSlider.setValue(selected.getRotation());
|
|
rotationSlider.setDisable(false);
|
|
rotationValueLabel.setText(String.format("%.0f°", selected.getRotation()));
|
|
|
|
// 重新添加监听
|
|
textContentField.setOnKeyReleased(e -> updateTextContent());
|
|
}
|
|
|
|
/**
|
|
* 更新旋转
|
|
*/
|
|
private void updateRotation() {
|
|
DrawableObject selected = canvas.getSelectedObject();
|
|
if (selected != null) {
|
|
selected.setRotation(rotationSlider.getValue());
|
|
canvas.redraw();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 显示文本控件
|
|
*/
|
|
private void showTextControls() {
|
|
textContentField.setDisable(false);
|
|
rotationSlider.setDisable(false);
|
|
fontFamilyCombo.setDisable(false);
|
|
fontSizeSpinner.setDisable(false);
|
|
fontStyleCombo.setDisable(false);
|
|
textColorPicker.setDisable(false);
|
|
fillColorPicker.setDisable(true);
|
|
strokeColorPicker.setDisable(true);
|
|
strokeWidthSpinner.setDisable(true);
|
|
|
|
deleteButton.setDisable(false);
|
|
}
|
|
|
|
/**
|
|
* 显示形状控件
|
|
*/
|
|
private void showShapeControls() {
|
|
textContentField.setDisable(true);
|
|
rotationSlider.setDisable(false);
|
|
fontFamilyCombo.setDisable(true);
|
|
fontSizeSpinner.setDisable(true);
|
|
fontStyleCombo.setDisable(true);
|
|
textColorPicker.setDisable(true);
|
|
fillColorPicker.setDisable(false);
|
|
strokeColorPicker.setDisable(false);
|
|
strokeWidthSpinner.setDisable(false);
|
|
|
|
deleteButton.setDisable(false);
|
|
}
|
|
|
|
/**
|
|
* 显示图片控件
|
|
*/
|
|
private void showImageControls() {
|
|
textContentField.setDisable(true);
|
|
rotationSlider.setDisable(false);
|
|
fontFamilyCombo.setDisable(true);
|
|
fontSizeSpinner.setDisable(true);
|
|
fontStyleCombo.setDisable(true);
|
|
textColorPicker.setDisable(true);
|
|
fillColorPicker.setDisable(true);
|
|
strokeColorPicker.setDisable(true);
|
|
strokeWidthSpinner.setDisable(true);
|
|
|
|
deleteButton.setDisable(false);
|
|
}
|
|
|
|
/**
|
|
* 设置编辑控件的可见性
|
|
*/
|
|
private void setEditingVisible(boolean visible) {
|
|
textContentField.setDisable(!visible);
|
|
fontFamilyCombo.setDisable(!visible);
|
|
fontSizeSpinner.setDisable(!visible);
|
|
fontStyleCombo.setDisable(!visible);
|
|
textColorPicker.setDisable(!visible);
|
|
fillColorPicker.setDisable(!visible);
|
|
strokeColorPicker.setDisable(!visible);
|
|
strokeWidthSpinner.setDisable(!visible);
|
|
deleteButton.setDisable(!visible);
|
|
}
|
|
|
|
/**
|
|
* 更新文本内容
|
|
*/
|
|
private void updateTextContent() {
|
|
DrawableObject selected = canvas.getSelectedObject();
|
|
if (selected instanceof TextObject) {
|
|
((TextObject) selected).setText(textContentField.getText());
|
|
canvas.redraw();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 更新文本风格
|
|
*/
|
|
private void updateTextStyle() {
|
|
DrawableObject selected = canvas.getSelectedObject();
|
|
if (selected instanceof TextObject) {
|
|
TextObject textObj = (TextObject) selected;
|
|
textObj.setFontFamily(fontFamilyCombo.getValue());
|
|
textObj.setFontSize(fontSizeSpinner.getValue());
|
|
textObj.setFontStyle(fontStyleCombo.getValue());
|
|
canvas.redraw();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 更新文本颜色
|
|
*/
|
|
private void updateTextColor() {
|
|
DrawableObject selected = canvas.getSelectedObject();
|
|
if (selected instanceof TextObject) {
|
|
Color color = textColorPicker.getValue();
|
|
String hexColor = String.format("%02X%02X%02X",
|
|
(int) (color.getRed() * 255),
|
|
(int) (color.getGreen() * 255),
|
|
(int) (color.getBlue() * 255));
|
|
((TextObject) selected).setTextColor(hexColor);
|
|
canvas.redraw();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 更新填充颜色
|
|
*/
|
|
private void updateFillColor() {
|
|
DrawableObject selected = canvas.getSelectedObject();
|
|
if (selected instanceof ShapeObject) {
|
|
Color color = fillColorPicker.getValue();
|
|
String hexColor = String.format("%02X%02X%02X",
|
|
(int) (color.getRed() * 255),
|
|
(int) (color.getGreen() * 255),
|
|
(int) (color.getBlue() * 255));
|
|
((ShapeObject) selected).setFillColor(hexColor);
|
|
canvas.redraw();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 更新边框颜色
|
|
*/
|
|
private void updateStrokeColor() {
|
|
DrawableObject selected = canvas.getSelectedObject();
|
|
if (selected instanceof ShapeObject) {
|
|
Color color = strokeColorPicker.getValue();
|
|
String hexColor = String.format("%02X%02X%02X",
|
|
(int) (color.getRed() * 255),
|
|
(int) (color.getGreen() * 255),
|
|
(int) (color.getBlue() * 255));
|
|
((ShapeObject) selected).setStrokeColor(hexColor);
|
|
canvas.redraw();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 更新边框宽度
|
|
*/
|
|
private void updateStrokeWidth() {
|
|
DrawableObject selected = canvas.getSelectedObject();
|
|
if (selected instanceof ShapeObject) {
|
|
((ShapeObject) selected).setStrokeWidth(strokeWidthSpinner.getValue());
|
|
canvas.redraw();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 删除选中的对象
|
|
*/
|
|
private void deleteSelectedObject() {
|
|
DrawableObject selected = canvas.getSelectedObject();
|
|
if (selected != null) {
|
|
canvas.removeObject(selected);
|
|
updatePropertyPanel();
|
|
}
|
|
}
|
|
}
|
|
|