/* -*- tab-width: 4 -*- * * Electric(tm) VLSI Design System * * File: MessagesWindow.java * * Copyright (c) 2003 Sun Microsystems and Static Free Software * * Electric(tm) 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. * * Electric(tm) 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 Electric(tm); see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, * Boston, Mass 02111-1307, USA. */ package com.sun.electric.tool.user.ui; import com.sun.electric.Main; import com.sun.electric.database.text.TextUtils; import com.sun.electric.tool.Job; import com.sun.electric.tool.io.FileType; import com.sun.electric.tool.user.ActivityLogger; import com.sun.electric.tool.user.dialogs.EDialog; import com.sun.electric.tool.user.dialogs.OpenFile; import java.awt.BorderLayout; import java.awt.Component; import java.awt.Container; import java.awt.Dimension; import java.awt.Font; import java.awt.Frame; import java.awt.GraphicsEnvironment; import java.awt.GridBagConstraints; import java.awt.Point; import java.awt.Rectangle; import java.awt.Toolkit; import java.awt.datatransfer.Clipboard; import java.awt.datatransfer.ClipboardOwner; import java.awt.datatransfer.StringSelection; import java.awt.datatransfer.Transferable; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.net.URL; import java.io.File; import java.io.PrintWriter; import javax.swing.DefaultListModel; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JInternalFrame; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JMenuItem; import javax.swing.JPopupMenu; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.ListSelectionModel; import javax.swing.SwingUtilities; /** * a console for the Java side of Electric. Used because the standard * Electric console can't handle multiple threads of printing. * An instance of this class should be set as the PrintStream for System.out, * e.g. System.setOut(new PrintStream(new MessagesWindow())); * In such a situation, there should never be a reason to call any of * the methods of this class directly. */ public class MessagesWindow implements MouseListener, ClipboardOwner { private JTextArea info; private Container contentFrame; public Container jf; public MessagesWindow(Dimension maxSize) { Dimension msgSize = new Dimension(maxSize.width/3*2, maxSize.height/100*15); Point msgPos = new Point(150, maxSize.height/100*85); JInternalFrame jInternalFrame = new JInternalFrame("Electric Messages", true, false, true, true); jf = jInternalFrame; contentFrame = jInternalFrame.getContentPane(); jInternalFrame.setFrameIcon(Main.getFrameIcon()); jf.setLocation(msgPos); contentFrame.setLayout(new BorderLayout()); info = new JTextArea(20, 110); info.setLineWrap(false); info.setFont(new Font("Monospaced", 0, 12)); info.addMouseListener(this); JScrollPane scrollPane = new JScrollPane(info, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); scrollPane.setPreferredSize(msgSize); contentFrame.add(scrollPane, BorderLayout.CENTER); ((JInternalFrame)jf).pack(); jf.setVisible(true); Main.desktop.add(jf); appendString(ActivityLogger.getLoggingInformation()); } // public Component getComponent() // { // return jf; // } /** * Method to tell whether the Messages Window is the current window. * @return true if the Messages Window is the current window. */ public boolean isFocusOwner() { return ((JInternalFrame)jf).isSelected(); //return jf.isFocusOwner(); } /** * Method to request focus on the Messages Window. */ public void requestFocus() { if (!Job.isClientThread()) { SwingUtilities.invokeLater(new Runnable() { public void run() { requestFocusUnsafe(); } }); return; } requestFocusUnsafe(); } private void requestFocusUnsafe() { //if (TopLevel.isMDIMode()) //{ ((JInternalFrame)jf).toFront(); try { ((JInternalFrame)jf).setSelected(true); } catch (java.beans.PropertyVetoException e) {} //} else //{ // ((JFrame)jf).toFront(); // jf.requestFocus(); //} } /** * Method to return the bounds of the Messages Window. * @return the bounds of the Messages Window. */ public Rectangle getMessagesLocation() { return jf.getBounds(); } /** * Method to return the number of columns in the Messages Window. * @return the number of columns in the Messages Window. */ public int getMessagesCharWidth() { return info.getColumns(); } /** * Method to adjust the Messages Window so that it attaches to the current Edit Window. */ public void tileWithEdit() { // get the location of the edit window WindowFrame wf = WindowFrame.getCurrentWindowFrame(); if (wf == null) return; Rectangle eb; eb = wf.getInternalFrame().getBounds(); //eb = wf.getFrame().getBounds(); // get the location of the messages window Rectangle mb = this.getMessagesLocation(); // adjust the messages window location and size mb.x = eb.x; mb.width = eb.width; mb.y = eb.y + eb.height; jf.setBounds(mb); } /** * Method to add text to the Messages Window. * @param str the text to add. */ public void appendString(String str) { info.append(str); SwingUtilities.invokeLater(new Runnable() { public void run() { info.setCaretPosition(info.getDocument().getLength()); } }); // info.setCaretPosition(info.getDocument().getLength()); // try // { // Rectangle r = info.modelToView(info.getDocument().getLength()); // info.scrollRectToVisible(r); // } catch (BadLocationException ble) // { // } } public void mouseClicked(MouseEvent e) {} public void mouseEntered(MouseEvent e) {} public void mouseExited(MouseEvent e) {} public void mousePressed(MouseEvent e) { // popup menu event (right click) if (e.isPopupTrigger()) doContext(e); } public void mouseReleased(MouseEvent e) { // popup menu event (right click) if (e.isPopupTrigger()) doContext(e); } public void lostOwnership (Clipboard parClipboard, Transferable parTransferable) {} private void doContext(MouseEvent e) { JPopupMenu menu = new JPopupMenu("Messages Window"); JMenuItem menuItem = new JMenuItem("Cut"); menu.add(menuItem); menuItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { copyText(false, true); } }); menuItem = new JMenuItem("Copy"); menu.add(menuItem); menuItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { copyText(false, false); } }); menuItem = new JMenuItem("Paste"); menu.add(menuItem); menuItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { pasteText(); } }); menu.addSeparator(); menuItem = new JMenuItem("Cut All"); menu.add(menuItem); menuItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { copyText(true, true); } }); menuItem = new JMenuItem("Copy All"); menu.add(menuItem); menuItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { copyText(true, false); } }); if (Job.getDebug()) { menuItem = new JMenuItem("Save All"); menu.add(menuItem); menuItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { saveAll(); } }); } menuItem = new JMenuItem("Clear"); menu.add(menuItem); menuItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { clear(true); } }); menu.show((Component)e.getSource(), e.getX(), e.getY()); } /** * Method to paste text from the clipboard to the Messages Window. */ public void pasteText() { info.paste(); } /** * Method to copy text from the Messages Window. * @param all true to copy ALL text in the Messages Window; false to copy only the selected text. * @param cut true to cut instead of copy (delete after copying). */ public void copyText(boolean all, boolean cut) { if (all) { if (cut) { info.selectAll(); info.cut(); } else { Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); clipboard.setContents(new StringSelection(info.getText()), this); } } else { if (cut) info.cut(); else info.copy(); } } /** * Method to copy text from the Messages Window. */ public void saveAll() { String fileName = OpenFile.chooseOutputFile(FileType.TEXT, null, "Message"); if (fileName == null) return; // cancel URL libURL = TextUtils.makeURLToFile(fileName); File f = new File(libURL.getPath()); try { System.out.println("Saving console messages in '" + fileName + " '"); PrintWriter wr = new PrintWriter(f); wr.print(info.getText()); wr.close(); } catch (Exception e) { e.printStackTrace(); } } /** * Method to erase everything in the Messages Window. * @param all true to delete all text; false to delete only selected text. */ public void clear(boolean all) { if (all) { info.setText(""); } else { info.replaceSelection(""); } } /** * Method to select all text in the Messages Window. */ public void selectAll() { info.selectAll(); } /************************************ MESSAGES WINDOW FONT SETTING ************************************/ /** * Method to interactively select the messages window font. */ public void selectFont() { //if (Main.isMDIMode()) //{ JFrame jf = (JFrame) Main.getCurrentJFrame(); new FontSelectDialog(jf); //} else //{ // new FontSelectDialog(null); //} } private class FontSelectDialog extends EDialog { private static final long serialVersionUID = 1L; private Font initialFont; private String initialFontName; private int initialFontSize; private JLabel sampleText; private JList fontNameList; private JList fontSizeList; public FontSelectDialog(Frame parent) { super(parent, true); setTitle("Set Messages Window Font"); getContentPane().setLayout(new java.awt.GridBagLayout()); // get the current messages window font initialFont = info.getFont(); initialFontName = initialFont.getName(); initialFontSize = initialFont.getSize(); // the title of the font column JLabel fontLabel = new JLabel("Font:"); GridBagConstraints gbc = new GridBagConstraints(); gbc.gridx = 0; gbc.gridy = 0; gbc.anchor = java.awt.GridBagConstraints.WEST; gbc.insets = new java.awt.Insets(4, 4, 4, 4); getContentPane().add(fontLabel, gbc); // the font column GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); String [] fontNames = ge.getAvailableFontFamilyNames(); JScrollPane fontNamePane = new JScrollPane(); DefaultListModel fontNameListModel = new DefaultListModel(); fontNameList = new JList(fontNameListModel); fontNameList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); fontNamePane.setViewportView(fontNameList); int initialIndex = 0; for(int i=0; i<fontNames.length; i++) { if (fontNames[i].equals(initialFontName)) initialIndex = i; fontNameListModel.addElement(fontNames[i]); } fontNameList.setSelectedIndex(initialIndex); fontNameList.ensureIndexIsVisible(initialIndex); fontNameList.addMouseListener(new MouseAdapter() { public void mouseClicked(MouseEvent evt) { updateSampleText(); } }); gbc = new GridBagConstraints(); gbc.gridx = 0; gbc.gridy = 1; gbc.weightx = 1; gbc.weighty = 1; gbc.fill = GridBagConstraints.BOTH; gbc.anchor = java.awt.GridBagConstraints.WEST; gbc.insets = new java.awt.Insets(4, 4, 4, 4); getContentPane().add(fontNamePane, gbc); // the title of the font size column JLabel sizeLabel = new JLabel("Size:"); gbc = new GridBagConstraints(); gbc.gridx = 1; gbc.gridy = 0; gbc.anchor = java.awt.GridBagConstraints.WEST; gbc.insets = new java.awt.Insets(4, 4, 4, 4); getContentPane().add(sizeLabel, gbc); // the font size column JScrollPane fontSizePane = new JScrollPane(); DefaultListModel fontSizeListModel = new DefaultListModel(); fontSizeList = new JList(fontSizeListModel); fontSizeList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); fontSizePane.setViewportView(fontSizeList); fontSizeListModel.addElement("8"); fontSizeListModel.addElement("9"); fontSizeListModel.addElement("10"); fontSizeListModel.addElement("11"); fontSizeListModel.addElement("12"); fontSizeListModel.addElement("14"); fontSizeListModel.addElement("16"); fontSizeListModel.addElement("18"); fontSizeListModel.addElement("20"); fontSizeListModel.addElement("22"); fontSizeListModel.addElement("24"); fontSizeListModel.addElement("28"); fontSizeListModel.addElement("32"); fontSizeListModel.addElement("36"); fontSizeListModel.addElement("40"); fontSizeListModel.addElement("48"); fontSizeListModel.addElement("72"); fontSizeList.setSelectedValue(Integer.toString(initialFontSize), true); fontSizeList.addMouseListener(new MouseAdapter() { public void mouseClicked(MouseEvent evt) { updateSampleText(); } }); gbc = new GridBagConstraints(); gbc.gridx = 1; gbc.gridy = 1; gbc.fill = GridBagConstraints.BOTH; gbc.anchor = java.awt.GridBagConstraints.WEST; gbc.insets = new java.awt.Insets(4, 4, 4, 4); getContentPane().add(fontSizePane, gbc); // the sample text sampleText = new JLabel("The Electric VLSI Design System"); sampleText.setBorder(javax.swing.BorderFactory.createTitledBorder("Sample text")); gbc = new GridBagConstraints(); gbc.gridx = 0; gbc.gridy = 2; gbc.gridwidth = 2; gbc.fill = GridBagConstraints.HORIZONTAL; gbc.anchor = java.awt.GridBagConstraints.WEST; gbc.insets = new java.awt.Insets(4, 4, 4, 4); getContentPane().add(sampleText, gbc); sampleText.setFont(initialFont); // the "OK" button JButton okButton = new JButton("OK"); okButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { OK(); } }); gbc = new GridBagConstraints(); gbc.gridx = 0; gbc.gridy = 3; gbc.anchor = java.awt.GridBagConstraints.WEST; gbc.insets = new java.awt.Insets(4, 4, 4, 4); getContentPane().add(okButton, gbc); // the "Cancel" button JButton cancelButton = new JButton("Cancel"); cancelButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { cancel(); } }); gbc = new GridBagConstraints(); gbc.gridx = 1; gbc.gridy = 3; gbc.anchor = java.awt.GridBagConstraints.WEST; gbc.insets = new java.awt.Insets(4, 4, 4, 4); getContentPane().add(cancelButton, gbc); pack(); addWindowListener(new java.awt.event.WindowAdapter() { public void windowClosing(java.awt.event.WindowEvent evt) { cancel(); } }); setVisible(true); } private void cancel() { dispose(); } private void updateSampleText() { String currentFontName = initialFontName; if (fontNameList.getSelectedIndex() != -1) currentFontName = (String)fontNameList.getSelectedValue(); int currentFontSize = initialFontSize; if (fontSizeList.getSelectedIndex() != -1) currentFontSize = TextUtils.atoi((String)fontSizeList.getSelectedValue()); Font font = new Font(currentFontName, 0, currentFontSize); sampleText.setFont(font); } private void OK() { String currentFontName = initialFontName; if (fontNameList.getSelectedIndex() != -1) currentFontName = (String)fontNameList.getSelectedValue(); int currentFontSize = initialFontSize; if (fontSizeList.getSelectedIndex() != -1) currentFontSize = TextUtils.atoi((String)fontSizeList.getSelectedValue()); if (!currentFontName.equals(initialFontName) || currentFontSize != initialFontSize) { initialFont = new Font(currentFontName, 0, currentFontSize); info.setFont(initialFont); System.out.println("Messages window font is now " + currentFontName + ", size " + currentFontSize); } cancel(); } } }