/* * Copyright 2007 - 2017 the original author or authors. * * 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 net.sf.jailer.ui; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.RenderingHints; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.SortedMap; import java.util.TreeMap; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.swing.DefaultComboBoxModel; import javax.swing.JCheckBox; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import net.sf.jailer.datamodel.Association; import net.sf.jailer.datamodel.Cardinality; import net.sf.jailer.datamodel.DataModel; import net.sf.jailer.datamodel.Table; import net.sf.jailer.util.SqlUtil; /** * Lets user apply an action on a subset of a given {@link Association} set. * * @author Ralf Wisser */ public abstract class AssociationListUI extends javax.swing.JPanel { /** * Types of {@link Association}. */ private enum AssociationType { CHILD("1Child", GREEN), ASSOC("2Association", new Color(0, 0, 150)), PARENT("3Parent", RED); public final String name; public final Color color; private AssociationType(String name, Color color) { this.name = name; this.color = color; } }; /** * Association model for this UI. */ public interface AssociationModel { /** * The source table. */ String getSourceName(); /** * The destination table. */ String getDestinationName(); /** * The join-condition for joining source with destination table. */ String getJoinCondition(); /** * The cardinality. */ Cardinality getCardinality(); AssociationType getType(); /** * <code>true</code> for reversed association. */ boolean isReversed(); /** * The name of the association. */ String getName(); DataModel getDataModel(); }; /** * Default implementation of an association model for this UI. */ public static class DefaultAssociationModel implements AssociationModel { protected final Association association; public DefaultAssociationModel(Association association) { this.association = association; } /** * The source table. */ public String getSourceName() { return association.getDataModel().getDisplayName(association.source); } /** * The destination table. */ public String getDestinationName() { return association.getDataModel().getDisplayName(association.destination); } /** * The join-condition for joining source with destination table. */ public String getJoinCondition() { return association.getUnrestrictedJoinCondition(); } /** * The cardinality. */ public Cardinality getCardinality() { return association.getCardinality(); } /** * <code>true</code> for reversed association. */ public boolean isReversed() { return association.reversed; } /** * The name of the association. */ public String getName() { return association.getName(); } public DataModel getDataModel() { return association.getDataModel(); } @Override public AssociationType getType() { if (association.isInsertSourceBeforeDestination()) { return AssociationType.CHILD; } if (association.isInsertDestinationBeforeSource()) { return AssociationType.PARENT; } return AssociationType.ASSOC; } @Override public boolean equals(Object obj) { if (obj instanceof DefaultAssociationModel) { return association.equals(((DefaultAssociationModel) obj).association); } return false; } @Override public int hashCode() { return association.hashCode(); } }; /** * The model. */ private List<AssociationModel> model = new ArrayList<AssociationModel>(); /** * Selected associations. */ private Set<AssociationModel> selection = new HashSet<AssociationModel>(); /** * Hidden model associations. */ private Set<AssociationModel> hidden = new HashSet<AssociationModel>(); /** * All hidden associations. */ private Set<AssociationModel> hiddenAll = new HashSet<AssociationModel>(); /** * Keep order of associations according to the source-table? */ private final boolean stableSourceOrder; /** Creates new form AssociationListUI */ public AssociationListUI(String actionButtonText, String actionButtonToolTip, boolean stableSourceOrder) { this.stableSourceOrder = stableSourceOrder; initComponents(); doItButton.setText(actionButtonText); doItButton.setToolTipText(actionButtonToolTip); groupByComboBox.setModel(new DefaultComboBoxModel(GroupByDefinition.values())); groupByComboBox.setSelectedIndex(0); groupByComboBox.addItemListener(new ItemListener() { @Override public void itemStateChanged(ItemEvent e) { updateModel(); revalidate(); } }); if (jScrollPane1.getVerticalScrollBar() != null) { jScrollPane1.getVerticalScrollBar().setUnitIncrement(16); } if (jScrollPane1.getHorizontalScrollBar() != null) { jScrollPane1.getHorizontalScrollBar().setUnitIncrement(16); } } private Double pixelPerTableNameChar = null; /** * Sets the model. * * @param model the model */ public void setModel(Collection<AssociationModel> model) { this.model = new ArrayList<AssociationModel>(model); selection.retainAll(model); hidden.clear(); hidden.addAll(hiddenAll); hidden.retainAll(model); if (pixelPerTableNameChar == null) { Iterator<AssociationModel> firstAssociationI = model.iterator(); if (firstAssociationI.hasNext()) { AssociationModel firstAssociation = firstAssociationI.next(); double size = 0.0; int l = 0; for (Table t: firstAssociation.getDataModel().getTables()) { String tName = firstAssociation.getDataModel().getDisplayName(t); size += new JLabel(tName).getMinimumSize().width; l += tName.length(); } pixelPerTableNameChar = 8.0; if (l > 0) { pixelPerTableNameChar = size / l; } if (pixelPerTableNameChar < 5.0) { pixelPerTableNameChar = 5.0; } } } updateModel(); } private static final Color GREEN = new Color(0, 130, 0); private static final Color RED = Color.red; private static abstract class ColumnContentGetter { public abstract String getContent(AssociationModel association); public abstract String getDisplayName(); public Color getFgColor(Collection<AssociationModel> group) { Color fg = null; for (AssociationModel associationModel: group) { Color c = associationModel.getType().color; if (fg == null || fg == c) { fg = c; } else { fg = null; break; } } return fg; } }; private static class TypeGetter extends ColumnContentGetter { public String getContent(AssociationModel association) { return association.getType().name; } public String getDisplayName() { return "Type"; } }; private static class SourceGetter extends ColumnContentGetter { public String getContent(AssociationModel association) { return association.getSourceName(); } public String getDisplayName() { return "From"; } public Color getFgColor(Collection<AssociationModel> group) { return null; } }; private static class DestinationGetter extends ColumnContentGetter { public String getContent(AssociationModel association) { return association.getDestinationName(); } public String getDisplayName() { return "To"; } }; private static class AssociationNameGetter extends ColumnContentGetter { public String getContent(AssociationModel association) { return association.getName(); } public String getDisplayName() { return "Association Name"; } }; private class Node { public final Collection<AssociationModel> associations; public final List<Node> children = new ArrayList<AssociationListUI.Node>(); public final String group; public final Color fgColor; public Node(String group, Collection<AssociationModel> associations, Color fgColor) { this.group = group; this.associations = associations; this.fgColor = fgColor; } public boolean isLinear() { return children.size() == 0 || children.size() == 1 && children.get(0).isLinear(); } public boolean isSelected() { return selection.containsAll(associations); } public Collection<Node> getSubNodes() { Collection<Node> subNodes = new ArrayList<Node>(); for (Node child: children) { subNodes.add(child); subNodes.addAll(child.getSubNodes()); } return subNodes; } } private static ColumnContentGetter TYPE_CG = new TypeGetter(); private static ColumnContentGetter SOURCE_CG = new SourceGetter(); private static ColumnContentGetter DESTINATION_CG = new DestinationGetter(); private static ColumnContentGetter ASSOCIATION_NAME_CG = new AssociationNameGetter(); private enum GroupByDefinition { TSD("Type, From, To", new ColumnContentGetter[] { TYPE_CG, SOURCE_CG, DESTINATION_CG, ASSOCIATION_NAME_CG }), TDS("Type, To, From", new ColumnContentGetter[] { TYPE_CG, DESTINATION_CG, SOURCE_CG, ASSOCIATION_NAME_CG }), STD("From, Type, To", new ColumnContentGetter[] { SOURCE_CG, TYPE_CG, DESTINATION_CG, ASSOCIATION_NAME_CG }), DTS("To, Type, From", new ColumnContentGetter[] { DESTINATION_CG, TYPE_CG, SOURCE_CG, ASSOCIATION_NAME_CG }), SDT("From, To, Type", new ColumnContentGetter[] { SOURCE_CG, DESTINATION_CG, TYPE_CG, ASSOCIATION_NAME_CG }), DST("To, From, Type", new ColumnContentGetter[] { DESTINATION_CG, SOURCE_CG, TYPE_CG, ASSOCIATION_NAME_CG }); public final ColumnContentGetter[] columnContentGetter; public final String displayName; private GroupByDefinition(String displayName, ColumnContentGetter[] columnContentGetter) { this.displayName = displayName; this.columnContentGetter = columnContentGetter; } public String toString() { return displayName; } }; private List<MouseListener> allMouseListener = new ArrayList<MouseListener>(); private Map<Node, List<MouseListener>> mouseListenerPerNode = new HashMap<Node, List<MouseListener>>(); private List<Node> roots; /** * Hides selected associations. */ private void hideSelection() { hidden.addAll(selection); hiddenAll.addAll(selection); selection.clear(); updateModel(); } /** * Unhides hidden associations. */ private void unhideHidden() { hidden.clear(); hiddenAll.clear(); updateModel(); } /** * Performes action on selected associations. */ protected abstract void applyAction(Collection<AssociationModel> selection); /** * Updates the model UI. */ private void updateModel() { listPanel.removeAll(); allMouseListener.clear(); mouseListenerPerNode.clear(); ColumnContentGetter[] columnContentGetter = ((GroupByDefinition) groupByComboBox.getSelectedItem()).columnContentGetter; Collection<AssociationModel> unhidden = new ArrayList<AssociationListUI.AssociationModel>(model); unhidden.removeAll(hidden); roots = createHierarchy(columnContentGetter, 0, unhidden); if (!unhidden.isEmpty()) { for (int x = 0; x <= columnContentGetter.length; ++x) { String text = x == 0? " " : columnContentGetter[x - 1].getDisplayName(); JLabel title = new JLabel(text + " "); title.setBackground(Color.WHITE); title.setOpaque(true); title.setFont(bold); GridBagConstraints gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = x; gridBagConstraints.gridy = 0; gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; listPanel.add(title, gridBagConstraints); } } int[] y = new int[] { 2 }; updateUI(roots, 0, y, new boolean[] { false }, new HashMap<Integer, Integer>(), new Node[5]); JLabel l = new JLabel(" "); l.setBackground(Color.WHITE); l.setOpaque(true); GridBagConstraints gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridwidth = 5; gridBagConstraints.gridx = 0; gridBagConstraints.gridy = y[0]; gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; gridBagConstraints.weighty = 1.0; gridBagConstraints.weightx = 1.0; listPanel.add(l, gridBagConstraints); infoLabel.setText(selection.size() + " selected association" + (selection.size() == 1? "" : "s") + ", " + hidden.size() + " hidden "); hideButton.setEnabled(!selection.isEmpty()); doItButton.setEnabled(!selection.isEmpty()); unhideButton.setEnabled(!hidden.isEmpty()); revalidate(); } private void updateUI(List<Node> nodes, int level, int[] y, boolean[] groupStart, Map<Integer, Integer> minLevelPerY, Node[] lastRowContent) { boolean firstNode = true; Node pred = null; for (Node node: nodes) { GridBagConstraints gridBagConstraints; Color bgColor; if (y[0] % 2 == 0) { bgColor = new java.awt.Color(240, 255, 255); } else { bgColor = Color.WHITE; } if (!minLevelPerY.containsKey(y[0])) { minLevelPerY.put(y[0], level); } if (!firstNode) { for (int x = 0; x < level; ++x) { String lastText = " "; Color lastFgColor = null; if (lastRowContent[x] != null) { lastText = lastRowContent[x].group; lastFgColor = lastRowContent[x].fgColor; if (lastFgColor != null) { lastFgColor = new Color( lastFgColor.getRed() + 2 * (255 - lastFgColor.getRed()) / 3, lastFgColor.getGreen() + 2 * (255 - lastFgColor.getGreen()) / 3, lastFgColor.getBlue() + 2 * (255 - lastFgColor.getBlue()) / 3); } else { lastFgColor = Color.lightGray; } } JComponent l = createLabel(node, y[0], shorten(lastText), null, false, false, bgColor, lastFgColor, false, false); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = x + 1; gridBagConstraints.gridy = y[0]; gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; listPanel.add(l, gridBagConstraints); } } groupStart[0] = groupStart[0] || (y[0] > 0 && (!node.isLinear() || pred != null && !pred.isLinear())); // level < minLevelPerY.get(y[0] - 1)); AssociationModel a = node.associations.iterator().next(); String joinCondition = a.getJoinCondition(); if (a.isReversed()) { joinCondition = SqlUtil.reversRestrictionCondition(joinCondition); } JComponent l = createLabel(node, y[0], node.group, level >= 3? joinCondition : null, level < 3, groupStart[0], bgColor, level >= 3? Color.gray : node.fgColor, node.isSelected(), true); lastRowContent[level] = node; gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = level + 1; gridBagConstraints.gridy = y[0]; gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; if (level == 3) { gridBagConstraints.weightx = 1; } listPanel.add(l, gridBagConstraints); if (level >= 3) { ++y[0]; groupStart[0] = false; JPanel p = new JPanel(); p.setLayout(new GridBagLayout()); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = y[0] - 1; gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; listPanel.add(p, gridBagConstraints); gridBagConstraints = new GridBagConstraints(); gridBagConstraints.gridx = 1; gridBagConstraints.gridy = 1; gridBagConstraints.weightx = 1; gridBagConstraints.weighty = 1; gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; gridBagConstraints.insets = new Insets(2, 0, 2, 0); final JCheckBox checkbox = new JCheckBox(" "); p.add(checkbox, gridBagConstraints); p.setBackground(bgColor); checkbox.setBackground(bgColor); if (node.associations.size() != 1) { System.err.println("node.associations.size() != 1, " + node.associations.size()); } else { final AssociationModel association = a; checkbox.setSelected(selection.contains(association)); checkbox.addItemListener(new ItemListener() { @Override public void itemStateChanged(ItemEvent e) { if (checkbox.isSelected()) { selection.add(association); onSelect(association); } else { selection.remove(association); } updateModel(); } }); } } else { updateUI(node.children, level + 1, y, groupStart, minLevelPerY, lastRowContent); } firstNode = false; pred = node; } } private final Color BGCOLOR_OF_SELECTED_ROW = Color.CYAN; private Font font = new JLabel("normal").getFont(); private Font bold = new Font(font.getName(), font.getStyle() | Font.BOLD, font.getSize()); private Font nonbold = new Font(font.getName(), font.getStyle() & ~Font.BOLD, font.getSize()); private JComponent createLabel(final Node node, final int y, String text, String tooltip, boolean shorten, final boolean firstOfGroup, Color bgColor, Color fgColor, boolean selected, boolean addListener) { final JPanel panel = new JPanel() { @Override public void paint(Graphics graphics) { super.paint(graphics); if (firstOfGroup) { if (!(graphics instanceof Graphics2D)) return; Graphics2D g2d = (Graphics2D) graphics; Color color = Color.gray; g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2d.setColor(color); g2d.setStroke(new BasicStroke()); g2d.drawLine(0, 1, getSize().width - 1, 1); } } private static final long serialVersionUID = 5285941807747744395L; }; if (selected) { bgColor = new Color(220, 225, 255); } panel.setLayout(new GridBagLayout()); final JLabel label = new JLabel(); label.setOpaque(true); label.setFont(nonbold); if (fgColor != null) { label.setForeground(fgColor); } GridBagConstraints gridBagConstraints = new GridBagConstraints(); gridBagConstraints.gridx = 1; gridBagConstraints.gridy = 1; gridBagConstraints.weightx = 1; gridBagConstraints.weighty = 1; gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; gridBagConstraints.insets = new Insets(2, 0, 2, 0); panel.add(label, gridBagConstraints); if (text.trim().length() > 0) { label.setToolTipText(text); } if (tooltip != null) { label.setToolTipText(tooltip); } if (shorten) { text = shorten(text); } label.setText(text + " "); label.setBackground(bgColor); panel.setBackground(bgColor); if (!addListener) { return panel; } MouseListener l; label.addMouseListener(l = new MouseListener() { Color bgColorL; Color bgColorP; @Override public void mouseReleased(MouseEvent e) { } @Override public void mousePressed(MouseEvent e) { } @Override public void mouseExited(MouseEvent e) { if (e != null) { for (Node subNode: node.getSubNodes()) { for (MouseListener l: mouseListenerPerNode.get(subNode)) { if (l != this) { l.mouseExited(null); } } } } if (bgColorL != null) { label.setBackground(bgColorL); } if (bgColorP != null) { panel.setBackground(bgColorP); } } @Override public void mouseEntered(MouseEvent e) { if (e != null) { for (MouseListener l: allMouseListener) { if (l != this) { l.mouseExited(null); } } for (Node subNode: node.getSubNodes()) { for (MouseListener l: mouseListenerPerNode.get(subNode)) { if (l != this) { l.mouseEntered(null); } } } } if (bgColorL == null) { bgColorL = label.getBackground(); } if (bgColorP == null) { bgColorP = panel.getBackground(); } panel.setBackground(BGCOLOR_OF_SELECTED_ROW); label.setBackground(BGCOLOR_OF_SELECTED_ROW); } @Override public void mouseClicked(MouseEvent e) { if (e.getButton() == MouseEvent.BUTTON1) { if (node.isSelected()) { selection.removeAll(node.associations); } else { selection.addAll(node.associations); Node leaf = node; while (leaf.children != null && leaf.children.size() > 0) { leaf = leaf.children.get(0); } if (leaf.associations.size() > 0) { onSelect(leaf.associations.iterator().next()); } } updateModel(); } } }); allMouseListener.add(l); if (mouseListenerPerNode.get(node) == null) { mouseListenerPerNode.put(node, new ArrayList<MouseListener>()); } mouseListenerPerNode.get(node).add(l); return panel; } protected void onSelect(AssociationModel association) { } private Map<String, String> shortForms = new HashMap<String, String>(); private String shorten(String text) { if (shortForms.containsKey(text)) { return shortForms.get(text); } Pattern p = Pattern.compile("^(.*) (\\([0-9]*\\))$"); Matcher matcher = p.matcher(text); String pre = text; String suf = ""; if (matcher.matches()) { pre = matcher.group(1); suf = matcher.group(2); } String shortText = text; int maxWidth = (int) ((pixelPerTableNameChar == null? 8 : pixelPerTableNameChar) * 30.0); for (int i = pre.length() - 2; i > 3; --i) { if (new JLabel(shortText).getMinimumSize().width <= maxWidth) { break; } shortText = pre.substring(0, i) + "..." + suf; } shortForms.put(text, shortText); return shortText; } /** * Create hierarchy of associations. * * @param columnContentGetter the {@link ColumnContentGetter} * @param i index of current {@link ColumnContentGetter} * @return list of nodes */ private List<Node> createHierarchy(ColumnContentGetter[] columnContentGetter, int i, Collection<AssociationModel> associations) { SortedMap<String, Collection<AssociationModel>> groups = new TreeMap<String, Collection<AssociationModel>>(); List<String> groupKeys = new ArrayList<String>(); for (AssociationModel association: associations) { String key = columnContentGetter[i].getContent(association); if (!groups.containsKey(key)) { groups.put(key, new ArrayList<AssociationModel>()); groupKeys.add(key); } groups.get(key).add(association); } List<Node> result = new ArrayList<Node>(); Iterable<String> gk = groups.keySet(); if (stableSourceOrder && (columnContentGetter[i] instanceof SourceGetter)) { gk = groupKeys; } for (String groupKey: gk) { Collection<AssociationModel> group = groups.get(groupKey); String gName = groupKey; if (columnContentGetter[i] instanceof TypeGetter) { gName = gName.substring(1); } Node node = new Node(gName, group, columnContentGetter[i].getFgColor(group)); result.add(node); if (i + 1 < columnContentGetter.length) { node.children.addAll(createHierarchy(columnContentGetter, i + 1, group)); } } return result; } /** This method is called from within the constructor to * initialize the form. * WARNING: Do NOT modify this code. The content of this method is * always regenerated by the Form Editor. */ // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents private void initComponents() { java.awt.GridBagConstraints gridBagConstraints; jPanel1 = new javax.swing.JPanel(); jScrollPane1 = new javax.swing.JScrollPane(); listPanel = new javax.swing.JPanel(); jPanel2 = new javax.swing.JPanel(); jLabel1 = new javax.swing.JLabel(); groupByComboBox = new net.sf.jailer.ui.JComboBox(); infoLabel = new javax.swing.JLabel(); jPanel4 = new javax.swing.JPanel(); hideButton = new javax.swing.JButton(); unhideButton = new javax.swing.JButton(); doItButton = new javax.swing.JButton(); setLayout(new java.awt.BorderLayout()); jPanel1.setLayout(new java.awt.GridBagLayout()); listPanel.setLayout(new java.awt.GridBagLayout()); jScrollPane1.setViewportView(listPanel); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 1; gridBagConstraints.gridy = 1; gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; gridBagConstraints.weightx = 1.0; gridBagConstraints.weighty = 1.0; jPanel1.add(jScrollPane1, gridBagConstraints); jPanel2.setLayout(new java.awt.GridBagLayout()); jLabel1.setText(" Sorted by "); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 1; gridBagConstraints.gridy = 1; gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST; gridBagConstraints.weightx = 1.0; jPanel2.add(jLabel1, gridBagConstraints); groupByComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" })); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 2; gridBagConstraints.gridy = 1; gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; jPanel2.add(groupByComboBox, gridBagConstraints); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 1; gridBagConstraints.gridy = 2; gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; gridBagConstraints.weightx = 1.0; jPanel1.add(jPanel2, gridBagConstraints); infoLabel.setText(" 12 selected, 0 hidden"); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 1; gridBagConstraints.gridy = 3; gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST; gridBagConstraints.insets = new java.awt.Insets(4, 0, 4, 0); jPanel1.add(infoLabel, gridBagConstraints); jPanel4.setLayout(new java.awt.GridBagLayout()); hideButton.setText("Hide"); hideButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { hideButtonActionPerformed(evt); } }); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 1; gridBagConstraints.gridy = 1; jPanel4.add(hideButton, gridBagConstraints); unhideButton.setText("Unhide"); unhideButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { unhideButtonActionPerformed(evt); } }); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 2; gridBagConstraints.gridy = 1; jPanel4.add(unhideButton, gridBagConstraints); doItButton.setText("doIt"); doItButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { doItButtonActionPerformed(evt); } }); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 3; gridBagConstraints.gridy = 1; gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST; gridBagConstraints.weightx = 1.0; jPanel4.add(doItButton, gridBagConstraints); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 1; gridBagConstraints.gridy = 6; gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; jPanel1.add(jPanel4, gridBagConstraints); add(jPanel1, java.awt.BorderLayout.CENTER); }// </editor-fold>//GEN-END:initComponents private void hideButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_hideButtonActionPerformed hideSelection(); }//GEN-LAST:event_hideButtonActionPerformed private void unhideButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_unhideButtonActionPerformed unhideHidden(); }//GEN-LAST:event_unhideButtonActionPerformed private void doItButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_doItButtonActionPerformed if (selection.size() < 50 || JOptionPane.YES_OPTION == JOptionPane.showConfirmDialog(this, "Resolve " + selection.size() + " associations?", "Resolve", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE)) { applyAction(new ArrayList<AssociationListUI.AssociationModel>(selection)); } }//GEN-LAST:event_doItButtonActionPerformed // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JButton doItButton; private net.sf.jailer.ui.JComboBox groupByComboBox; private javax.swing.JButton hideButton; private javax.swing.JLabel infoLabel; private javax.swing.JLabel jLabel1; private javax.swing.JPanel jPanel1; private javax.swing.JPanel jPanel2; private javax.swing.JPanel jPanel4; private javax.swing.JScrollPane jScrollPane1; private javax.swing.JPanel listPanel; private javax.swing.JButton unhideButton; // End of variables declaration//GEN-END:variables private static final long serialVersionUID = -5302225732569622137L; }