/*
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License version 3 as published by
the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.cirqwizard.fx.panel;
import javafx.beans.binding.Bindings;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.*;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyCodeCombination;
import javafx.scene.input.KeyCombination;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.VBox;
import javafx.stage.FileChooser;
import org.cirqwizard.fx.Context;
import org.cirqwizard.fx.PCBSize;
import org.cirqwizard.fx.PanelPane;
import org.cirqwizard.fx.ScreenController;
import org.cirqwizard.fx.controls.RealNumberTextFieldTableCell;
import org.cirqwizard.layers.PanelBoard;
import org.cirqwizard.logging.LoggerFactory;
import org.cirqwizard.settings.ApplicationConstants;
import org.cirqwizard.settings.MachineSettings;
import org.cirqwizard.settings.SettingsFactory;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
public class PanelController extends ScreenController implements Initializable
{
private static final KeyCodeCombination KEY_CODE_ZOOM_IN = new KeyCodeCombination(KeyCode.EQUALS, KeyCombination.SHORTCUT_DOWN);
private static final KeyCodeCombination KEY_CODE_ZOOM_OUT = new KeyCodeCombination(KeyCode.MINUS, KeyCombination.SHORTCUT_DOWN);
@FXML private ComboBox<PCBSize> sizeComboBox;
@FXML private ScrollPane scrollPane;
@FXML private PanelPane panelPane;
@FXML TableView<PanelBoard> boardsTable;
@FXML TableColumn<PanelBoard, String> boardFileColumn;
@FXML TableColumn<PanelBoard, Integer> boardXColumn;
@FXML TableColumn<PanelBoard, Integer> boardYColumn;
@FXML TableColumn<PanelBoard, Boolean> boardOutlineColumn;
@FXML private Button removeButton;
@FXML private VBox errorBox;
private CheckBox ignoreErrorCheckBox;
@FXML private Button continueButton;
private PanelValidator validator;
private boolean resetCacheOnChange = true;
@Override
protected String getFxmlName()
{
return "Panel.fxml";
}
@Override
protected String getName()
{
return "Panel";
}
@Override
public void initialize(URL location, ResourceBundle resources)
{
scrollPane.viewportBoundsProperty().addListener((v, oldV, newV) -> zoomToFit(false));
sizeComboBox.getItems().addAll(PCBSize.values());
sizeComboBox.getSelectionModel().selectedItemProperty().addListener((v, oldV, newV) ->
{
panelPane.getPanel().setSize(newV);
if (resetCacheOnChange)
panelPane.getPanel().resetCacheTimestamps();
savePanel();
zoomToFit(true);
});
boardsTable.getSelectionModel().selectedItemProperty().addListener((v, oldV, newV) -> panelPane.selectBoard(newV));
boardFileColumn.setCellValueFactory(new PropertyValueFactory<>("filename"));
boardFileColumn.setEditable(false);
boardFileColumn.setCellFactory(p -> new TextFieldTableCell<PanelBoard, String>()
{
@Override
public void updateItem(String item, boolean empty)
{
super.updateItem(item != null ? item.substring(item.lastIndexOf(File.separatorChar) + 1, item.length()) : null, empty);
setTooltip(item == null ? null : new Tooltip(item));
}
});
boardXColumn.setCellValueFactory(new PropertyValueFactory<>("x"));
boardXColumn.setCellFactory(p -> new RealNumberTextFieldTableCell<>());
boardXColumn.setOnEditCommit(event ->
{
event.getRowValue().setX(event.getNewValue());
panelPane.getPanel().resetCacheTimestamps();
validator.validateBoards();
savePanel();
panelPane.render();
});
boardYColumn.setCellValueFactory(new PropertyValueFactory<>("y"));
boardYColumn.setCellFactory(p -> new RealNumberTextFieldTableCell<>());
boardYColumn.setOnEditCommit(event ->
{
event.getRowValue().setY(event.getNewValue());
panelPane.getPanel().resetCacheTimestamps();
validator.validateBoards();
savePanel();
panelPane.render();
});
boardOutlineColumn.setCellValueFactory(new PropertyValueFactory<>("generateOutline"));
boardOutlineColumn.setCellFactory(p -> new OutlineCheckBoxTableCell(boardsTable, panelPane,
getMainApplication().getContext().getPanelFile(), validator));
panelPane.setBoardDragListener(() ->
{
panelPane.getPanel().resetCacheTimestamps();
panelPane.getPanel().save(getMainApplication().getContext().getPanelFile());
validator.validateBoards();
refreshTable();
});
ignoreErrorCheckBox = new CheckBox("Ignore the errors. I know what I am doing");
continueButton.disableProperty().bind(Bindings.and(Bindings.isNotEmpty(errorBox.getChildren()),
Bindings.not(ignoreErrorCheckBox.selectedProperty())));
removeButton.disableProperty().bind(Bindings.isNull(boardsTable.getSelectionModel().selectedItemProperty()));
}
@Override
public void refresh()
{
resetCacheOnChange = false;
panelPane.setPanel(getMainApplication().getContext().getPanel());
sizeComboBox.getSelectionModel().select(panelPane.getPanel().getSize());
resetCacheOnChange = true;
refreshTable();
zoomToFit(true);
MachineSettings machineSettings = SettingsFactory.getMachineSettings();
if (machineSettings.getReferencePinX().getValue() != null && machineSettings.getReferencePinY().getValue() != null)
{
getMainApplication().getContext().setG54X(machineSettings.getReferencePinX().getValue() -
ApplicationConstants.getRegistrationPinsInset());
getMainApplication().getContext().setG54Y(machineSettings.getReferencePinY().getValue() -
ApplicationConstants.getRegistrationPinsInset());
}
validator = new PanelValidator(panelPane.getPanel(), errorBox, ignoreErrorCheckBox, () ->
{
savePanel();
panelPane.render();
refreshTable();
});
validator.validateBoards();
}
private EventHandler<? super KeyEvent> shortcutHandler = event -> {
if (event.isConsumed())
return;
if (KEY_CODE_ZOOM_IN.match(event))
{
zoomIn();
event.consume();
}
else if (KEY_CODE_ZOOM_OUT.match(event))
{
zoomOut();
event.consume();
}
};
@Override
public EventHandler<? super KeyEvent> getShortcutHandler()
{
return shortcutHandler;
}
private void refreshTable()
{
boardsTable.getItems().clear();
boardsTable.getItems().addAll(panelPane.getPanel().getBoards());
}
public void rotateCw()
{
if (panelPane.getSelectedBoard() != null)
{
panelPane.getSelectedBoard().rotate(true);
panelPane.getPanel().save(getMainApplication().getContext().getPanelFile());
panelPane.render();
validator.validateBoards();
}
}
public void rotateCcw()
{
if (panelPane.getSelectedBoard() != null)
{
panelPane.getSelectedBoard().rotate(false);
panelPane.getPanel().save(getMainApplication().getContext().getPanelFile());
panelPane.render();
validator.validateBoards();
}
}
public void zoomIn()
{
panelPane.zoomIn();
}
public void zoomOut()
{
panelPane.zoomOut();
}
public void zoomToFit(boolean force)
{
panelPane.zoomToFit(scrollPane.getViewportBounds().getWidth(), scrollPane.getViewportBounds().getHeight(), force);
}
public void addBoard()
{
try
{
FileChooser chooser = new FileChooser();
FileChooser.ExtensionFilter filter = new FileChooser.ExtensionFilter("Gerber files", "*.sol", "*.cmp");
chooser.getExtensionFilters().add(filter);
File file = chooser.showOpenDialog(null);
String filename = file.getAbsolutePath();
String commonName = filename.substring(0, filename.lastIndexOf('.'));
PanelBoard board = new PanelBoard(commonName, 0, 0);
board.loadBoard();
board.centerInPanel(panelPane.getPanel());
panelPane.getPanel().addBoard(board);
panelPane.getPanel().resetCacheTimestamps();
savePanel();
panelPane.render();
refreshTable();
validator.validateBoards();
}
catch (IOException e)
{
LoggerFactory.logException("Error adding board", e);
}
}
public void removeBoard()
{
panelPane.getPanel().getBoards().remove(boardsTable.getSelectionModel().getSelectedItem());
savePanel();
panelPane.render();
refreshTable();
validator.validateBoards();
}
private void savePanel()
{
Context context = getMainApplication().getContext();
context.getPanel().save(context.getPanelFile());
}
}