/* * Copyright 2013 Sylvain LAURENT * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package ch.sla.jdbcperflogger.console.ui; import java.awt.Component; import java.awt.Cursor; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.beans.Beans; import java.util.TreeSet; import java.util.prefs.BackingStoreException; import java.util.prefs.Preferences; import javax.swing.DefaultComboBoxModel; import javax.swing.DefaultListCellRenderer; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JComboBox; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextField; import javax.swing.JTextPane; import javax.swing.ListSelectionModel; import javax.swing.UIManager; import javax.swing.UIManager.LookAndFeelInfo; import javax.swing.border.TitledBorder; import javax.swing.event.HyperlinkEvent; import javax.swing.event.HyperlinkListener; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import org.eclipse.jdt.annotation.Nullable; @SuppressWarnings("serial") public class WelcomePanel extends JPanel { private final static String WEB_SITE_ADDRESS = "https://github.com/sylvainlaurent/JDBC-Performance-Logger"; private final JTextField txtTargetHost; private final JTextField txtTargetPort; private final JList<HostPort> recentConnectionsList; private final TreeSet<HostPort> recentConnections = new TreeSet<>(); private final Preferences prefs = Preferences.userNodeForPackage(WelcomePanel.class); public WelcomePanel(final IClientConnectionDelegate clientConnectionCreator) { final GridBagLayout gridBagLayout = new GridBagLayout(); gridBagLayout.columnWidths = new int[] { 438, 0 }; gridBagLayout.rowHeights = new int[] { 0, 46, 88, 0, 0 }; gridBagLayout.columnWeights = new double[] { 1.0, Double.MIN_VALUE }; gridBagLayout.rowWeights = new double[] { 0.0, 0.0, 1.0, 1.0, Double.MIN_VALUE }; setLayout(gridBagLayout); final JPanel lookAndFeelPanel = new JPanel(); lookAndFeelPanel .setBorder(new TitledBorder(null, "Look and Feel", TitledBorder.LEADING, TitledBorder.TOP, null, null)); final GridBagConstraints gbc_lookAndFeelPanel = new GridBagConstraints(); gbc_lookAndFeelPanel.insets = new Insets(0, 0, 5, 0); gbc_lookAndFeelPanel.fill = GridBagConstraints.BOTH; gbc_lookAndFeelPanel.gridx = 0; gbc_lookAndFeelPanel.gridy = 0; add(lookAndFeelPanel, gbc_lookAndFeelPanel); final GridBagLayout gbl_lookAndFeelPanel = new GridBagLayout(); gbl_lookAndFeelPanel.columnWidths = new int[] { 263, 0, 0 }; gbl_lookAndFeelPanel.rowHeights = new int[] { 0, 0 }; gbl_lookAndFeelPanel.columnWeights = new double[] { 0.0, 1.0, Double.MIN_VALUE }; gbl_lookAndFeelPanel.rowWeights = new double[] { 0.0, Double.MIN_VALUE }; lookAndFeelPanel.setLayout(gbl_lookAndFeelPanel); final JComboBox<LookAndFeelInfo> lookAndFeelsCombobox = new JComboBox<>(); final GridBagConstraints gbc_lookAndFeelComboBox = new GridBagConstraints(); gbc_lookAndFeelComboBox.fill = GridBagConstraints.HORIZONTAL; gbc_lookAndFeelComboBox.gridx = 0; gbc_lookAndFeelComboBox.gridy = 0; lookAndFeelPanel.add(lookAndFeelsCombobox, gbc_lookAndFeelComboBox); if (!Beans.isDesignTime()) { final LookAndFeelInfo[] lookAndFeels = UIManager.getInstalledLookAndFeels(); final DefaultComboBoxModel<LookAndFeelInfo> lookAndFeelsCboxModel = new DefaultComboBoxModel<>( lookAndFeels); lookAndFeelsCboxModel.insertElementAt(null, 0); lookAndFeelsCombobox.setModel(lookAndFeelsCboxModel); final String initialPreferredLookAndFeel = PerfLoggerGuiMain.getPreferredLookAndFeel(); if (initialPreferredLookAndFeel == null) { lookAndFeelsCombobox.setSelectedIndex(0); } else { for (int i = 0; i < lookAndFeels.length; i++) { if (lookAndFeels[i].getClassName().equals(initialPreferredLookAndFeel)) { lookAndFeelsCombobox.setSelectedIndex(1 + i); break; } } } } lookAndFeelsCombobox.setRenderer(new DefaultListCellRenderer() { @Override public Component getListCellRendererComponent(@Nullable final JList<?> list, @Nullable final Object value, final int index, final boolean isSelected, final boolean cellHasFocus) { if (value == null) { return super.getListCellRendererComponent(list, "(default)", index, isSelected, cellHasFocus); } final LookAndFeelInfo lfInfo = (LookAndFeelInfo) value; return super.getListCellRendererComponent(list, lfInfo.getName(), index, isSelected, cellHasFocus); } }); lookAndFeelsCombobox.addActionListener(new ActionListener() { @Override public void actionPerformed(@Nullable final ActionEvent e) { @Nullable final LookAndFeelInfo selectedLf = (LookAndFeelInfo) lookAndFeelsCombobox.getSelectedItem(); PerfLoggerGuiMain.savePreferredLookAndFeel(selectedLf != null ? selectedLf.getClassName() : null); JOptionPane.showMessageDialog(WelcomePanel.this, "You need to relaunch the application to apply the new look and feel."); } }); final JPanel serverModePanel = new JPanel(); serverModePanel.setBorder(new TitledBorder("Server mode")); final GridBagConstraints gbc_serverModePanel = new GridBagConstraints(); gbc_serverModePanel.anchor = GridBagConstraints.NORTH; gbc_serverModePanel.fill = GridBagConstraints.HORIZONTAL; gbc_serverModePanel.insets = new Insets(0, 0, 5, 0); gbc_serverModePanel.gridx = 0; gbc_serverModePanel.gridy = 1; add(serverModePanel, gbc_serverModePanel); final GridBagLayout gbl_serverModePanel = new GridBagLayout(); gbl_serverModePanel.columnWidths = new int[] { 204, 32, 0 }; gbl_serverModePanel.rowHeights = new int[] { 16, 0 }; gbl_serverModePanel.columnWeights = new double[] { 0.0, 0.0, Double.MIN_VALUE }; gbl_serverModePanel.rowWeights = new double[] { 0.0, Double.MIN_VALUE }; serverModePanel.setLayout(gbl_serverModePanel); final JLabel lblWaitingForConnections = new JLabel("Waiting for connections on port:"); final GridBagConstraints gbc_lblWaitingForConnections = new GridBagConstraints(); gbc_lblWaitingForConnections.anchor = GridBagConstraints.NORTHWEST; gbc_lblWaitingForConnections.insets = new Insets(0, 0, 0, 5); gbc_lblWaitingForConnections.gridx = 0; gbc_lblWaitingForConnections.gridy = 0; serverModePanel.add(lblWaitingForConnections, gbc_lblWaitingForConnections); final JLabel serverPortLabel = new JLabel("4561"); final GridBagConstraints gbc_serverPortLabel = new GridBagConstraints(); gbc_serverPortLabel.anchor = GridBagConstraints.NORTHWEST; gbc_serverPortLabel.gridx = 1; gbc_serverPortLabel.gridy = 0; serverModePanel.add(serverPortLabel, gbc_serverPortLabel); final JPanel clientModePanel = new JPanel(); clientModePanel.setBorder(new TitledBorder("Client mode")); final GridBagConstraints gbc_clientModePanel = new GridBagConstraints(); gbc_clientModePanel.insets = new Insets(0, 0, 5, 0); gbc_clientModePanel.fill = GridBagConstraints.BOTH; gbc_clientModePanel.gridx = 0; gbc_clientModePanel.gridy = 2; add(clientModePanel, gbc_clientModePanel); final GridBagLayout gbl_clientModePanel = new GridBagLayout(); gbl_clientModePanel.columnWidths = new int[] { 30, 74, 292, 0 }; gbl_clientModePanel.rowHeights = new int[] { 28, 30, 51, 0 }; gbl_clientModePanel.columnWeights = new double[] { 0.0, 1.0, 1.0, Double.MIN_VALUE }; gbl_clientModePanel.rowWeights = new double[] { 0.0, 0.0, 1.0, Double.MIN_VALUE }; clientModePanel.setLayout(gbl_clientModePanel); final JButton btnConnect = new JButton("Connect"); btnConnect.addActionListener(new ActionListener() { @Override public void actionPerformed(@Nullable final ActionEvent e) { connect(clientConnectionCreator); } }); final JLabel lblHost = new JLabel("Host"); final GridBagConstraints gbc_lblHost = new GridBagConstraints(); gbc_lblHost.anchor = GridBagConstraints.EAST; gbc_lblHost.insets = new Insets(0, 0, 5, 5); gbc_lblHost.gridx = 0; gbc_lblHost.gridy = 0; clientModePanel.add(lblHost, gbc_lblHost); txtTargetHost = new JTextField(); txtTargetHost.setText("localhost"); txtTargetHost.setColumns(10); final GridBagConstraints gbc_txtTargetHost = new GridBagConstraints(); gbc_txtTargetHost.fill = GridBagConstraints.HORIZONTAL; gbc_txtTargetHost.anchor = GridBagConstraints.NORTH; gbc_txtTargetHost.insets = new Insets(0, 0, 5, 0); gbc_txtTargetHost.gridwidth = 2; gbc_txtTargetHost.gridx = 1; gbc_txtTargetHost.gridy = 0; clientModePanel.add(txtTargetHost, gbc_txtTargetHost); final JLabel lblPort = new JLabel("Port"); final GridBagConstraints gbc_lblPort = new GridBagConstraints(); gbc_lblPort.anchor = GridBagConstraints.EAST; gbc_lblPort.insets = new Insets(0, 0, 5, 5); gbc_lblPort.gridx = 0; gbc_lblPort.gridy = 1; clientModePanel.add(lblPort, gbc_lblPort); txtTargetPort = new JTextField(); txtTargetPort.setText("8889"); txtTargetPort.setColumns(5); final GridBagConstraints gbc_txtTargetPort = new GridBagConstraints(); gbc_txtTargetPort.fill = GridBagConstraints.HORIZONTAL; gbc_txtTargetPort.anchor = GridBagConstraints.NORTH; gbc_txtTargetPort.insets = new Insets(0, 0, 5, 5); gbc_txtTargetPort.gridx = 1; gbc_txtTargetPort.gridy = 1; clientModePanel.add(txtTargetPort, gbc_txtTargetPort); btnConnect.setActionCommand("connect"); final GridBagConstraints gbc_btnConnect = new GridBagConstraints(); gbc_btnConnect.insets = new Insets(0, 0, 5, 0); gbc_btnConnect.anchor = GridBagConstraints.SOUTHWEST; gbc_btnConnect.gridx = 2; gbc_btnConnect.gridy = 1; clientModePanel.add(btnConnect, gbc_btnConnect); final JLabel lblRecentConnections = new JLabel("Recent connections"); final GridBagConstraints gbc_lblRecentConnections = new GridBagConstraints(); gbc_lblRecentConnections.anchor = GridBagConstraints.NORTH; gbc_lblRecentConnections.insets = new Insets(0, 0, 0, 5); gbc_lblRecentConnections.gridx = 0; gbc_lblRecentConnections.gridy = 2; clientModePanel.add(lblRecentConnections, gbc_lblRecentConnections); final JScrollPane recentConnectionsScrollPane = new JScrollPane(); final GridBagConstraints gbc_recentConnectionsScrollPane = new GridBagConstraints(); gbc_recentConnectionsScrollPane.insets = new Insets(0, 0, 5, 0); gbc_recentConnectionsScrollPane.fill = GridBagConstraints.BOTH; gbc_recentConnectionsScrollPane.gridwidth = 2; gbc_recentConnectionsScrollPane.gridx = 1; gbc_recentConnectionsScrollPane.gridy = 2; clientModePanel.add(recentConnectionsScrollPane, gbc_recentConnectionsScrollPane); recentConnectionsList = new JList<>(); recentConnectionsList.addKeyListener(new KeyAdapter() { @Override public void keyTyped(@Nullable final KeyEvent e) { assert e != null; switch (e.getKeyChar()) { case KeyEvent.VK_DELETE: case KeyEvent.VK_BACK_SPACE: final HostPort hostPort = getSelectedRecentConnection(); if (hostPort != null) { removeRecentConnection(hostPort); } } } }); recentConnectionsList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); recentConnectionsList.addListSelectionListener(new ListSelectionListener() { @Override public void valueChanged(@Nullable final ListSelectionEvent e) { assert e != null; if (e.getValueIsAdjusting()) { return; } final HostPort hostPort = getSelectedRecentConnection(); if (hostPort != null) { txtTargetHost.setText(hostPort.getHost()); txtTargetPort.setText(Integer.toString(hostPort.getPort())); } } }); recentConnectionsList.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(@Nullable final MouseEvent e) { assert e != null; if (e.getClickCount() == 2) { connect(clientConnectionCreator); } } }); recentConnectionsScrollPane.setViewportView(recentConnectionsList); final JPanel aboutPanel = new JPanel(); aboutPanel.setBorder(new TitledBorder(null, "About", TitledBorder.LEADING, TitledBorder.TOP, null, null)); final GridBagConstraints gbc_aboutPanel = new GridBagConstraints(); gbc_aboutPanel.fill = GridBagConstraints.BOTH; gbc_aboutPanel.gridx = 0; gbc_aboutPanel.gridy = 3; add(aboutPanel, gbc_aboutPanel); final GridBagLayout gbl_aboutPanel = new GridBagLayout(); gbl_aboutPanel.columnWidths = new int[] { 0, 0, 0 }; gbl_aboutPanel.rowHeights = new int[] { 0, 0 }; gbl_aboutPanel.columnWeights = new double[] { 1.0, 0.0, Double.MIN_VALUE }; gbl_aboutPanel.rowWeights = new double[] { 1.0, Double.MIN_VALUE }; aboutPanel.setLayout(gbl_aboutPanel); final JTextPane aboutTextPane = new JTextPane(); aboutTextPane.setBackground(UIManager.getColor("control")); aboutTextPane.setEditable(false); aboutTextPane.setContentType("text/html"); String txt = "<p>Web site: <a href=\"" + WEB_SITE_ADDRESS + "\">" + WEB_SITE_ADDRESS + "</a></p>"; txt += "<p>Version: " + GuiUtils.getAppVersion() + "</p>"; aboutTextPane.setText(txt); aboutTextPane.addHyperlinkListener(new HyperlinkListener() { @Override public void hyperlinkUpdate(@Nullable final HyperlinkEvent e) { if (e != null && e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { GuiUtils.openWebSite(e.getURL().toString()); } } }); final GridBagConstraints gbc_aboutTextPane = new GridBagConstraints(); gbc_aboutTextPane.insets = new Insets(0, 0, 0, 5); gbc_aboutTextPane.fill = GridBagConstraints.BOTH; gbc_aboutTextPane.gridx = 0; gbc_aboutTextPane.gridy = 0; aboutPanel.add(aboutTextPane, gbc_aboutTextPane); final JLabel lblNewLabel = new JLabel(); lblNewLabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); lblNewLabel.addMouseListener(new MouseAdapter() { @Override public void mouseReleased(@Nullable final MouseEvent e) { GuiUtils.openWebSite(WEB_SITE_ADDRESS); } }); lblNewLabel.setIcon(new ImageIcon(WelcomePanel.class.getResource("/icons/forkme_right_green_007200.png"))); final GridBagConstraints gbc_lblNewLabel = new GridBagConstraints(); gbc_lblNewLabel.anchor = GridBagConstraints.NORTHEAST; gbc_lblNewLabel.gridx = 1; gbc_lblNewLabel.gridy = 0; aboutPanel.add(lblNewLabel, gbc_lblNewLabel); readPrefsForRecentConnections(); } @Nullable private HostPort getSelectedRecentConnection() { final int idx = recentConnectionsList.getSelectedIndex(); if (idx == -1) { return null; } final HostPort hostPort = recentConnectionsList.getModel().getElementAt(idx); return hostPort; } private void connect(final IClientConnectionDelegate clientConnectionCreator) { final String targetHost = txtTargetHost.getText(); if (targetHost != null) { final int port = Integer.parseInt(txtTargetPort.getText()); addConnection(targetHost, port); clientConnectionCreator.createClientConnection(targetHost, port); } } private void addConnection(final String host, final int port) { recentConnections.add(new HostPort(host, port)); recentConnectionsList.setListData(recentConnections.toArray(new HostPort[recentConnections.size()])); prefs.putInt(host, port); try { prefs.sync(); } catch (final BackingStoreException e) { throw new IllegalStateException(e); } } private void removeRecentConnection(final HostPort hostPort) { prefs.remove(hostPort.getHost()); recentConnections.remove(hostPort); recentConnectionsList.setListData(recentConnections.toArray(new HostPort[recentConnections.size()])); } private void readPrefsForRecentConnections() { try { for (final String host : prefs.keys()) { final int port = prefs.getInt(host, -1); if (port != -1) { addConnection(host, port); } } } catch (final BackingStoreException e) { throw new IllegalStateException(e); } } }