1/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.preload.ui;
18
19import com.android.ddmlib.Client;
20import com.android.ddmlib.ClientData;
21
22import java.awt.BorderLayout;
23import java.awt.Component;
24import java.awt.Dimension;
25import java.io.File;
26import java.util.List;
27
28import javax.swing.Action;
29import javax.swing.DefaultListCellRenderer;
30import javax.swing.JDialog;
31import javax.swing.JFileChooser;
32import javax.swing.JFrame;
33import javax.swing.JLabel;
34import javax.swing.JList;
35import javax.swing.JOptionPane;
36import javax.swing.JProgressBar;
37import javax.swing.JScrollPane;
38import javax.swing.JTable;
39import javax.swing.JToolBar;
40import javax.swing.ListModel;
41import javax.swing.SwingUtilities;
42import javax.swing.table.TableModel;
43
44public class SwingUI extends JFrame implements IUI {
45
46    private JList<Client> clientList;
47    private JTable dataTable;
48
49    // Shared file chooser, means the directory is retained.
50    private JFileChooser jfc;
51
52    public SwingUI() {
53        super("Preloaded-classes computation");
54    }
55
56    @Override
57    public boolean isSingleThreaded() {
58        return false;
59    }
60
61    @Override
62    public void prepare(ListModel<Client> clientListModel, TableModel dataTableModel,
63            List<Action> actions) {
64        getContentPane().add(new JScrollPane(clientList = new JList<Client>(clientListModel)),
65                BorderLayout.WEST);
66        clientList.setCellRenderer(new ClientListCellRenderer());
67        // clientList.addListSelectionListener(listener);
68
69        dataTable = new JTable(dataTableModel);
70        getContentPane().add(new JScrollPane(dataTable), BorderLayout.CENTER);
71
72        JToolBar toolbar = new JToolBar(JToolBar.HORIZONTAL);
73        for (Action a : actions) {
74            if (a == null) {
75                toolbar.addSeparator();
76            } else {
77                toolbar.add(a);
78            }
79        }
80        getContentPane().add(toolbar, BorderLayout.PAGE_START);
81
82        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
83        setBounds(100, 100, 800, 600);
84
85        setVisible(true);
86    }
87
88    @Override
89    public void ready() {
90    }
91
92    @Override
93    public Client getSelectedClient() {
94        return clientList.getSelectedValue();
95    }
96
97    @Override
98    public int getSelectedDataTableRow() {
99        return dataTable.getSelectedRow();
100    }
101
102    private JDialog currentWaitDialog = null;
103
104    @Override
105    public void showWaitDialog() {
106        if (currentWaitDialog == null) {
107            currentWaitDialog = new JDialog(this, "Please wait...", true);
108            currentWaitDialog.getContentPane().add(new JLabel("Please be patient."),
109                    BorderLayout.CENTER);
110            JProgressBar progress = new JProgressBar(JProgressBar.HORIZONTAL);
111            progress.setIndeterminate(true);
112            currentWaitDialog.getContentPane().add(progress, BorderLayout.SOUTH);
113            currentWaitDialog.setSize(200, 100);
114            currentWaitDialog.setLocationRelativeTo(null);
115            showWaitDialogLater();
116        }
117    }
118
119    private void showWaitDialogLater() {
120        SwingUtilities.invokeLater(new Runnable() {
121            @Override
122            public void run() {
123                if (currentWaitDialog != null) {
124                    currentWaitDialog.setVisible(true); // This is blocking.
125                }
126            }
127        });
128    }
129
130    @Override
131    public void updateWaitDialog(String s) {
132        if (currentWaitDialog != null) {
133            ((JLabel) currentWaitDialog.getContentPane().getComponent(0)).setText(s);
134            Dimension prefSize = currentWaitDialog.getPreferredSize();
135            Dimension curSize = currentWaitDialog.getSize();
136            if (prefSize.width > curSize.width || prefSize.height > curSize.height) {
137                currentWaitDialog.setSize(Math.max(prefSize.width, curSize.width),
138                        Math.max(prefSize.height, curSize.height));
139                currentWaitDialog.invalidate();
140            }
141        }
142    }
143
144    @Override
145    public void hideWaitDialog() {
146        if (currentWaitDialog != null) {
147            currentWaitDialog.setVisible(false);
148            currentWaitDialog = null;
149        }
150    }
151
152    @Override
153    public void showMessageDialog(String s) {
154        // Hide the wait dialog...
155        if (currentWaitDialog != null) {
156            currentWaitDialog.setVisible(false);
157        }
158
159        try {
160            JOptionPane.showMessageDialog(this, s);
161        } finally {
162            // And reshow it afterwards...
163            if (currentWaitDialog != null) {
164                showWaitDialogLater();
165            }
166        }
167    }
168
169    @Override
170    public boolean showConfirmDialog(String title, String message) {
171        // Hide the wait dialog...
172        if (currentWaitDialog != null) {
173            currentWaitDialog.setVisible(false);
174        }
175
176        try {
177            return JOptionPane.showConfirmDialog(this, title, message, JOptionPane.YES_NO_OPTION)
178                    == JOptionPane.YES_OPTION;
179        } finally {
180            // And reshow it afterwards...
181            if (currentWaitDialog != null) {
182                showWaitDialogLater();
183            }
184        }
185    }
186
187    @Override
188    public String showInputDialog(String message) {
189        // Hide the wait dialog...
190        if (currentWaitDialog != null) {
191            currentWaitDialog.setVisible(false);
192        }
193
194        try {
195            return JOptionPane.showInputDialog(message);
196        } finally {
197            // And reshow it afterwards...
198            if (currentWaitDialog != null) {
199                showWaitDialogLater();
200            }
201        }
202    }
203
204    @Override
205    @SuppressWarnings("unchecked")
206    public <T> T showChoiceDialog(String title, String message, T[] choices) {
207        // Hide the wait dialog...
208        if (currentWaitDialog != null) {
209            currentWaitDialog.setVisible(false);
210        }
211
212        try{
213            return (T)JOptionPane.showInputDialog(this,
214                    title,
215                    message,
216                    JOptionPane.QUESTION_MESSAGE,
217                    null,
218                    choices,
219                    choices[0]);
220        } finally {
221            // And reshow it afterwards...
222            if (currentWaitDialog != null) {
223                showWaitDialogLater();
224            }
225        }
226    }
227
228    @Override
229    public File showSaveDialog() {
230        // Hide the wait dialog...
231        if (currentWaitDialog != null) {
232            currentWaitDialog.setVisible(false);
233        }
234
235        try{
236            if (jfc == null) {
237                jfc = new JFileChooser();
238            }
239
240            int ret = jfc.showSaveDialog(this);
241            if (ret == JFileChooser.APPROVE_OPTION) {
242                return jfc.getSelectedFile();
243            } else {
244                return null;
245            }
246        } finally {
247            // And reshow it afterwards...
248            if (currentWaitDialog != null) {
249                showWaitDialogLater();
250            }
251        }
252    }
253
254    @Override
255    public File[] showOpenDialog(boolean multi) {
256        // Hide the wait dialog...
257        if (currentWaitDialog != null) {
258            currentWaitDialog.setVisible(false);
259        }
260
261        try{
262            if (jfc == null) {
263                jfc = new JFileChooser();
264            }
265
266            jfc.setMultiSelectionEnabled(multi);
267            int ret = jfc.showOpenDialog(this);
268            if (ret == JFileChooser.APPROVE_OPTION) {
269                return jfc.getSelectedFiles();
270            } else {
271                return null;
272            }
273        } finally {
274            // And reshow it afterwards...
275            if (currentWaitDialog != null) {
276                showWaitDialogLater();
277            }
278        }
279    }
280
281    private class ClientListCellRenderer extends DefaultListCellRenderer {
282
283        @Override
284        public Component getListCellRendererComponent(JList<?> list, Object value, int index,
285                boolean isSelected, boolean cellHasFocus) {
286            ClientData cd = ((Client) value).getClientData();
287            String s = cd.getClientDescription() + " (pid " + cd.getPid() + ")";
288            return super.getListCellRendererComponent(list, s, index, isSelected, cellHasFocus);
289        }
290    }
291}
292