package org.geogebra.desktop.gui.view.spreadsheet; import java.awt.AWTException; import java.awt.Dimension; import java.awt.Font; import java.awt.Robot; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.FocusEvent; import java.awt.event.FocusListener; import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JTextField; import javax.swing.JToolBar; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import org.geogebra.common.gui.view.spreadsheet.RelativeCopy; import org.geogebra.common.kernel.geos.GeoElement; import org.geogebra.common.kernel.geos.GeoElementSpreadsheet; import org.geogebra.common.main.App; import org.geogebra.common.main.Localization; import org.geogebra.desktop.gui.inputfield.AutoCompleteTextFieldD; import org.geogebra.desktop.gui.inputfield.KeyNavigation; import org.geogebra.desktop.gui.layout.LayoutD; import org.geogebra.desktop.main.AppD; import org.geogebra.desktop.util.GuiResourcesD; public class FormulaBar extends JToolBar implements ActionListener, FocusListener { private static final long serialVersionUID = 1L; private AppD app; private SpreadsheetViewD view; private MyTableD table; private JButton btnCancelFormula; private JButton btnAcceptFormula; private AutoCompleteTextFieldD fldFormula; private AutoCompleteTextFieldD fldCellName; private boolean isIniting; private MyCellEditorSpreadsheet editor; private int row, column; public FormulaBar(AppD app, SpreadsheetViewD view) { this.app = app; this.view = view; this.table = (MyTableD) view.getSpreadsheetTable(); this.editor = table.editor; // create GUI objects btnCancelFormula = new JButton( app.getScaledIcon(GuiResourcesD.DELETE_SMALL)); btnCancelFormula.setFocusable(false); btnCancelFormula.addActionListener(this); btnCancelFormula.setBorder(BorderFactory.createEmptyBorder(0, 4, 0, 4)); btnCancelFormula.addMouseListener(new BarButtonListener()); btnAcceptFormula = new JButton(app.getScaledIcon(GuiResourcesD.APPLY)); btnAcceptFormula.addMouseListener(new BarButtonListener()); btnAcceptFormula.setFocusable(false); btnAcceptFormula.setBorder(BorderFactory.createEmptyBorder(0, 4, 0, 4)); fldFormula = new AutoCompleteTextFieldD(-1, app, KeyNavigation.IGNORE); fldFormula.addActionListener(this); fldFormula.addFocusListener(this); fldFormula.setShowSymbolTableIcon(true); fldCellName = new AutoCompleteTextFieldD(5, app, KeyNavigation.IGNORE); fldCellName.setAutoComplete(false); // fldCellName.setEditable(false); Dimension d = fldCellName.getMaximumSize(); d.width = fldCellName.getPreferredSize().width; fldCellName.setMaximumSize(d); fldCellName.addActionListener(this); add(fldCellName); add(btnCancelFormula); add(btnAcceptFormula); add(fldFormula); setFloatable(false); // add document listener to enable updating of the spreadsheet cell // editot fldFormula.getDocument().addDocumentListener(documentListener); // add an instance of the spreadsheet cell editor listener // to enable auto-update while dragging cell ranges during editing fldFormula.addKeyListener( editor.new SpreadsheetCellEditorKeyListener(true)); // prevent the focus system from stealing TAB; this allows tabbing // through auto-complete cycles fldFormula.setFocusTraversalKeysEnabled(false); setLabels(); } private DocumentListener documentListener = new DocumentListener() { @Override public void changedUpdate(DocumentEvent documentEvent) { // do nothing } @Override public void insertUpdate(DocumentEvent documentEvent) { updateCellEditor(documentEvent); } @Override public void removeUpdate(DocumentEvent documentEvent) { updateCellEditor(documentEvent); } private void updateCellEditor(DocumentEvent documentEvent) { view.getSpreadsheetTable().updateEditor(fldFormula.getText()); } }; public void setEditorText(String text) { if (!fldFormula.hasFocus() || table.isDragging2) { fldFormula.setText(text); } } public void update() { // Application.debug("formula bar update"); if (table.isSelectNone()) { fldCellName.setText(""); fldFormula.setText(""); // Application.debug("nothing selected"); return; } row = table.minSelectionRow; column = table.minSelectionColumn; String cellName = GeoElementSpreadsheet.getSpreadsheetCellName(column, row); fldCellName.removeActionListener(this); fldCellName.setText(cellName); fldCellName.addActionListener(this); String cellContents = ""; GeoElement cellGeo = RelativeCopy.getValue(app, column, row); if (cellGeo != null) { // Application.debug("cell with geo selected at: " + row + " ," + // column); cellContents = cellGeo.getRedefineString(true, false); int index = cellContents.indexOf("="); if ((!cellGeo.isGeoText())) { if (index == -1) { cellContents = "=" + cellContents; } } } else { // Application.debug("empty cell selected at: " + row + " ," + // column); } fldFormula.removeActionListener(this); fldFormula.setText(cellContents); fldFormula.addActionListener(this); } @Override public void focusGained(FocusEvent e) { // make sure the spreadsheet gets the view focus in case first click is // here if (!view.hasViewFocus()) { ((LayoutD) app.getGuiManager().getLayout()).getDockManager() .setFocusedPanel(App.VIEW_SPREADSHEET); } // select the upper left corner cell if nothing is selected if (table.isSelectNone() || table.getSelectedRow() < 0 || table.getSelectedColumn() < 0) { table.setSelection(0, 0); update(); } // start cell editing in the currently selected cell // TODO: should these be an anchor cell? table.setAllowEditing(true); view.getSpreadsheetTable().editCellAt(table.getSelectedRow(), table.getSelectedColumn()); view.getSpreadsheetTable().repaint(); } @Override public void focusLost(FocusEvent arg0) { // TODO Auto-generated method stub } @Override public void actionPerformed(ActionEvent e) { if (isIniting) { return; } Object source = e.getSource(); if (source instanceof JTextField) { doTextFieldActionPerformed((JTextField) source); } } private void doTextFieldActionPerformed(JTextField source) { if (isIniting) { return; } String inputText = source.getText().trim(); if (source == fldCellName) { if (table.setSelection(inputText)) { update(); } } } private class BarButtonListener extends MouseAdapter { @Override public void mouseClicked(MouseEvent event) { Object source = event.getSource(); if (source == btnCancelFormula) { Robot robot; try { robot = new Robot(); robot.keyPress(KeyEvent.VK_ESCAPE); } catch (AWTException e) { e.printStackTrace(); } } else if (source == btnAcceptFormula) { if (fldFormula.hasFocus()) { editor.stopCellEditing(0, 1); } } } } public void updateFonts(Font font) { fldFormula.setFont(font); fldCellName.setFont(font); updateIcons(); repaint(); } public void updateIcons() { btnCancelFormula.setIcon(app.getScaledIcon(GuiResourcesD.DELETE_SMALL)); btnAcceptFormula.setIcon(app.getScaledIcon(GuiResourcesD.APPLY)); } public void setLabels() { Localization loc = app.getLocalization(); btnAcceptFormula.setToolTipText(loc.getPlain("Apply")); btnCancelFormula.setToolTipText(loc.getPlain("Cancel")); } public boolean editorHasFocus() { return fldFormula.hasFocus(); } }