/* * Copyright (C) 2012 Sony Mobile Communications AB * * This file is part of ApkAnalyser. * * 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 analyser.gui; import gui.AbstractMainFrame; import gui.Canceable; import java.awt.BorderLayout; import java.awt.FlowLayout; import java.awt.GridLayout; import java.awt.HeadlessException; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.ArrayList; import java.util.Enumeration; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Vector; import javax.swing.AbstractButton; import javax.swing.BorderFactory; import javax.swing.ButtonGroup; import javax.swing.DefaultButtonModel; import javax.swing.JButton; import javax.swing.JDialog; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JPanel; import javax.swing.JRadioButton; import javax.swing.JScrollPane; import javax.swing.JTextField; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import mereflect.MEClass; import mereflect.MEField; public class FieldDialog extends JDialog { private static final long serialVersionUID = 3596837179732660909L; public static final int INSTANCE = 0; public static final int ELEMENTS = 1; public static final int ALL_ELEMENTS = 2; protected static Map<MEClass, Integer> selectedIndexPerClass = new HashMap<MEClass, Integer>(); AbstractMainFrame mainFrame; JList list; JTextField prefixTextField; boolean acked = false; Object ACK_LOCK = new Object(); boolean awaitingAckRequest = true; String locationPrefix; ButtonGroup rbGroup; JRadioButton oInstance; JRadioButton oElements; JRadioButton oAllElements; JTextField indexTextField; MEClass clazz; MEField chosenField = null; String output = null; int arraySpec = ALL_ELEMENTS; int[] specArrayElements; Canceable canceable; /** * @param owner * @param title * @throws java.awt.HeadlessException */ public FieldDialog(AbstractMainFrame owner, MEClass clazz, String title, String prefix, Vector<MEField> fields, Canceable canceable) throws HeadlessException { super(owner, title); mainFrame = owner; this.clazz = clazz; this.canceable = canceable; initGui(prefix, fields); } protected void initGui(String prefix, Vector<MEField> fields) { locationPrefix = prefix; JPanel mainPanel = new JPanel(); mainPanel.setBorder(BorderFactory.createEmptyBorder(2, 4, 2, 4)); mainPanel.setLayout(new BorderLayout()); // Prefix textfield JPanel textFieldPanel = new JPanel(); textFieldPanel.setLayout(new BorderLayout()); prefixTextField = new JTextField(locationPrefix); textFieldPanel.add(prefixTextField, BorderLayout.CENTER); textFieldPanel.setBorder(BorderFactory.createTitledBorder("Field output prefix")); // Array radiobuttons JPanel radioPanel = new JPanel(new GridLayout(0, 2)); rbGroup = new ButtonGroup(); oInstance = new JRadioButton("Array instance"); oElements = new JRadioButton("Specified elements (comma separated)"); oAllElements = new JRadioButton("All elements"); indexTextField = new JTextField("0"); rbGroup.add(oInstance); rbGroup.add(oElements); rbGroup.add(oAllElements); oAllElements.setEnabled(false); radioPanel.add(oElements); radioPanel.add(indexTextField); radioPanel.add(oAllElements); radioPanel.add(new JLabel()); radioPanel.add(oInstance); radioPanel.add(new JLabel()); radioPanel.setBorder(BorderFactory.createTitledBorder("Array field output")); ActionListener ugly = new ActionListener() { @Override public void actionPerformed(ActionEvent e) { DefaultButtonModel model = (DefaultButtonModel) oElements.getModel(); boolean enabled = model.getGroup().isSelected(model); indexTextField.setEnabled(enabled); } }; Enumeration<AbstractButton> rbe = rbGroup.getElements(); while (rbe.hasMoreElements()) { ((JRadioButton) rbe.nextElement()).addActionListener(ugly); } oElements.setSelected(true); indexTextField.setEnabled(true); // Field list JPanel listPanel = new JPanel(); listPanel.setLayout(new BorderLayout()); listPanel.setBorder(BorderFactory.createTitledBorder("Fields")); list = new JList(fields); listPanel.add(new JScrollPane(list), BorderLayout.CENTER); int sel = 0; if (selectedIndexPerClass.get(clazz) != null) { sel = (selectedIndexPerClass.get(clazz)).intValue(); } list.addListSelectionListener(new ListSelectionListener() { @Override public void valueChanged(ListSelectionEvent l) { String text = prefixTextField.getText(); MEField sField = (MEField) list.getSelectedValue(); boolean enableArrays = sField != null && sField.getType().isArray(); oInstance.setEnabled(enableArrays); oElements.setEnabled(enableArrays); //oAllElements.setEnabled(enableArrays); // TODO enable choice when implemented indexTextField.setEditable(enableArrays); if (sField != null && (text == null || text.trim().length() == 0 || text.startsWith(locationPrefix))) { prefixTextField.setText(locationPrefix + " " + sField.getType().toString() + " " + sField.getName() + "="); } } }); list.setSelectedIndex(sel); mainPanel.add(textFieldPanel, BorderLayout.NORTH); mainPanel.add(listPanel, BorderLayout.CENTER); mainPanel.add(radioPanel, BorderLayout.SOUTH); // Buttons JPanel buttons = new JPanel(); buttons.setLayout(new FlowLayout(FlowLayout.RIGHT)); JButton ok = new JButton("OK"); JButton cancel = new JButton("Cancel"); ok.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { apply(); close(); } }); cancel.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { close(); } }); buttons.add(ok); buttons.add(cancel); getContentPane().setLayout(new BorderLayout()); getContentPane().add(mainPanel, BorderLayout.CENTER); getContentPane().add(buttons, BorderLayout.SOUTH); awaitingAckRequest = true; chosenField = null; output = null; } protected void apply() { selectedIndexPerClass.put(clazz, new Integer(list.getSelectedIndex())); output = prefixTextField.getText(); chosenField = (MEField) list.getSelectedValue(); DefaultButtonModel modelAllElements = (DefaultButtonModel) oAllElements.getModel(); DefaultButtonModel modelElements = (DefaultButtonModel) oElements.getModel(); DefaultButtonModel modelInstance = (DefaultButtonModel) oInstance.getModel(); if (modelAllElements.getGroup().isSelected(modelAllElements)) { arraySpec = ALL_ELEMENTS; } else if (modelElements.getGroup().isSelected(modelElements)) { arraySpec = ELEMENTS; } else if (modelInstance.getGroup().isSelected(modelInstance)) { arraySpec = INSTANCE; } if (arraySpec == ELEMENTS) { String[] indicesStr = Settings.breakString(indexTextField.getText(), ","); List<Integer> indicesList = new ArrayList<Integer>(); for (int i = 0; i < indicesStr.length; i++) { try { indicesList.add(Integer.parseInt(indicesStr[i].trim())); } catch (Throwable ignore) { } } specArrayElements = new int[indicesList.size()]; for (int i = 0; i < specArrayElements.length; i++) { specArrayElements[i] = (indicesList.get(i)).intValue(); } } } protected void close() { synchronized (ACK_LOCK) { ACK_LOCK.notify(); awaitingAckRequest = false; } setVisible(false); dispose(); } /** * @return */ public MEField getChosenField() { return chosenField; } /** * @return */ public String getOutput() { return output; } public int getArraySpecification() { return arraySpec; } public int[] getArrayIndicesSpecification() { return specArrayElements; } public void awaitAcknowledge() { synchronized (ACK_LOCK) { while (awaitingAckRequest && canceable.isRunning()) { try { ACK_LOCK.wait(1000); } catch (InterruptedException ignore) { } } } } }