/*
* Copyright (C) 2011 The Android Open Source Project
*
* 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 com.android.ddmuilib.logcat;
import com.android.ddmlib.Log.LogLevel;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.TitleAreaDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
/**
* Dialog used to create or edit settings for a logcat filter.
*/
public final class LogCatFilterSettingsDialog extends TitleAreaDialog {
private static final String TITLE = "Logcat Message Filter Settings";
private static final String DEFAULT_MESSAGE =
"Filter logcat messages by the source's tag, pid or minimum log level.\n"
+ "Empty fields will match all messages.";
private String mFilterName;
private String mTag;
private String mText;
private String mPid;
private String mAppName;
private String mLogLevel;
private Text mFilterNameText;
private Text mTagFilterText;
private Text mTextFilterText;
private Text mPidFilterText;
private Text mAppNameFilterText;
private Combo mLogLevelCombo;
private Button mOkButton;
/**
* Construct the filter settings dialog with default values for all fields.
* @param parentShell .
*/
public LogCatFilterSettingsDialog(Shell parentShell) {
super(parentShell);
setDefaults("", "", "", "", "", LogLevel.VERBOSE);
}
/**
* Set the default values to show when the dialog is opened.
* @param filterName name for the filter.
* @param tag value for filter by tag
* @param text value for filter by text
* @param pid value for filter by pid
* @param appName value for filter by app name
* @param level value for filter by log level
*/
public void setDefaults(String filterName, String tag, String text, String pid, String appName,
LogLevel level) {
mFilterName = filterName;
mTag = tag;
mText = text;
mPid = pid;
mAppName = appName;
mLogLevel = level.getStringValue();
}
@Override
protected Control createDialogArea(Composite shell) {
setTitle(TITLE);
setMessage(DEFAULT_MESSAGE);
Composite parent = (Composite) super.createDialogArea(shell);
Composite c = new Composite(parent, SWT.BORDER);
c.setLayout(new GridLayout(2, false));
c.setLayoutData(new GridData(GridData.FILL_BOTH));
createLabel(c, "Filter Name:");
mFilterNameText = new Text(c, SWT.BORDER);
mFilterNameText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
mFilterNameText.setText(mFilterName);
createSeparator(c);
createLabel(c, "by Log Tag:");
mTagFilterText = new Text(c, SWT.BORDER);
mTagFilterText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
mTagFilterText.setText(mTag);
createLabel(c, "by Log Message:");
mTextFilterText = new Text(c, SWT.BORDER);
mTextFilterText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
mTextFilterText.setText(mText);
createLabel(c, "by PID:");
mPidFilterText = new Text(c, SWT.BORDER);
mPidFilterText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
mPidFilterText.setText(mPid);
createLabel(c, "by Application Name:");
mAppNameFilterText = new Text(c, SWT.BORDER);
mAppNameFilterText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
mAppNameFilterText.setText(mAppName);
createLabel(c, "by Log Level:");
mLogLevelCombo = new Combo(c, SWT.READ_ONLY | SWT.DROP_DOWN);
mLogLevelCombo.setItems(getLogLevels().toArray(new String[0]));
mLogLevelCombo.select(getLogLevels().indexOf(mLogLevel));
/* call validateDialog() whenever user modifies any text field */
ModifyListener m = new ModifyListener() {
@Override
public void modifyText(ModifyEvent arg0) {
DialogStatus status = validateDialog();
mOkButton.setEnabled(status.valid);
setErrorMessage(status.message);
}
};
mFilterNameText.addModifyListener(m);
mTagFilterText.addModifyListener(m);
mTextFilterText.addModifyListener(m);
mPidFilterText.addModifyListener(m);
mAppNameFilterText.addModifyListener(m);
return c;
}
@Override
protected void createButtonsForButtonBar(Composite parent) {
super.createButtonsForButtonBar(parent);
mOkButton = getButton(IDialogConstants.OK_ID);
DialogStatus status = validateDialog();
mOkButton.setEnabled(status.valid);
}
/**
* A tuple that specifies whether the current state of the inputs
* on the dialog is valid or not. If it is not valid, the message
* field stores the reason why it isn't.
*/
private static final class DialogStatus {
final boolean valid;
final String message;
private DialogStatus(boolean isValid, String errMessage) {
valid = isValid;
message = errMessage;
}
}
private DialogStatus validateDialog() {
/* check that there is some name for the filter */
if (mFilterNameText.getText().trim().equals("")) {
return new DialogStatus(false,
"Please provide a name for this filter.");
}
/* if a pid is provided, it should be a +ve integer */
String pidText = mPidFilterText.getText().trim();
if (pidText.trim().length() > 0) {
int pid = 0;
try {
pid = Integer.parseInt(pidText);
} catch (NumberFormatException e) {
return new DialogStatus(false,
"PID should be a positive integer.");
}
if (pid < 0) {
return new DialogStatus(false,
"PID should be a positive integer.");
}
}
/* tag field must use a valid regex pattern */
String tagText = mTagFilterText.getText().trim();
if (tagText.trim().length() > 0) {
try {
Pattern.compile(tagText);
} catch (PatternSyntaxException e) {
return new DialogStatus(false,
"Invalid regex used in tag field: " + e.getMessage());
}
}
/* text field must use a valid regex pattern */
String messageText = mTextFilterText.getText().trim();
if (messageText.trim().length() > 0) {
try {
Pattern.compile(messageText);
} catch (PatternSyntaxException e) {
return new DialogStatus(false,
"Invalid regex used in text field: " + e.getMessage());
}
}
/* app name field must use a valid regex pattern */
String appNameText = mAppNameFilterText.getText().trim();
if (appNameText.trim().length() > 0) {
try {
Pattern.compile(appNameText);
} catch (PatternSyntaxException e) {
return new DialogStatus(false,
"Invalid regex used in application name field: " + e.getMessage());
}
}
return new DialogStatus(true, null);
}
private void createSeparator(Composite c) {
Label l = new Label(c, SWT.SEPARATOR | SWT.HORIZONTAL);
GridData gd = new GridData(GridData.FILL_HORIZONTAL);
gd.horizontalSpan = 2;
l.setLayoutData(gd);
}
private void createLabel(Composite c, String text) {
Label l = new Label(c, SWT.NONE);
l.setText(text);
GridData gd = new GridData();
gd.horizontalAlignment = SWT.RIGHT;
l.setLayoutData(gd);
}
@Override
protected void okPressed() {
/* save values from the widgets before the shell is closed. */
mFilterName = mFilterNameText.getText();
mTag = mTagFilterText.getText();
mText = mTextFilterText.getText();
mLogLevel = mLogLevelCombo.getText();
mPid = mPidFilterText.getText();
mAppName = mAppNameFilterText.getText();
super.okPressed();
}
/**
* Obtain the name for this filter.
* @return user provided filter name, maybe empty.
*/
public String getFilterName() {
return mFilterName;
}
/**
* Obtain the tag regex to filter by.
* @return user provided tag regex, maybe empty.
*/
public String getTag() {
return mTag;
}
/**
* Obtain the text regex to filter by.
* @return user provided tag regex, maybe empty.
*/
public String getText() {
return mText;
}
/**
* Obtain user provided PID to filter by.
* @return user provided pid, maybe empty.
*/
public String getPid() {
return mPid;
}
/**
* Obtain user provided application name to filter by.
* @return user provided app name regex, maybe empty
*/
public String getAppName() {
return mAppName;
}
/**
* Obtain log level to filter by.
* @return log level string.
*/
public String getLogLevel() {
return mLogLevel;
}
/**
* Obtain the string representation of all supported log levels.
* @return an array of strings, each representing a certain log level.
*/
public static List<String> getLogLevels() {
List<String> logLevels = new ArrayList<String>();
for (LogLevel l : LogLevel.values()) {
logLevels.add(l.getStringValue());
}
return logLevels;
}
}