package net.sourceforge.fidocadj.dialogs; import net.sourceforge.fidocadj.circuit.CircuitPanel; import net.sourceforge.fidocadj.circuit.controllers.EditorActions; import net.sourceforge.fidocadj.circuit.controllers.ParserActions; import net.sourceforge.fidocadj.circuit.controllers.SelectionActions; import net.sourceforge.fidocadj.circuit.model.DrawingModel; import net.sourceforge.fidocadj.export.ExportGraphic; import net.sourceforge.fidocadj.geom.DrawingSize; import net.sourceforge.fidocadj.geom.MapCoordinates; import net.sourceforge.fidocadj.globals.Globals; import net.sourceforge.fidocadj.globals.LibUtils; import net.sourceforge.fidocadj.layers.LayerDesc; import net.sourceforge.fidocadj.primitives.GraphicPrimitive; import net.sourceforge.fidocadj.primitives.MacroDesc; import net.sourceforge.fidocadj.primitives.PrimitiveMacro; import net.sourceforge.fidocadj.dialogs.mindimdialog.MinimumSizeDialog; import java.awt.*; import java.awt.datatransfer.*; import java.awt.event.*; import java.io.File; import java.io.IOException; import java.io.FileNotFoundException; import java.lang.reflect.Method; import java.util.Date; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Vector; import java.util.prefs.Preferences; import java.util.LinkedList; import javax.swing.*; import javax.swing.border.Border; import javax.swing.event.*; /** Choose file format, size and options of the graphic exporting. <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 2012-2015 Phylum2, Davide Bucci </pre> @author Phylum2, Davide Bucci */ public class DialogSymbolize extends MinimumSizeDialog { final private JPanel parent; private DrawingModel cp; // Swing elements private JComboBox<String> libFilename; private JTextField libName; private JTextField name; private JTextField key; private JComboBox<String> group; private JCheckBox snapToGrid; OriginCircuitPanel cpanel = new OriginCircuitPanel(false); /** Gets the library to be created or modified. @return the given library (string description). */ public String getLibraryName() { String s=libName.getText(); return s.trim(); } /** Gets the name of the macro to be created @return the name */ public String getMacroName() { return name.getText(); } /** Gets the prefix (filename) of the macro to be created @return the filename/prefix */ public String getPrefix() { return libFilename.getEditor().getItem().toString(); } /** Gets the group of the macro to be created @return the name of the group */ public String getGroup() { return group.getEditor().getItem().toString(); } /** List all the libraries available which are not standard in the libFilename combo box. If there are no non standard libraries, suggest a default name. */ private void enumLibs() { libFilename.removeAllItems(); List<String> lst = new LinkedList<String>(); Map<String,MacroDesc> m=cpanel.dmp.getLibrary(); for (Entry<String,MacroDesc> e : m.entrySet()) { MacroDesc md = e.getValue(); // Add only non standard libs. if(!lst.contains(md.filename) && !LibUtils.isStdLib(md)) { libFilename.addItem(md.filename); lst.add(md.filename); } } if (((DefaultComboBoxModel) libFilename.getModel()).getSize() == 0) libFilename.addItem("user_lib"); libFilename.setEditable(true); } /** Create the GUI for the dialog. @return the panel containing the user interface. */ private JPanel createInterfacePanel() { JPanel panel = new JPanel(); GridBagLayout bgl=new GridBagLayout(); GridBagConstraints constraints=new GridBagConstraints(); panel.setLayout(bgl); JLabel libraryLabel=new JLabel(Globals.messages.getString("Library_file")); constraints = DialogUtil.createConst(1,0,1,1,0,0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(6,0,0,0)); panel.add(libraryLabel, constraints); libFilename=new JComboBox<String>(); String e = null; constraints = DialogUtil.createConst(2,0,1,1,100,100, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(6,0,0,0)); panel.add(libFilename, constraints); JLabel libraryNameLabel=new JLabel(Globals.messages.getString("Library_name")); constraints = DialogUtil.createConst(1,1,1,1,0,0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(6,0,0,0)); panel.add(libraryNameLabel, constraints); libName = new JTextField(); constraints = DialogUtil.createConst(2,1,1,1,0,0, GridBagConstraints.EAST, GridBagConstraints.BOTH, new Insets(6,0,0,0)); panel.add(libName, constraints); MouseAdapter ma = new MouseAdapter() { boolean grid = false; /** Mouse click: either show the grid (button 3), or move the origin. */ public void mouseReleased(MouseEvent e) { // Toggle grid visibility, via the secondary mouse button if (e.getButton()==e.BUTTON3) { grid = !grid; cpanel.setGridVisibility(grid); cpanel.repaint(); } else { mouseDragged(e); } } /** Drag the origin of axes using the mouse. */ public void mouseDragged(MouseEvent evt) { int x=evt.getX(); int y=evt.getY(); if(snapToGrid.isSelected()) { cpanel.xl=cpanel.getMapCoordinates().unmapXsnap(x); cpanel.yl=cpanel.getMapCoordinates().unmapYsnap(y); } else { cpanel.xl=cpanel.getMapCoordinates().unmapXnosnap(x); cpanel.yl=cpanel.getMapCoordinates().unmapYnosnap(y); } x=cpanel.getMapCoordinates().mapXi(cpanel.xl,cpanel.yl,false); y=cpanel.getMapCoordinates().mapYi(cpanel.xl,cpanel.yl,false); cpanel.setDx(x); cpanel.setDy(y); cpanel.repaint(); } }; // Make sort that the user can move the origin both by clicking // and by dragging the mouse pointer. cpanel.addMouseListener(ma); cpanel.addMouseMotionListener(ma); // Reasonable size cpanel.setSize(256, 256); cpanel.setPreferredSize(new Dimension(256, 256)); cpanel.add(Box.createVerticalStrut(256)); cpanel.add(Box.createHorizontalStrut(256)); cpanel.dmp.setLayers(cp.getLayers()); cpanel.dmp.setLibrary(cp.getLibrary()); enumLibs(); cpanel.antiAlias = true; cpanel.profileTime = false; MacroDesc macro = buildMacro("temp","temp","temp","temp", "temp", new Point(100,100)); cpanel.setBorder(BorderFactory.createLoweredBevelBorder()); // Set the current objects in the preview panel. cpanel.getParserActions().addString( new StringBuffer(macro.description), false); // Calculate an optimum preview size in order to show all elements. MapCoordinates m = DrawingSize.calculateZoomToFit(cpanel.dmp, cpanel.getSize().width*80/100, cpanel.getSize().height*80/100, true); m.setXCenter(-m.getXCenter()+10); m.setYCenter(-m.getYCenter()+10); cpanel.setMapCoordinates(m); cpanel.resetOrigin(); constraints = DialogUtil.createConst(3,0,8,8,100,100, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(6,6,6,6)); panel.add(cpanel, constraints); JLabel groupLabel=new JLabel(Globals.messages.getString("Group")); // constraints = DialogUtil.createConst(1,3,1,1,0,0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(6,40,0,0)); panel.add(groupLabel, constraints); group=new JComboBox<String>(); listGroups(); if (group.getItemCount()==0) group.addItem(Globals.messages.getString("Group").toLowerCase()); group.setEditable(true); libFilename.addItemListener(new ItemListener() { @Override public void itemStateChanged(ItemEvent arg0) { listGroups(); } }); libFilename.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent arg0) { listGroups(); } }); constraints = DialogUtil.createConst(2,3,1,1,100,100, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(6,0,0,0)); panel.add(group, constraints); JLabel nameLabel=new JLabel(Globals.messages.getString("Name")); // constraints = DialogUtil.createConst(1,4,1,1,0,0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(6,40,12,0)); panel.add(nameLabel, constraints); name=new JTextField(); name.setText( Globals.messages.getString("Name").toLowerCase()); constraints = DialogUtil.createConst(2,4,1,1,100,100, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(6,0,12,0)); panel.add(name, constraints); JLabel nameLabel1=new JLabel(Globals.messages.getString("Key")); // constraints = DialogUtil.createConst(1,5,1,1,0,0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(6,40,12,0)); panel.add(nameLabel1, constraints); key=new JTextField(); long t=System.nanoTime(); long h=0; for(int i=0; t>0; ++i) { t>>=i*8; h^=t & 0xFF; } constraints = DialogUtil.createConst(2,5,1,1,100,100, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(6,0,12,0)); panel.add(key, constraints); key.getDocument().addDocumentListener(new DocumentListener() { /** Needed to implement the DocumentListener interface @param e the document event. */ public void insertUpdate(DocumentEvent e) { showValidity(); } /** Needed to implement the DocumentListener interface @param e the document event. */ public void removeUpdate(DocumentEvent e) { showValidity(); } /** Needed to implement the DocumentListener interface @param e the document event. */ public void changedUpdate(DocumentEvent e) { showValidity(); } /** Change the background color of the fiel depending on the validity of the key currently defined. */ public void showValidity() { if(isKeyInvalid()) { key.setBackground(Color.RED.darker()); key.setForeground(Color.WHITE); } else { Color c1=UIManager.getColor("TextField.background"); Color c2=UIManager.getColor("TextField.foreground"); if(c1!=null && c2!=null) { key.setBackground(c1); key.setForeground(c2); } else { key.setBackground(Color.GREEN.darker().darker()); key.setForeground(Color.WHITE); } } } }); while(isKeyInvalid()) { key.setText(String.valueOf(h++)); } snapToGrid=new JCheckBox( Globals.messages.getString("SnapToGridOrigin")); constraints = DialogUtil.createConst(2,6,1,1,0,0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(6,0,0,0)); panel.add(snapToGrid, constraints); // Keep in mind the last edited library and group if (Globals.lastCLib!=null) libFilename.setSelectedItem(Globals.lastCLib); if (Globals.lastCGrp!=null) group.setSelectedItem(Globals.lastCGrp); libFilename.getEditor().selectAll(); return panel; } /** Obtain all the groups in a given library and put them in the group list. */ private void listGroups() { // Obtain all the groups in a given library. List<String> l = LibUtils.enumGroups(cp.getLibrary(), libFilename.getEditor().getItem().toString()); // Update the group list. group.removeAllItems(); for (String s : l) group.addItem(s); libName.setText(LibUtils.getLibName(cp.getLibrary(), libFilename.getEditor().getItem().toString())); } /** Standard constructor. @param circuitPanel the panel containing a complete editor. @param p the model */ public DialogSymbolize (CircuitPanel circuitPanel, DrawingModel p) { super(350,250,(JFrame)null, Globals.messages.getString("SaveSymbol"), true); parent = circuitPanel; addComponentListener(this); // Obtain the current content pane and create the grid layout manager // which will be used for putting the elements of the interface. GridBagLayout bgl=new GridBagLayout(); GridBagConstraints constraints; Container contentPane=getContentPane(); contentPane.setLayout(bgl); constraints = DialogUtil.createConst(2,0,1,1,100,100, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(12,0,0,20)); setCircuit(p); JPanel panel = createInterfacePanel(); JButton ok=new JButton(Globals.messages.getString("Ok_btn")); JButton cancel=new JButton(Globals.messages.getString("Cancel_btn")); constraints.gridx=0; constraints.gridy=1; constraints.gridwidth=4; constraints.gridheight=1; constraints.anchor=GridBagConstraints.EAST; constraints.insets=new Insets(20,20,20,20); contentPane.add(panel, constraints); constraints.gridx=0; constraints.gridy=2; constraints.gridwidth=4; constraints.gridheight=1; constraints.anchor=GridBagConstraints.EAST; constraints.insets=new Insets(20,20,20,20); // Put the OK and Cancel buttons and make them active. Box b=Box.createHorizontalBox(); b.add(Box.createHorizontalGlue()); ok.setPreferredSize(cancel.getPreferredSize()); if (Globals.okCancelWinOrder) { b.add(ok); b.add(Box.createHorizontalStrut(12)); b.add(cancel); } else { b.add(cancel); b.add(Box.createHorizontalStrut(12)); b.add(ok); } // Add the OK/cancel buttons in the correct order contentPane.add(b, constraints); ok.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { // Check if there is a valid key available. We can not continue // without a key! if (isKeyAbsent()) { JOptionPane.showMessageDialog(null, Globals.messages.getString("InvKey"), Globals.messages.getString("Symbolize"), JOptionPane.ERROR_MESSAGE); key.requestFocus(); return; } else if(isKeyDuplicate()) { JOptionPane.showMessageDialog(null, Globals.messages.getString("DupKey"), Globals.messages.getString("Symbolize"), JOptionPane.ERROR_MESSAGE); key.requestFocus(); return; } else if(isKeyContainingInvalidChars()) { JOptionPane.showMessageDialog(null, Globals.messages.getString("SpaceKey"), Globals.messages.getString("Symbolize"), JOptionPane.ERROR_MESSAGE); key.requestFocus(); return; } Point p = new Point(200-cpanel.xl, 200-cpanel.yl); MacroDesc macro = buildMacro(getMacroName().trim(), key.getText().trim(),getLibraryName().trim(), getGroup().trim(), getPrefix().trim(),p); cp.getLibrary().put(macro.key, macro); // add to lib // Save the new symbol in the current libFilename try { LibUtils.save(cp.getLibrary(), LibUtils.getLibPath(getPrefix()).trim(), getLibraryName(), getPrefix()); } catch (FileNotFoundException F) { JOptionPane.showMessageDialog(null, Globals.messages.getString("DirNotFound"), Globals.messages.getString("Symbolize"), JOptionPane.ERROR_MESSAGE); } setVisible(false); ((JFrame)Globals.activeWindow).repaint(); // Update libs updateTreeLib(); Globals.lastCLib = getLibraryName(); Globals.lastCGrp = getGroup(); } }); cancel.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { setVisible(false); } }); // Here is an action in which the dialog is closed AbstractAction cancelAction = new AbstractAction () { public void actionPerformed (ActionEvent e) { setVisible(false); } }; DialogUtil.addCancelEscape (this, cancelAction); pack(); DialogUtil.center(this); getRootPane().setDefaultButton(ok); } /** Check if the current key is duplicate or not. @return true if a duplicate exists in the library. */ private boolean isKeyDuplicate() { return LibUtils.checkKey(cp.getLibrary(), getPrefix().trim(), getPrefix().trim()+"."+key.getText().trim()); } /** Check if the current key is containing invalid characters. @return true the current key is containing invalid chars. */ private boolean isKeyContainingInvalidChars() { // Currently, the only recognized invalid chars are spaces and dots. return key.getText().contains(" ") || key.getText().contains("."); } /** Check if the current key is specified. @return true the current key is not empty */ private boolean isKeyAbsent() { return key.getText().length()<1; } /** Check if the key is valid or not. */ private boolean isKeyInvalid() { return isKeyAbsent() || isKeyContainingInvalidChars() || isKeyDuplicate(); } protected MacroDesc buildMacro(String myname, String mykey, String mylib, String mygrp, String myprefix, Point origin) { StringBuilder ss = new StringBuilder(); SelectionActions sa = new SelectionActions(cp); EditorActions edt=new EditorActions(cp, sa, null); // Check if there is anything selected. if (sa.getFirstSelectedPrimitive() == null) return null; // Move the selected primitives around the origin just // determined and add them to the macro description contained // in ss. DrawingModel ps = new DrawingModel(); try { ps.setLibrary(cp.getLibrary()); ParserActions pa = new ParserActions(ps); for (GraphicPrimitive g : cp.getPrimitiveVector()) { if (g.getSelected()) { pa.addString(new StringBuffer(g.toString(true)), true); } } //sa.setSelectionAll(true); } catch (Exception e){ e.printStackTrace(); } for (GraphicPrimitive psp : ps.getPrimitiveVector()) { if (!psp.getSelected()) continue; psp.movePrimitive(origin.x, origin.y); ss.append(psp.toString(true)); } parent.repaint(); String desc = ss.toString(); MacroDesc md = new MacroDesc(myprefix+"."+mykey, myname, desc, mygrp, mylib, myprefix); return md; } /** Update all the libs shown in the tree. */ protected void updateTreeLib() { // TODO: // This is a tricky code. What if a new menu option is added? // This would be better, but there is something to solve about access. // ((FidoFrame)Globals.activeWindow).loadLibraries(); Container cc; cc = (JFrame)Globals.activeWindow; ((AbstractButton) ((JFrame) cc).getJMenuBar() .getMenu(3).getSubElements()[0].getSubElements()[1]).doClick(); } /** Sets the drawing database on which to work @param p the database */ public void setCircuit(DrawingModel p) { this.cp = p; } }