1/*
2 * Copyright (C) 2007 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.ddmuilib.logcat;
18
19import com.android.ddmuilib.ImageLoader;
20
21import org.eclipse.swt.SWT;
22import org.eclipse.swt.events.ModifyEvent;
23import org.eclipse.swt.events.ModifyListener;
24import org.eclipse.swt.events.SelectionAdapter;
25import org.eclipse.swt.events.SelectionEvent;
26import org.eclipse.swt.graphics.Rectangle;
27import org.eclipse.swt.layout.GridData;
28import org.eclipse.swt.layout.GridLayout;
29import org.eclipse.swt.widgets.Button;
30import org.eclipse.swt.widgets.Combo;
31import org.eclipse.swt.widgets.Composite;
32import org.eclipse.swt.widgets.Dialog;
33import org.eclipse.swt.widgets.Display;
34import org.eclipse.swt.widgets.Event;
35import org.eclipse.swt.widgets.Label;
36import org.eclipse.swt.widgets.Listener;
37import org.eclipse.swt.widgets.Shell;
38import org.eclipse.swt.widgets.Text;
39
40/**
41 * Small dialog box to edit a static port number.
42 */
43public class EditFilterDialog extends Dialog {
44
45    private static final int DLG_WIDTH = 400;
46    private static final int DLG_HEIGHT = 260;
47
48    private static final String IMAGE_WARNING = "warning.png"; //$NON-NLS-1$
49    private static final String IMAGE_EMPTY = "empty.png"; //$NON-NLS-1$
50
51    private Shell mParent;
52
53    private Shell mShell;
54
55    private boolean mOk = false;
56
57    /**
58     * Filter being edited or created
59     */
60    private LogFilter mFilter;
61
62    private String mName;
63    private String mTag;
64    private String mPid;
65
66    /** Log level as an index of the drop-down combo
67     * @see getLogLevel
68     * @see getComboIndex
69     */
70    private int mLogLevel;
71
72    private Button mOkButton;
73
74    private Label mNameWarning;
75    private Label mTagWarning;
76    private Label mPidWarning;
77
78    public EditFilterDialog(Shell parent) {
79        super(parent, SWT.DIALOG_TRIM | SWT.BORDER | SWT.APPLICATION_MODAL);
80    }
81
82    public EditFilterDialog(Shell shell, LogFilter filter) {
83        this(shell);
84        mFilter = filter;
85    }
86
87    /**
88     * Opens the dialog. The method will return when the user closes the dialog
89     * somehow.
90     *
91     * @return true if ok was pressed, false if cancelled.
92     */
93    public boolean open() {
94        createUI();
95
96        if (mParent == null || mShell == null) {
97            return false;
98        }
99
100        mShell.setMinimumSize(DLG_WIDTH, DLG_HEIGHT);
101        Rectangle r = mParent.getBounds();
102        // get the center new top left.
103        int cx = r.x + r.width/2;
104        int x = cx - DLG_WIDTH / 2;
105        int cy = r.y + r.height/2;
106        int y = cy - DLG_HEIGHT / 2;
107        mShell.setBounds(x, y, DLG_WIDTH, DLG_HEIGHT);
108
109        mShell.open();
110
111        Display display = mParent.getDisplay();
112        while (!mShell.isDisposed()) {
113            if (!display.readAndDispatch())
114                display.sleep();
115        }
116
117        // we're quitting with OK.
118        // Lets update the filter if needed
119        if (mOk) {
120            // if it was a "Create filter" action we need to create it first.
121            if (mFilter == null) {
122                mFilter = new LogFilter(mName);
123            }
124
125            // setup the filter
126            mFilter.setTagMode(mTag);
127
128            if (mPid != null && mPid.length() > 0) {
129                mFilter.setPidMode(Integer.parseInt(mPid));
130            } else {
131                mFilter.setPidMode(-1);
132            }
133
134            mFilter.setLogLevel(getLogLevel(mLogLevel));
135        }
136
137        return mOk;
138    }
139
140    public LogFilter getFilter() {
141        return mFilter;
142    }
143
144    private void createUI() {
145        mParent = getParent();
146        mShell = new Shell(mParent, getStyle());
147        mShell.setText("Log Filter");
148
149        mShell.setLayout(new GridLayout(1, false));
150
151        mShell.addListener(SWT.Close, new Listener() {
152            @Override
153            public void handleEvent(Event event) {
154            }
155        });
156
157        // top part with the filter name
158        Composite nameComposite = new Composite(mShell, SWT.NONE);
159        nameComposite.setLayoutData(new GridData(GridData.FILL_BOTH));
160        nameComposite.setLayout(new GridLayout(3, false));
161
162        Label l = new Label(nameComposite, SWT.NONE);
163        l.setText("Filter Name:");
164
165        final Text filterNameText = new Text(nameComposite,
166                SWT.SINGLE | SWT.BORDER);
167        if (mFilter != null) {
168            mName = mFilter.getName();
169            if (mName != null) {
170                filterNameText.setText(mName);
171            }
172        }
173        filterNameText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
174        filterNameText.addModifyListener(new ModifyListener() {
175            @Override
176            public void modifyText(ModifyEvent e) {
177                mName = filterNameText.getText().trim();
178                validate();
179            }
180        });
181
182        mNameWarning = new Label(nameComposite, SWT.NONE);
183        mNameWarning.setImage(ImageLoader.getDdmUiLibLoader().loadImage(IMAGE_EMPTY,
184                mShell.getDisplay()));
185
186        // separator
187        l = new Label(mShell, SWT.SEPARATOR | SWT.HORIZONTAL);
188        l.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
189
190
191        // center part with the filter parameters
192        Composite main = new Composite(mShell, SWT.NONE);
193        main.setLayoutData(new GridData(GridData.FILL_BOTH));
194        main.setLayout(new GridLayout(3, false));
195
196        l = new Label(main, SWT.NONE);
197        l.setText("by Log Tag:");
198
199        final Text tagText = new Text(main, SWT.SINGLE | SWT.BORDER);
200        if (mFilter != null) {
201            mTag = mFilter.getTagFilter();
202            if (mTag != null) {
203                tagText.setText(mTag);
204            }
205        }
206
207        tagText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
208        tagText.addModifyListener(new ModifyListener() {
209            @Override
210            public void modifyText(ModifyEvent e) {
211                mTag = tagText.getText().trim();
212                validate();
213            }
214        });
215
216        mTagWarning = new Label(main, SWT.NONE);
217        mTagWarning.setImage(ImageLoader.getDdmUiLibLoader().loadImage(IMAGE_EMPTY,
218                mShell.getDisplay()));
219
220        l = new Label(main, SWT.NONE);
221        l.setText("by pid:");
222
223        final Text pidText = new Text(main, SWT.SINGLE | SWT.BORDER);
224        if (mFilter != null) {
225            if (mFilter.getPidFilter() != -1) {
226                mPid = Integer.toString(mFilter.getPidFilter());
227            } else {
228                mPid = "";
229            }
230            pidText.setText(mPid);
231        }
232        pidText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
233        pidText.addModifyListener(new ModifyListener() {
234            @Override
235            public void modifyText(ModifyEvent e) {
236                mPid = pidText.getText().trim();
237                validate();
238            }
239        });
240
241        mPidWarning = new Label(main, SWT.NONE);
242        mPidWarning.setImage(ImageLoader.getDdmUiLibLoader().loadImage(IMAGE_EMPTY,
243                mShell.getDisplay()));
244
245        l = new Label(main, SWT.NONE);
246        l.setText("by Log level:");
247
248        final Combo logCombo = new Combo(main, SWT.DROP_DOWN | SWT.READ_ONLY);
249        GridData gd = new GridData(GridData.FILL_HORIZONTAL);
250        gd.horizontalSpan = 2;
251        logCombo.setLayoutData(gd);
252
253        // add the labels
254        logCombo.add("<none>");
255        logCombo.add("Error");
256        logCombo.add("Warning");
257        logCombo.add("Info");
258        logCombo.add("Debug");
259        logCombo.add("Verbose");
260
261        if (mFilter != null) {
262            mLogLevel = getComboIndex(mFilter.getLogLevel());
263            logCombo.select(mLogLevel);
264        } else {
265            logCombo.select(0);
266        }
267
268        logCombo.addSelectionListener(new SelectionAdapter() {
269            @Override
270            public void widgetSelected(SelectionEvent e) {
271                // get the selection
272                mLogLevel = logCombo.getSelectionIndex();
273                validate();
274            }
275        });
276
277        // separator
278        l = new Label(mShell, SWT.SEPARATOR | SWT.HORIZONTAL);
279        l.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
280
281        // bottom part with the ok/cancel
282        Composite bottomComp = new Composite(mShell, SWT.NONE);
283        bottomComp
284                .setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_CENTER));
285        bottomComp.setLayout(new GridLayout(2, true));
286
287        mOkButton = new Button(bottomComp, SWT.NONE);
288        mOkButton.setText("OK");
289        mOkButton.addSelectionListener(new SelectionAdapter() {
290            @Override
291            public void widgetSelected(SelectionEvent e) {
292                mOk = true;
293                mShell.close();
294            }
295        });
296        mOkButton.setEnabled(false);
297        mShell.setDefaultButton(mOkButton);
298
299        Button cancelButton = new Button(bottomComp, SWT.NONE);
300        cancelButton.setText("Cancel");
301        cancelButton.addSelectionListener(new SelectionAdapter() {
302            @Override
303            public void widgetSelected(SelectionEvent e) {
304                mShell.close();
305            }
306        });
307
308        validate();
309    }
310
311    /**
312     * Returns the log level from a combo index.
313     * @param index the Combo index
314     * @return a log level valid for the Log class.
315     */
316    protected int getLogLevel(int index) {
317        if (index == 0) {
318            return -1;
319        }
320
321        return 7 - index;
322    }
323
324    /**
325     * Returns the index in the combo that matches the log level
326     * @param logLevel The Log level.
327     * @return the combo index
328     */
329    private int getComboIndex(int logLevel) {
330        if (logLevel == -1) {
331            return 0;
332        }
333
334        return 7 - logLevel;
335    }
336
337    /**
338     * Validates the content of the 2 text fields and enable/disable "ok", while
339     * setting up the warning/error message.
340     */
341    private void validate() {
342
343        boolean result = true;
344
345        // then we check it only contains digits.
346        if (mPid != null) {
347            if (mPid.matches("[0-9]*") == false) { //$NON-NLS-1$
348                mPidWarning.setImage(ImageLoader.getDdmUiLibLoader().loadImage(
349                        IMAGE_WARNING,
350                        mShell.getDisplay()));
351                mPidWarning.setToolTipText("PID must be a number"); //$NON-NLS-1$
352                result = false;
353            } else {
354                mPidWarning.setImage(ImageLoader.getDdmUiLibLoader().loadImage(
355                        IMAGE_EMPTY,
356                        mShell.getDisplay()));
357                mPidWarning.setToolTipText(null);
358            }
359        }
360
361        // then we check it not contains character | or :
362        if (mTag != null) {
363            if (mTag.matches(".*[:|].*") == true) { //$NON-NLS-1$
364                mTagWarning.setImage(ImageLoader.getDdmUiLibLoader().loadImage(
365                        IMAGE_WARNING,
366                        mShell.getDisplay()));
367                mTagWarning.setToolTipText("Tag cannot contain | or :"); //$NON-NLS-1$
368                result = false;
369            } else {
370                mTagWarning.setImage(ImageLoader.getDdmUiLibLoader().loadImage(
371                        IMAGE_EMPTY,
372                        mShell.getDisplay()));
373                mTagWarning.setToolTipText(null);
374            }
375        }
376
377        // then we check it not contains character | or :
378        if (mName != null && mName.length() > 0) {
379            if (mName.matches(".*[:|].*") == true) { //$NON-NLS-1$
380                mNameWarning.setImage(ImageLoader.getDdmUiLibLoader().loadImage(
381                        IMAGE_WARNING,
382                        mShell.getDisplay()));
383                mNameWarning.setToolTipText("Name cannot contain | or :"); //$NON-NLS-1$
384                result = false;
385            } else {
386                mNameWarning.setImage(ImageLoader.getDdmUiLibLoader().loadImage(
387                        IMAGE_EMPTY,
388                        mShell.getDisplay()));
389                mNameWarning.setToolTipText(null);
390            }
391        } else {
392            result = false;
393        }
394
395        mOkButton.setEnabled(result);
396    }
397}
398