package net.sourceforge.fidocadj; import javax.swing.*; import javax.swing.event.*; import java.awt.event.*; import java.io.*; import net.sourceforge.fidocadj.globals.*; import net.sourceforge.fidocadj.circuit.controllers.*; import net.sourceforge.fidocadj.circuit.*; import net.sourceforge.fidocadj.dialogs.*; import net.sourceforge.fidocadj.clipboard.*; import net.sourceforge.fidocadj.geom.*; /** MenuTools.java Class creating and handling the main menu of FidoCadJ. It contains the methods to create the menu, as well as an event handling system for menu-related operatixons. <pre> This file is part of FidoCadJ. FidoCadJ is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. FidoCadJ 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 FidoCadJ. If not, @see<a href=http://www.gnu.org/licenses/>http://www.gnu.org/licenses/</a>. Copyright 2015-2017 by Davide Bucci </pre> @author Davide Bucci */ public class MenuTools implements MenuListener { JCheckBoxMenuItem libs; /** Create all the menus and associate to them all the needed listeners. @param al the action listener to associate to the menu elements. @return the menu bar. */ public JMenuBar defineMenuBar(ActionListener al) { // Menu creation JMenuBar menuBar=new JMenuBar(); menuBar.add(defineFileMenu(al)); menuBar.add(defineEditMenu(al)); menuBar.add(defineViewMenu(al)); menuBar.add(defineCircuitMenu(al)); // On a MacOSX system, this menu is associated to preferences menu // in the application menu. We do not need to show it in bar. // This needs the AppleSpecific extensions to be active. JMenu about = defineAboutMenu(al); if(!Globals.weAreOnAMac) menuBar.add(about); return menuBar; } /** The menuSelected method, useful for the MenuListener interface. @param evt the menu event object. */ public void menuSelected(MenuEvent evt) { // does nothing } /** The menuDeselected method, useful for the MenuListener interface. @param evt the menu event object. */ public void menuDeselected(MenuEvent evt) { // does nothing } /** The menuCanceled method, useful for the MenuListener interface. @param evt the menu event object. */ public void menuCanceled(MenuEvent evt) { // does nothing } /** Create the main File menu. @param al the action listener to associate to the menu. @return the menu. */ public JMenu defineFileMenu(ActionListener al) { JMenu fileMenu=new JMenu(Globals.messages.getString("File")); JMenuItem fileNew = new JMenuItem(Globals.messages.getString("New")); fileNew.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, Globals.shortcutKey)); JMenuItem fileOpen = new JMenuItem(Globals.messages.getString("Open")); fileOpen.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, Globals.shortcutKey)); JMenuItem fileSave = new JMenuItem(Globals.messages.getString("Save")); fileSave.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, Globals.shortcutKey)); JMenuItem fileSaveName = new JMenuItem(Globals.messages.getString("SaveName")); fileSaveName.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, Globals.shortcutKey | InputEvent.SHIFT_MASK)); JMenuItem fileSaveNameSplit = new JMenuItem(Globals.messages.getString("Save_split")); JMenuItem fileExport = new JMenuItem(Globals.messages.getString("Export")); fileExport.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_E, Globals.shortcutKey)); JMenuItem filePrint = new JMenuItem(Globals.messages.getString("Print")); filePrint.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_P, Globals.shortcutKey)); JMenuItem fileClose = new JMenuItem(Globals.messages.getString("Close")); fileClose.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_W, Globals.shortcutKey)); JMenuItem options = new JMenuItem(Globals.messages.getString("Circ_opt")); // Add the items in the file menu. fileMenu.add(fileNew); fileMenu.add(fileOpen); fileMenu.add(fileSave); fileMenu.add(fileSaveName); fileMenu.addSeparator(); fileMenu.add(fileSaveNameSplit); fileMenu.addSeparator(); fileMenu.add(fileExport); fileMenu.add(filePrint); fileMenu.addSeparator(); // On a MacOSX system, options is associated to preferences menu // in the application menu. We do not need to show it in File. // This needs the AppleSpecific extensions to be active. if(!Globals.weAreOnAMac) { fileMenu.add(options); fileMenu.addSeparator(); } fileMenu.add(fileClose); // Define all the action listeners fileNew.addActionListener(al); fileOpen.addActionListener(al); fileExport.addActionListener(al); filePrint.addActionListener(al); fileClose.addActionListener(al); fileSave.addActionListener(al); fileSaveName.addActionListener(al); fileSaveNameSplit.addActionListener(al); options.addActionListener(al); return fileMenu; } /** Define the Edit main menu. @param al the action listener to associate to the menu. @return the menu. */ public JMenu defineEditMenu(ActionListener al) { JMenu editMenu = new JMenu(Globals.messages.getString("Edit_menu")); JMenuItem editUndo = new JMenuItem(Globals.messages.getString("Undo")); editUndo.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Z, Globals.shortcutKey)); //editUndo.setEnabled(false); JMenuItem editRedo = new JMenuItem(Globals.messages.getString("Redo")); editRedo.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Z, Globals.shortcutKey | InputEvent.SHIFT_MASK)); //editRedo.setEnabled(false); JMenuItem editCut = new JMenuItem(Globals.messages.getString("Cut")); editCut.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X, Globals.shortcutKey)); JMenuItem editCopy = new JMenuItem(Globals.messages.getString("Copy")); editCopy.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, Globals.shortcutKey)); JMenuItem editCopySplit = new JMenuItem(Globals.messages.getString("Copy_split")); editCopySplit.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_M, Globals.shortcutKey)); JMenuItem editPaste = new JMenuItem(Globals.messages.getString("Paste")); editPaste.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_V, Globals.shortcutKey)); JMenuItem clipboardCircuit = new JMenuItem(Globals.messages.getString("DefineClipboard")); JMenuItem editSelectAll = new JMenuItem(Globals.messages.getString("SelectAll")); editSelectAll.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_A, Globals.shortcutKey)); JMenuItem editDuplicate = new JMenuItem(Globals.messages.getString("Duplicate")); editDuplicate.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_D, Globals.shortcutKey)); JMenuItem editRotate = new JMenuItem(Globals.messages.getString("Rotate")); editRotate.setAccelerator(KeyStroke.getKeyStroke("R")); JMenuItem editMirror = new JMenuItem(Globals.messages.getString("Mirror_E")); editMirror.setAccelerator(KeyStroke.getKeyStroke("S")); editUndo.addActionListener(al); editRedo.addActionListener(al); editCut.addActionListener(al); editCopy.addActionListener(al); editCopySplit.addActionListener(al); editPaste.addActionListener(al); editSelectAll.addActionListener(al); editDuplicate.addActionListener(al); editMirror.addActionListener(al); editRotate.addActionListener(al); clipboardCircuit.addActionListener(al); editMenu.add(editUndo); editMenu.add(editRedo); editMenu.addSeparator(); editMenu.add(editCut); editMenu.add(editCopy); editMenu.add(editCopySplit); editMenu.add(editPaste); editMenu.add(clipboardCircuit); editMenu.add(editDuplicate); editMenu.addSeparator(); editMenu.add(editSelectAll); editMenu.addSeparator(); editMenu.add(editRotate); editMenu.add(editMirror); return editMenu; } /** Define the main View menu. @param al the action listener to associate to the menu. @return the menu. */ public JMenu defineViewMenu(ActionListener al) { JMenu viewMenu=new JMenu(Globals.messages.getString("View")); JMenuItem layerOptions = new JMenuItem(Globals.messages.getString("Layer_opt")); layerOptions.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_L, Globals.shortcutKey)); layerOptions.addActionListener(al); viewMenu.add(layerOptions); JMenuItem attachImage = new JMenuItem(Globals.messages.getString("Attach_image_menu")); attachImage.addActionListener(al); viewMenu.add(attachImage); viewMenu.addSeparator(); libs = new JCheckBoxMenuItem(Globals.messages.getString("Libs")); viewMenu.add(libs); libs.addActionListener(al); return viewMenu; } /** Define the main Circuit menu. @param al the action listener to associate to the menu. @return the menu. */ public JMenu defineCircuitMenu(ActionListener al) { JMenu circuitMenu=new JMenu(Globals.messages.getString("Circuit")); JMenuItem defineCircuit = new JMenuItem(Globals.messages.getString("Define")); defineCircuit.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_G, Globals.shortcutKey)); circuitMenu.add(defineCircuit); JMenuItem updateLibraries = new JMenuItem(Globals.messages.getString("LibraryUpdate")); updateLibraries.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_U, Globals.shortcutKey)); circuitMenu.add(updateLibraries); defineCircuit.addActionListener(al); updateLibraries.addActionListener(al); return circuitMenu; } /** Change the state of the show libs toggle menu item. @param s the state of the item. */ public void setShowLibsState(boolean s) { libs.setState(s); } /** Define the main About menu. @param al the action listener to associate to the menu. @return the menu. */ public JMenu defineAboutMenu(ActionListener al) { JMenu about = new JMenu(Globals.messages.getString("About")); JMenuItem aboutMenu = new JMenuItem(Globals.messages.getString("About_menu")); about.add(aboutMenu); aboutMenu.addActionListener(al); return about; } /** Process the menu events. @param evt the event. @param fff the frame in which the menu is present. @param coordL the coordinate listener to show messages if needed. */ public void processMenuActions(ActionEvent evt, FidoFrame fff, ChangeCoordinatesListener coordL) { ExportTools et = fff.getExportTools(); et.setCoordinateListener(coordL); PrintTools pt = fff.getPrintTools(); CircuitPanel cc = fff.cc; String arg=evt.getActionCommand(); EditorActions edt=cc.getEditorActions(); CopyPasteActions cpa=cc.getCopyPasteActions(); ElementsEdtActions eea = cc.getContinuosMoveActions(); SelectionActions sa = cc.getSelectionActions(); ParserActions pa = cc.getParserActions(); // Edit the FidoCadJ code of the drawing if (arg.equals(Globals.messages.getString("Define"))) { EnterCircuitFrame circuitDialog=new EnterCircuitFrame(fff, cc.getParserActions().getText(!cc.extStrict).toString()); circuitDialog.setVisible(true); pa.parseString(new StringBuffer(circuitDialog.getStringCircuit())); cc.getUndoActions().saveUndoState(); fff.repaint(); } else if (arg.equals(Globals.messages.getString("LibraryUpdate"))) { // Update libraries fff.loadLibraries(); fff.show(); } else if (arg.equals(Globals.messages.getString("Circ_opt"))) { // Options for the current drawing fff.showPrefs(); } else if (arg.equals(Globals.messages.getString("Layer_opt"))) { // Options for the layers DialogLayer layerDialog=new DialogLayer(fff,cc.dmp.getLayers()); layerDialog.setVisible(true); // It is important that we force a complete recalculation of // all details in the drawing, otherwise the buffered setup // will not be responsive to the changes in the layer editing. cc.dmp.setChanged(true); fff.repaint(); } else if(arg.equals(Globals.messages.getString("Libs"))) { fff.showLibs(!fff.areLibsVisible()); libs.setState(fff.areLibsVisible()); } else if (arg.equals(Globals.messages.getString("Print"))) { // Print the current drawing pt.associateToCircuitPanel(cc); pt.printDrawing(fff); } else if (arg.equals(Globals.messages.getString("SaveName"))) { // Save with name fff.getFileTools().saveWithName(false); } else if (arg.equals(Globals.messages.getString("Save_split"))) { // Save with name, split non standard macros fff.getFileTools().saveWithName(true); } else if (arg.equals(Globals.messages.getString("Save"))) { // Save with the current name (if available) fff.getFileTools().save(false); } else if (arg.equals(Globals.messages.getString("New"))) { // New drawing fff.createNewInstance(); } else if (arg.equals(Globals.messages.getString("Undo"))) { // Undo the last action cc.getUndoActions().undo(); fff.repaint(); } else if (arg.equals(Globals.messages.getString("Redo"))) { // Redo the last action cc.getUndoActions().redo(); fff.repaint(); } else if (arg.equals(Globals.messages.getString("About_menu"))) { // Show the about menu DialogAbout d=new DialogAbout(fff); d.setVisible(true); } else if (arg.equals(Globals.messages.getString("Open"))) { // Open a file OpenFile openf=new OpenFile(); openf.setParam(fff); /* The following code would require a thread safe implementation of some of the inner classes (such as CircuitModel), which was indeed not the case... Now, yes! */ SwingUtilities.invokeLater(openf); } else if (arg.equals(Globals.messages.getString("Export"))) { // Export the current drawing et.launchExport(fff, cc, fff.getFileTools().openFileDirectory); } else if (arg.equals(Globals.messages.getString("SelectAll"))) { // Select all elements in the current drawing sa.setSelectionAll(true); // Even if the drawing is not changed, a repaint operation is // needed since all selected elements are rendered in green. fff.repaint(); } else if (arg.equals(Globals.messages.getString("Copy"))) { // Copy all selected elements in the clipboard cpa.copySelected(!cc.extStrict, false); } else if (arg.equals(Globals.messages.getString("Copy_split"))) { // Copy elements, splitting non standard macros cpa.copySelected(!cc.extStrict, true); } else if (arg.equals(Globals.messages.getString("Cut"))) { // Cut all the selected elements cpa.copySelected(!cc.extStrict, false); edt.deleteAllSelected(true); fff.repaint(); } else if (arg.equals(Globals.messages.getString("Mirror_E"))) { // Mirror all the selected elements if(eea.isEnteringMacro()) eea.mirrorMacro(); else edt.mirrorAllSelected(); fff.repaint(); } else if (arg.equals(Globals.messages.getString("Rotate"))) { // 90 degrees rotation of all selected elements if(eea.isEnteringMacro()) eea.rotateMacro(); else edt.rotateAllSelected(); fff.repaint(); } else if (arg.equals(Globals.messages.getString("Duplicate"))) { // Duplicate cpa.copySelected(!cc.extStrict, false); cpa.paste(cc.getMapCoordinates().getXGridStep(), cc.getMapCoordinates().getYGridStep()); fff.repaint(); } else if (arg.equals(Globals.messages.getString("DefineClipboard"))) { // Paste as a new circuit TextTransfer textTransfer = new TextTransfer(); FidoFrame popFrame; if(cc.getUndoActions().getModified()) { popFrame = fff.createNewInstance(); } else { popFrame=fff; } pa.parseString( new StringBuffer(textTransfer.getClipboardContents())); fff.repaint(); } else if (arg.equals(Globals.messages.getString("Paste"))) { // Paste some graphical elements cpa.paste(cc.getMapCoordinates().getXGridStep(), cc.getMapCoordinates().getYGridStep()); fff.repaint(); } else if (arg.equals(Globals.messages.getString("Close"))) { // Close the current window if(!fff.getFileTools().checkIfToBeSaved()) { return; } fff.closeThisFrame(); } else if(arg.equals(Globals.messages.getString("Attach_image_menu"))){ // Show the attach image dialog. ImageAsCanvas ii=fff.cc.getAttachedImage(); DialogAttachImage di = new DialogAttachImage(fff); di.setFilename(ii.getFilename()); di.setCorner(ii.getCornerX(),ii.getCornerY()); di.setResolution(ii.getResolution()); di.setVisible(true); if(di.shouldAttach()) { try{ if(di.getShowImage()) ii.loadImage(di.getFilename()); else ii.removeImage(); ii.setResolution(di.getResolution()); ii.setCorner(di.getCornerX(),di.getCornerY()); } catch (IOException e) { JOptionPane.showMessageDialog(fff, Globals.messages.getString("Can_not_attach_image"), "", JOptionPane.INFORMATION_MESSAGE); } } } } }