/*
* Software Name : ATK
*
* Copyright (C) 2007 - 2012 France Télécom
*
* 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.
*
* ------------------------------------------------------------------
* File Name : PhoneConfigurationWizard.java
*
* Created : 08/01/2010
* Author(s) : France Telecom
*/
package com.orange.atk.atkUI.coregui;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Toolkit;
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.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.List;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.DefaultCellEditor;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.JTextPane;
import javax.swing.text.BadLocationException;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;
import org.apache.log4j.Logger;
import com.orange.atk.graphAnalyser.CreateGraph;
import com.orange.atk.monitoring.AroSettings;
import com.orange.atk.monitoring.Event;
import com.orange.atk.monitoring.EventlistModel;
import com.orange.atk.monitoring.Graph;
import com.orange.atk.monitoring.GraphlistModel;
import com.orange.atk.monitoring.MonitoringConfig;
import com.orange.atk.monitoring.ProcessTableModel;
import com.orange.atk.phone.PhoneInterface;
import com.orange.atk.phone.android.AndroidPhone;
import com.orange.atk.phone.detection.AutomaticPhoneDetection;
/**
* @author Fabien Moreau - FMOREAU@gfi.fr
*
*/
public class PhoneConfigurationWizard extends JFrame {
/**
*
*/
private static final long serialVersionUID = -6312160245575708505L;
private PhoneInterface phone;
private GraphlistModel graphs;
private EventlistModel events;
// process graph
private JTable processtable;
private ProcessTableModel tablemodel;
private JPopupMenu tablePopup;
private JCheckBox aroCheckbox;
// String
private String configpath;
// private static final String[] DEFAULT_MARKERS= {"Action","Error JATK",
// "Exception","Key Down",
// "KeyPress","Log","Standard Out/Err","Screenshot"};
private static final String[] USUAL_GRAPH_LIST = {"Cpu", "Memory", "Data sent", "Data received"};
private boolean isDefaultConfig = false;
public PhoneConfigurationWizard(String configFile, boolean isDefaultConfig) {
super();
this.isDefaultConfig = isDefaultConfig;
phone = AutomaticPhoneDetection.getInstance().getDevice();
this.configpath = configFile;
setLayout(new GridBagLayout());
// default constraints
// top left with no insets or a 0.1 weight (few move on resizing
GridBagConstraints c = new GridBagConstraints(0, 0, 1, 1, 0.1, 0.1,
GridBagConstraints.BASELINE_LEADING, GridBagConstraints.BOTH,
new Insets(1, 1, 1, 1), 0, 0);
final JPanel AROpane = new JPanel();
AROpane.setLayout(new BoxLayout(AROpane, BoxLayout.PAGE_AXIS));
AROpane.setBorder(BorderFactory.createTitledBorder("Application Resource Optimizer"));
aroCheckbox = new JCheckBox("enable ARO data collector");
AROpane.add(aroCheckbox);
add(AROpane, c);
c.gridy = 1;
c.gridx = 0;
add(buildGlobalGraphPanel(), c);
c.gridy = 1;
c.gridx = 1;
add(buildGlobalEventPanel(), c);
// specific to Android
if ((phone.getName() != null && phone.getName().contains("Android"))
&& !this.isDefaultConfig) {
c.gridy = 2;
c.gridx = 0;
c.gridwidth = 2;
c.weightx = 1;
c.weighty = 1;
add(buildMemoryProcessTable(), c);
}
MonitoringConfig config;
try {
config = MonitoringConfig.fromFile(configpath);
init(config);
} catch (IOException e1) {
Logger.getLogger(this.getClass()).error(e1);
}
pack();
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
saveconfig();
}
public void windowClosed(WindowEvent arg0) {
dispose();
}
});
setTitle("Phone Monitoring Configuration Wizard of " + configFile);
ImageIcon ii = new ImageIcon(CoreGUIPlugin.getMainIcon(), "Phone analyser configuration");
setIconImage(ii.getImage());
setVisible(true);
}
/**
* in relation with the constructor
*
* @return the table which manage memory process graph
*/
private Component buildMemoryProcessTable() {
JPanel panel = new JPanel();
panel.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints(0, 0, // gridx, gridy
1, 1, // gridwidth, gridheight
0.5, 0.5, // weightx, weighty
GridBagConstraints.CENTER, // anchor
GridBagConstraints.NONE, // FILL
new Insets(1, 1, 1, 1), // padding top, left, bottom, right
0, 0); // ipadx, ipady
JScrollPane scrollPanel = new JScrollPane();
processtable = new JTable();
tablemodel = new ProcessTableModel();
processtable.setModel(tablemodel);
processtable.setAutoCreateColumnsFromModel(true);
processtable.setShowGrid(true);
processtable.setFillsViewportHeight(true);
// Set up Edtitor for each column
// process column
processtable.getColumnModel().getColumn(0)
.setCellEditor(new DefaultCellEditor(buildProcessList()));
processtable.setFillsViewportHeight(true);
// Cpu, Mem or Storage
processtable.getColumnModel().getColumn(1)
.setCellEditor(new DefaultCellEditor(new JComboBox(USUAL_GRAPH_LIST)));
// Color
processtable.getColumnModel().getColumn(2)
.setCellEditor(new DefaultCellEditor(new JComboBox(CreateGraph.COLORS)));
// popup menu
processtable.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent arg0) {
if (arg0.getButton() == MouseEvent.BUTTON3) {
// RightClick
if (tablePopup == null) {
newtablePopup();
}
tablePopup.setLocation(arg0.getXOnScreen(), arg0.getYOnScreen());
tablePopup.setVisible(true);
}
if (arg0.getButton() == MouseEvent.BUTTON1 && tablePopup != null) {
tablePopup.setVisible(false);
}
}
});
// To center the window
this.setLocation(CoreGUIPlugin.mainFrame.getLocationX() + 150,
CoreGUIPlugin.mainFrame.getLocationY() + 100);
scrollPanel.getViewport().add(processtable);
scrollPanel.setBorder(BorderFactory.createTitledBorder("Process table"));
JButton jbmonitor = new JButton("Add Monitor Process");
jbmonitor.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
tablemodel.addRow();
}
});
JButton jbProcessInfo = new JButton("Process informations");
jbProcessInfo.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
displayProcessInfo();
}
});
panel.add(jbmonitor, gbc);
gbc.gridx = 1;
panel.add(jbProcessInfo, gbc);
gbc.gridx = 0;
gbc.gridy = 1;
gbc.gridwidth = 2;
panel.add(scrollPanel, gbc);
return panel;
}
private void displayProcessInfo() {
JFrame processInfoFrame = new JFrame("Process informations");
JTextPane text = new JTextPane();
text.setEditable(false);
Style defaultStyle = text.getStyle("default");
Style boldStyle = text.addStyle("Bold", null);
StyleConstants.setBold(boldStyle, true);
StyledDocument doc = text.getStyledDocument();
Hashtable<String, String> processInfo = ((AndroidPhone) phone).getProcessInfo();
Enumeration<String> processNames = processInfo.keys();
try {
while (processNames.hasMoreElements()) {
String process = processNames.nextElement();
String packages = processInfo.get(process);
String[] values = packages.split(",");
if (values.length > 1 || !process.equals(values[0])) {
doc.insertString(doc.getLength(), "\n " + process, boldStyle);
doc.insertString(doc.getLength(), " process is shared by packages:",
defaultStyle);
for (int i = 0; i < values.length; i++) {
doc.insertString(doc.getLength(), "\n * " + values[i], defaultStyle);
}
doc.insertString(doc.getLength(), "\n", defaultStyle);
}
}
doc.insertString(doc.getLength(),
"\n Other packages run in their own process (with the same name).",
defaultStyle);
} catch (BadLocationException e) {
Logger.getLogger(this.getClass()).error(e);
}
processInfoFrame.setLayout(new BorderLayout());
JScrollPane scrollPanel = new JScrollPane();
processInfoFrame.setPreferredSize(new Dimension(400, 500));
processInfoFrame.add(scrollPanel);
scrollPanel.getViewport().add(text);
Dimension sSize = Toolkit.getDefaultToolkit().getScreenSize();
Dimension fSize = this.getSize();
processInfoFrame.setLocation((sSize.width - fSize.width) / 2,
(sSize.height - fSize.height) / 2);
processInfoFrame.pack();
processInfoFrame.setVisible(true);
}
private void newtablePopup() {
tablePopup = new JPopupMenu();
JMenuItem jmiDelete = new JMenuItem("Delete Selected Lines");
jmiDelete.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
for (int row : processtable.getSelectedRows()) {
tablemodel.removeRow(row);
}
tablePopup.setVisible(false);
}
});
tablePopup.add(jmiDelete);
JMenuItem jmiadd = new JMenuItem("add a row");
jmiadd.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
tablemodel.addRow();
tablePopup.setVisible(false);
}
});
tablePopup.add(jmiadd);
}
private JComboBox buildProcessList() {
if (phone == null) {
JComboBox mybox = new JComboBox(USUAL_GRAPH_LIST);
mybox.setEditable(true);
return mybox;
} else {
return new JComboBox(phone.getMonitorList());
}
}
/**
*
* @return a JPpanel to select which event we want following
*/
private Component buildGlobalEventPanel() {
JPanel Eventpanel = new JPanel();
Eventpanel.setBorder(BorderFactory.createTitledBorder("Events"));
events = new EventlistModel();
final JList eventlist = new JList(events);
eventlist.setPreferredSize(new Dimension(100, 100));
eventlist.setBorder(BorderFactory.createTitledBorder("marked event"));
Eventpanel.setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints(0, 0, 1, 3, 1., 1.,
GridBagConstraints.BASELINE_LEADING, GridBagConstraints.BOTH,
new Insets(1, 1, 1, 1), 0, 0);
Eventpanel.add(eventlist, c);
c.gridx = 1;
c.gridy = 2;
c.fill = GridBagConstraints.HORIZONTAL;
c.anchor = GridBagConstraints.SOUTH;
JButton removemarker = new JButton("Remove");
removemarker.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
events.remove(eventlist.getSelectedIndex());
}
});
if (!this.isDefaultConfig) {
Eventpanel.add(removemarker, c);
}
return Eventpanel;
}
/**
*
* @return a JPANEL which contains all parameters for show or not devices
* graphs
*/
private Component buildGlobalGraphPanel() {
final JPanel globalpanel = new JPanel();
globalpanel.setBorder(BorderFactory.createTitledBorder("Device graphs"));
globalpanel.setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints(0, 0, 1, 8, 1., 1.,
GridBagConstraints.BASELINE_LEADING, GridBagConstraints.BOTH,
new Insets(1, 1, 1, 1), 0, 0);
graphs = new GraphlistModel();
final JList graphslist = new JList(graphs);
graphslist.setPreferredSize(new Dimension(100, 100));
graphslist.setBorder(BorderFactory.createTitledBorder("Graphics"));
globalpanel.add(graphslist, c);
c.gridwidth = 2;
c.gridheight = 1;
c.weightx = 0.01;
c.weighty = 0.1;
c.gridx = 1;
final JTextField graphname = new JTextField("name");
graphname.setEditable(false);
globalpanel.add(graphname, c);
c.gridy = 1;
final JComboBox graphcolor = new JComboBox(CreateGraph.COLORS);
globalpanel.add(graphcolor, c);
c.gridy = 2;
final JTextField graphcommentX = new JTextField("Comment X axis");
graphcommentX.setEditable(false);
globalpanel.add(graphcommentX, c);
c.gridy = 3;
final JTextField graphcommentY = new JTextField("Comment Y axis");
graphcommentY.setEditable(false);
globalpanel.add(graphcommentY, c);
c.gridy = 4;
final JTextField graphunit = new JTextField("Unit");
graphunit.setEditable(false);
globalpanel.add(graphunit, c);
c.gridy = 5;
final JCheckBox graphsampled = new JCheckBox("Sampled");
// globalpanel.add(graphsampled,c);
c.gridy = 6;
final JTextField graphscale = new JTextField("Scale");
graphscale.setEditable(false);
globalpanel.add(graphscale, c);
c.gridy = 7;
final JTextField graphtype = new JTextField("Type");
graphtype.setEditable(false);
globalpanel.add(graphtype, c);
c.gridy = 8;
c.gridwidth = 1;
JButton addmarker = new JButton("Add");
addmarker.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
graphs.addgraph(graphname.getText(), (String) graphcolor.getSelectedItem(),
graphcommentX.getText(), graphcommentY.getText(), graphunit.getText(),
graphscale.getText(), graphsampled.isSelected(), graphtype.getText());
saveconfig();
}
});
// globalpanel.add(addmarker,c);
graphcolor.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int i = graphslist.getSelectedIndex();
if (-1 == i) {
return;
}
graphs.changecolor((String) graphcolor.getSelectedItem(), i);
saveconfig();
}
});
c.gridx = 2;
JButton removemarker = new JButton("Remove");
removemarker.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
graphs.remove(graphslist.getSelectedIndex());
graphslist.update(graphslist.getGraphics());
}
});
if (!this.isDefaultConfig) {
globalpanel.add(removemarker, c);
}
c.gridx = 3;
JButton savemarker = new JButton("Save");
savemarker.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int i = graphslist.getSelectedIndex();
if (-1 == i) {
return;
}
graphs.savegraph(graphname.getText(), (String) graphcolor.getSelectedItem(),
graphcommentX.getText(), graphcommentY.getText(), graphunit.getText(),
graphscale.getText(), graphsampled.isSelected(), graphtype.getText(), i);
saveconfig();
}
});
// globalpanel.add(savemarker,c);
graphslist.addMouseListener(new MouseListener() {
public void mouseClicked(MouseEvent arg0) {
int i = graphslist.getSelectedIndex();
graphname.setText(graphs.getName(i));
graphcolor.setSelectedItem(graphs.getColor(i));
graphcommentX.setText(graphs.getcommentX(i));
graphcommentY.setText(graphs.getcommentY(i));
graphunit.setText(graphs.getunit(i));
graphscale.setText(graphs.getscale(i));
graphsampled.setText(graphs.getsampled(i));
graphtype.setText(graphs.gettype(i));
}
public void mouseEntered(MouseEvent arg0) {
// Do nothing
}
public void mouseExited(MouseEvent arg0) {
// Do nothing
}
public void mousePressed(MouseEvent arg0) {
// Do nothing
}
public void mouseReleased(MouseEvent arg0) {
// Do nothing
}
});
return globalpanel;
}
private void init(MonitoringConfig config) {
for (Graph g : config.getGraphs()) {
if (g.getName().contains("_")) {
String[] tableLine = g.getName().split("_");
tablemodel.add(tableLine[1], tableLine[0], g.getColor());
} else {
this.graphs.addgraph(g.getName(), g.getColor(), g.getXcomment(), g.getYcomment(),
g.getUnit(), g.getScale(), g.getSampled(), g.getType());
}
}
for (Event e : config.getEvents()) {
this.events.addEvent(e.getName(), e.getPosition());
}
aroCheckbox.setSelected((config.getAroSettings() != null
&& config.getAroSettings().isEnabled()));
}
private void saveconfig() {
MonitoringConfig config = new MonitoringConfig();
List<Graph> configGraphs = new ArrayList<Graph>();
List<Event> configEvents = new ArrayList<Event>();
for (int i = 0; i < graphs.getSize(); i++) {
configGraphs.add(new Graph(graphs.getName(i),
graphs.getColor(i),
graphs.getcommentX(i),
graphs.getcommentY(i),
graphs.getunit(i),
graphs.getscale(i),
Boolean.valueOf(graphs.getsampled(i)),
graphs.gettype(i)));
}
// table Graph
if (tablemodel != null) {
for (int i = 0; i < tablemodel.getRowCount(); i++) {
// don't save non-fill row
String processname = (String) tablemodel.getValueAt(i, 0);
String type = (String) tablemodel.getValueAt(i, 1);
String color = (String) tablemodel.getValueAt(i, 2);
if ("process".equals(processname) || "color".equals(color)
|| "Cpu or Mem".equals(type)) {
JOptionPane
.showMessageDialog(null,
"You must select the process, the color AND the type! \nThe line will be ignored.");
continue;
}
String unit = "";
String scale = "1";
if (type.equals("Cpu")) {
unit = "%";
}
else if (type.equals("Memory")) {
unit = "KBytes";
} else if (type.equals("Data sent")) {
unit = "KBytes";
scale = "1000";
} else if (type.equals("Data received")) {
unit = "KBytes";
scale = "1000";
}
configGraphs.add(new Graph(type + "_" + processname, color, "time (min)", type
+ " " + processname, unit, scale, true, null));
}
}
for (int i = 0; i < events.getSize(); i++) {
configEvents.add(new Event(events.getName(i), events.getPosition(i), "gray"));
}
config.setAroSettings(new AroSettings(aroCheckbox.isSelected()));
config.setGraphs(configGraphs);
config.setEvents(configEvents);
config.toFile(configpath);
}
}