/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package Macros;
import com.willwinder.ugs.nbp.lookup.CentralLookup;
import com.willwinder.universalgcodesender.listeners.UGSEventListener;
import com.willwinder.universalgcodesender.model.BackendAPI;
import com.willwinder.universalgcodesender.model.UGSEvent;
import com.willwinder.universalgcodesender.types.Macro;
import com.willwinder.universalgcodesender.utils.Settings;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.CharBuffer;
import java.util.Arrays;
import javax.swing.JButton;
import javax.swing.JOptionPane;
import javax.swing.table.DefaultTableModel;
import org.netbeans.api.settings.ConvertAsProperties;
import org.openide.awt.ActionID;
import org.openide.awt.ActionReference;
import org.openide.util.Exceptions;
import org.openide.windows.TopComponent;
import org.openide.util.NbBundle.Messages;
/**
* Top component which displays something.
*/
@ConvertAsProperties(
dtd = "-//Macros//MacroWindow//EN",
autostore = false
)
@TopComponent.Description(
preferredID = "MacroWindowTopComponent",
//iconBase="SET/PATH/TO/ICON/HERE",
persistenceType = TopComponent.PERSISTENCE_ALWAYS
)
@TopComponent.Registration(mode = "visualizer", openAtStartup = false)
@ActionID(category = "Window", id = "Macros.MacroWindowTopComponent")
@ActionReference(path = "Menu/Window" /*, position = 333 */)
@TopComponent.OpenActionRegistration(
displayName = "#CTL_MacroWindowAction",
preferredID = "MacroWindowTopComponent"
)
@Messages({
"CTL_MacroWindowAction=Macros",
"CTL_MacroWindowTopComponent=MacroWindow Window",
"HINT_MacroWindowTopComponent=This is a MacroWindow window"
})
public final class MacroWindowTopComponent extends TopComponent implements UGSEventListener{
// This is used in most functions, so cache it here.
DefaultTableModel model;
private int editRow = -1;
private final BackendAPI backend;
private boolean isSending;
private static final String SEPARATOR = "|";
private static final String UGS_MACROFILENAMe = "ugsMacros.txt";
private Settings settings;
public MacroWindowTopComponent() {
initComponents();
setName(Bundle.CTL_MacroWindowTopComponent());
setToolTipText(Bundle.HINT_MacroWindowTopComponent());
this.macroPanel.setLayout(new GridLayout(6,4, 20, 20));
settings = CentralLookup.getDefault().lookup(Settings.class);
backend = CentralLookup.getDefault().lookup(BackendAPI.class);
backend.addUGSEventListener(this);
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
tabbedPanel = new javax.swing.JTabbedPane();
macroPanel = new javax.swing.JPanel();
settingsPanel = new javax.swing.JPanel();
editPanel = new javax.swing.JPanel();
titleLabel = new javax.swing.JLabel();
titleTextField = new javax.swing.JTextField();
gcodeLabel = new javax.swing.JLabel();
gcodeTextField = new javax.swing.JTextField();
newMacroButton = new javax.swing.JButton();
updateMacroButton = new javax.swing.JButton();
moveUpButton = new javax.swing.JButton();
deleteButton = new javax.swing.JButton();
editButton = new javax.swing.JButton();
moveDownButton = new javax.swing.JButton();
tableScrollPane = new javax.swing.JScrollPane();
macroTable = new javax.swing.JTable();
tabbedPanel.setBackground(new java.awt.Color(238, 238, 238));
macroPanel.setBorder(javax.swing.BorderFactory.createEmptyBorder(10, 10, 10, 10));
javax.swing.GroupLayout macroPanelLayout = new javax.swing.GroupLayout(macroPanel);
macroPanel.setLayout(macroPanelLayout);
macroPanelLayout.setHorizontalGroup(
macroPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 867, Short.MAX_VALUE)
);
macroPanelLayout.setVerticalGroup(
macroPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 504, Short.MAX_VALUE)
);
tabbedPanel.addTab(org.openide.util.NbBundle.getMessage(MacroWindowTopComponent.class, "MacroWindowTopComponent.macroPanel.TabConstraints.tabTitle"), macroPanel); // NOI18N
editPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(MacroWindowTopComponent.class, "MacroWindowTopComponent.editPanel.border.title"))); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(titleLabel, org.openide.util.NbBundle.getMessage(MacroWindowTopComponent.class, "MacroWindowTopComponent.titleLabel.text")); // NOI18N
titleTextField.setText(org.openide.util.NbBundle.getMessage(MacroWindowTopComponent.class, "MacroWindowTopComponent.titleTextField.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(gcodeLabel, org.openide.util.NbBundle.getMessage(MacroWindowTopComponent.class, "MacroWindowTopComponent.gcodeLabel.text")); // NOI18N
gcodeTextField.setText(org.openide.util.NbBundle.getMessage(MacroWindowTopComponent.class, "MacroWindowTopComponent.gcodeTextField.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(newMacroButton, org.openide.util.NbBundle.getMessage(MacroWindowTopComponent.class, "MacroWindowTopComponent.newMacroButton.text")); // NOI18N
newMacroButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
newMacroButtonActionPerformed(evt);
}
});
org.openide.awt.Mnemonics.setLocalizedText(updateMacroButton, org.openide.util.NbBundle.getMessage(MacroWindowTopComponent.class, "MacroWindowTopComponent.updateMacroButton.text")); // NOI18N
updateMacroButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
updateMacroButtonActionPerformed(evt);
}
});
javax.swing.GroupLayout editPanelLayout = new javax.swing.GroupLayout(editPanel);
editPanel.setLayout(editPanelLayout);
editPanelLayout.setHorizontalGroup(
editPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(editPanelLayout.createSequentialGroup()
.addGroup(editPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(gcodeLabel)
.addComponent(titleLabel))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(editPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(titleTextField)
.addComponent(gcodeTextField))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(editPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addComponent(updateMacroButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(newMacroButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addContainerGap())
);
editPanelLayout.setVerticalGroup(
editPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(editPanelLayout.createSequentialGroup()
.addGroup(editPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(titleLabel)
.addComponent(titleTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(newMacroButton))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(editPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(gcodeLabel)
.addComponent(gcodeTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(updateMacroButton))
.addGap(0, 10, Short.MAX_VALUE))
);
moveUpButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/icons/glyphicons-601-chevron-up.png"))); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(moveUpButton, org.openide.util.NbBundle.getMessage(MacroWindowTopComponent.class, "MacroWindowTopComponent.moveUpButton.text")); // NOI18N
moveUpButton.setToolTipText(org.openide.util.NbBundle.getMessage(MacroWindowTopComponent.class, "MacroWindowTopComponent.moveUpButton.toolTipText")); // NOI18N
moveUpButton.setMinimumSize(new java.awt.Dimension(58, 31));
moveUpButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
moveUpButtonActionPerformed(evt);
}
});
deleteButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/icons/glyphicons-208-remove.png"))); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(deleteButton, org.openide.util.NbBundle.getMessage(MacroWindowTopComponent.class, "MacroWindowTopComponent.deleteButton.text")); // NOI18N
deleteButton.setToolTipText(org.openide.util.NbBundle.getMessage(MacroWindowTopComponent.class, "MacroWindowTopComponent.deleteButton.toolTipText")); // NOI18N
deleteButton.setMaximumSize(new java.awt.Dimension(58, 31));
deleteButton.setMinimumSize(new java.awt.Dimension(58, 31));
deleteButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
deleteButtonActionPerformed(evt);
}
});
editButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/icons/glyphicons-151-edit.png"))); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(editButton, org.openide.util.NbBundle.getMessage(MacroWindowTopComponent.class, "MacroWindowTopComponent.editButton.text")); // NOI18N
editButton.setToolTipText(org.openide.util.NbBundle.getMessage(MacroWindowTopComponent.class, "MacroWindowTopComponent.editButton.toolTipText")); // NOI18N
editButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
editButtonActionPerformed(evt);
}
});
moveDownButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/icons/glyphicons-602-chevron-down.png"))); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(moveDownButton, org.openide.util.NbBundle.getMessage(MacroWindowTopComponent.class, "MacroWindowTopComponent.moveDownButton.text")); // NOI18N
moveDownButton.setToolTipText(org.openide.util.NbBundle.getMessage(MacroWindowTopComponent.class, "MacroWindowTopComponent.moveDownButton.toolTipText")); // NOI18N
moveDownButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
moveDownButtonActionPerformed(evt);
}
});
macroTable.setModel(new javax.swing.table.DefaultTableModel(
new Object [][] {
},
new String [] {
"Title", "Gcode"
}
) {
Class[] types = new Class [] {
java.lang.String.class, java.lang.String.class
};
boolean[] canEdit = new boolean [] {
false, false
};
public Class getColumnClass(int columnIndex) {
return types [columnIndex];
}
public boolean isCellEditable(int rowIndex, int columnIndex) {
return canEdit [columnIndex];
}
});
macroTable.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
tableScrollPane.setViewportView(macroTable);
javax.swing.GroupLayout settingsPanelLayout = new javax.swing.GroupLayout(settingsPanel);
settingsPanel.setLayout(settingsPanelLayout);
settingsPanelLayout.setHorizontalGroup(
settingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(editPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(settingsPanelLayout.createSequentialGroup()
.addComponent(tableScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 813, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(settingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
.addComponent(moveUpButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(deleteButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(editButton, javax.swing.GroupLayout.DEFAULT_SIZE, 68, Short.MAX_VALUE)
.addComponent(moveDownButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
);
settingsPanelLayout.setVerticalGroup(
settingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(settingsPanelLayout.createSequentialGroup()
.addComponent(editPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(settingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(settingsPanelLayout.createSequentialGroup()
.addComponent(moveUpButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(deleteButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(editButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(moveDownButton)
.addContainerGap())
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, settingsPanelLayout.createSequentialGroup()
.addGap(0, 0, Short.MAX_VALUE)
.addComponent(tableScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))))
);
tabbedPanel.addTab(org.openide.util.NbBundle.getMessage(MacroWindowTopComponent.class, "MacroWindowTopComponent.settingsPanel.TabConstraints.tabTitle"), settingsPanel); // NOI18N
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(tabbedPanel)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(tabbedPanel)
);
}// </editor-fold>//GEN-END:initComponents
private void moveUpButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_moveUpButtonActionPerformed
// TODO add your handling code here:
int[] selectedRows = this.macroTable.getSelectedRows();
// Exit early if nothing is selected.
if (selectedRows.length == 0) return;
Arrays.sort(selectedRows);
// Exit early if the selected range can't move.
if (selectedRows[0] == 0) return;
for (int i = 0; i < selectedRows.length; i++) {
selectedRows[i] = this.moveRow(selectedRows[i], -1);
}
int first = selectedRows[0];
int last = selectedRows[selectedRows.length-1];
this.macroTable.setRowSelectionInterval(first, last);
updateMacroPanel();
}//GEN-LAST:event_moveUpButtonActionPerformed
private void updateMacroButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_updateMacroButtonActionPerformed
if (!"".equals(this.gcodeTextField.getText()) &&
!"".equals(this.titleTextField.getText())) {
if (this.editRow == -1) {
addRow(this.titleTextField.getText(), this.gcodeTextField.getText());
} else {
model.setValueAt(this.titleTextField.getText(), this.editRow, 0);
model.setValueAt(this.gcodeTextField.getText(), this.editRow, 1);
this.editRow = -1;
}
emptyTextFields();
updateMacroPanel();
}
}//GEN-LAST:event_updateMacroButtonActionPerformed
private void addRow(String title, String gcode) {
model.addRow(new Object[]{
title, gcode,
false
});
}
private void emptyTextFields() {
this.titleTextField.setText("");
this.gcodeTextField.setText("");
}
private void deleteButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deleteButtonActionPerformed
int[] selectedRows = this.macroTable.getSelectedRows();
if (selectedRows.length == 0) return;
Arrays.sort(selectedRows);
for (int i = selectedRows.length - 1; i >= 0; i--) {
int row = selectedRows[i];
this.model.removeRow(row);
this.model.fireTableRowsDeleted(row, row);
}
updateMacroPanel();
}//GEN-LAST:event_deleteButtonActionPerformed
private void moveDownButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_moveDownButtonActionPerformed
int[] selectedRows = this.macroTable.getSelectedRows();
// Exit early if nothing is selected.
if (selectedRows.length == 0) return;
Arrays.sort(selectedRows);
// Exit early if the selected range can't move.
if (selectedRows[selectedRows.length-1] == this.macroTable.getRowCount()) return;
for (int i = selectedRows.length - 1; i >= 0; i--) {
selectedRows[i] = this.moveRow(selectedRows[i], 1);
}
this.macroTable.setRowSelectionInterval(selectedRows[0], selectedRows[selectedRows.length-1]);
updateMacroPanel();
}//GEN-LAST:event_moveDownButtonActionPerformed
private void editButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_editButtonActionPerformed
// TODO add your handling code here:
this.editRow = this.macroTable.getSelectedRow();
if (this.editRow > -1) {
this.titleTextField.setText((String) this.model.getValueAt(this.editRow, 0));
this.gcodeTextField.setText((String) this.model.getValueAt(this.editRow, 1));
}
}//GEN-LAST:event_editButtonActionPerformed
private void newMacroButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_newMacroButtonActionPerformed
emptyTextFields();
this.editRow = -1;
}//GEN-LAST:event_newMacroButtonActionPerformed
private void updateMacroPanel() {
// TODO add your handling code here:
this.macroPanel.removeAll();
String fileContent = "";
int rows = this.model.getRowCount();
int cols = this.model.getColumnCount();
for(int i = 0; i < rows; i++) {
String buttonTitle = (String) this.model.getValueAt(i, 0);
String buttonGcode = (String) this.model.getValueAt(i, 1);
JButton button = new JButton(buttonTitle);
button.setToolTipText(buttonGcode);
button.setEnabled(!isSending && backend.isConnected());
button.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
macroButtonActionPerformed(evt);
}
});
//button.setMinimumSize(new Dimension(30, 30));
this.macroPanel.add(button);
settings.updateMacro(i, buttonTitle, "", buttonGcode);
}
}
private void macroButtonActionPerformed(java.awt.event.ActionEvent evt) {
JButton macroButton = (JButton) evt.getSource();
String gcode = macroButton.getToolTipText();
String[] gCodeCommands = gcode.split(";");
try {
for (int i = 0; i < gCodeCommands.length; i++) {
backend.sendGcodeCommand(gCodeCommands[i]);
}
} catch (Exception ex) {
Exceptions.printStackTrace(ex);
}
}
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton deleteButton;
private javax.swing.JButton editButton;
private javax.swing.JPanel editPanel;
private javax.swing.JLabel gcodeLabel;
private javax.swing.JTextField gcodeTextField;
private javax.swing.JPanel macroPanel;
private javax.swing.JTable macroTable;
private javax.swing.JButton moveDownButton;
private javax.swing.JButton moveUpButton;
private javax.swing.JButton newMacroButton;
private javax.swing.JPanel settingsPanel;
private javax.swing.JTabbedPane tabbedPanel;
private javax.swing.JScrollPane tableScrollPane;
private javax.swing.JLabel titleLabel;
private javax.swing.JTextField titleTextField;
private javax.swing.JButton updateMacroButton;
// End of variables declaration//GEN-END:variables
@Override
public void componentOpened() {
// TODO add custom code on component opening
this.model = (DefaultTableModel)this.macroTable.getModel();
loadSettings();
updateMacroPanel();
}
private void loadSettings() {
int index = settings.getLastMacroIndex();
if (settings.getLastMacroIndex() > -1) {
for (int i = 0; i <= settings.getLastMacroIndex(); i++) {
Macro macro = settings.getMacro(i);
addRow(macro.getName(), macro.getGcode());
}
}
}
@Override
public void componentClosed() {
// TODO add custom code on component closing
}
void writeProperties(java.util.Properties p) {
// better to version settings since initial version as advocated at
// http://wiki.apidesign.org/wiki/PropertyFiles
p.setProperty("version", "1.0");
// TODO store your settings
}
void readProperties(java.util.Properties p) {
String version = p.getProperty("version");
// TODO read your settings according to their version
}
/**
* Move a given row by some offset. If the offset would move the row outside
* of the current table size, the row is not moved.
* @param row row to move.
* @param offset how far to move row.
* @return location of row after move.
*/
private int moveRow(int row, int offset) {
int dest = row + offset;
if (dest < 0 || dest >= model.getRowCount()) {
return row;
}
model.moveRow(row, row, dest);
return dest;
}
@Override
public void UGSEvent(com.willwinder.universalgcodesender.model.UGSEvent ugse) {
if (ugse.isStateChangeEvent()) {
isSending = backend.isSending();
}
updateMacroPanel();
}
}