1 /* 2 * Copyright (C) 2011 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 package com.android.ddmuilib.logcat; 17 18 import com.android.ddmlib.Log.LogLevel; 19 20 import org.eclipse.jface.dialogs.IDialogConstants; 21 import org.eclipse.jface.dialogs.TitleAreaDialog; 22 import org.eclipse.swt.SWT; 23 import org.eclipse.swt.events.ModifyEvent; 24 import org.eclipse.swt.events.ModifyListener; 25 import org.eclipse.swt.layout.GridData; 26 import org.eclipse.swt.layout.GridLayout; 27 import org.eclipse.swt.widgets.Button; 28 import org.eclipse.swt.widgets.Combo; 29 import org.eclipse.swt.widgets.Composite; 30 import org.eclipse.swt.widgets.Control; 31 import org.eclipse.swt.widgets.Label; 32 import org.eclipse.swt.widgets.Shell; 33 import org.eclipse.swt.widgets.Text; 34 35 import java.util.ArrayList; 36 import java.util.List; 37 import java.util.regex.Pattern; 38 import java.util.regex.PatternSyntaxException; 39 40 /** 41 * Dialog used to create or edit settings for a logcat filter. 42 */ 43 public final class LogCatFilterSettingsDialog extends TitleAreaDialog { 44 private static final String TITLE = "Logcat Message Filter Settings"; 45 private static final String DEFAULT_MESSAGE = 46 "Filter logcat messages by the source's tag, pid or minimum log level.\n" 47 + "Empty fields will match all messages."; 48 49 private String mFilterName; 50 private String mTag; 51 private String mText; 52 private String mPid; 53 private String mAppName; 54 private String mLogLevel; 55 56 private Text mFilterNameText; 57 private Text mTagFilterText; 58 private Text mTextFilterText; 59 private Text mPidFilterText; 60 private Text mAppNameFilterText; 61 private Combo mLogLevelCombo; 62 private Button mOkButton; 63 64 /** 65 * Construct the filter settings dialog with default values for all fields. 66 * @param parentShell . 67 */ LogCatFilterSettingsDialog(Shell parentShell)68 public LogCatFilterSettingsDialog(Shell parentShell) { 69 super(parentShell); 70 setDefaults("", "", "", "", "", LogLevel.VERBOSE); 71 } 72 73 /** 74 * Set the default values to show when the dialog is opened. 75 * @param filterName name for the filter. 76 * @param tag value for filter by tag 77 * @param text value for filter by text 78 * @param pid value for filter by pid 79 * @param appName value for filter by app name 80 * @param level value for filter by log level 81 */ setDefaults(String filterName, String tag, String text, String pid, String appName, LogLevel level)82 public void setDefaults(String filterName, String tag, String text, String pid, String appName, 83 LogLevel level) { 84 mFilterName = filterName; 85 mTag = tag; 86 mText = text; 87 mPid = pid; 88 mAppName = appName; 89 mLogLevel = level.getStringValue(); 90 } 91 92 @Override createDialogArea(Composite shell)93 protected Control createDialogArea(Composite shell) { 94 setTitle(TITLE); 95 setMessage(DEFAULT_MESSAGE); 96 97 Composite parent = (Composite) super.createDialogArea(shell); 98 Composite c = new Composite(parent, SWT.BORDER); 99 c.setLayout(new GridLayout(2, false)); 100 c.setLayoutData(new GridData(GridData.FILL_BOTH)); 101 102 createLabel(c, "Filter Name:"); 103 mFilterNameText = new Text(c, SWT.BORDER); 104 mFilterNameText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); 105 mFilterNameText.setText(mFilterName); 106 107 createSeparator(c); 108 109 createLabel(c, "by Log Tag:"); 110 mTagFilterText = new Text(c, SWT.BORDER); 111 mTagFilterText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); 112 mTagFilterText.setText(mTag); 113 114 createLabel(c, "by Log Message:"); 115 mTextFilterText = new Text(c, SWT.BORDER); 116 mTextFilterText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); 117 mTextFilterText.setText(mText); 118 119 createLabel(c, "by PID:"); 120 mPidFilterText = new Text(c, SWT.BORDER); 121 mPidFilterText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); 122 mPidFilterText.setText(mPid); 123 124 createLabel(c, "by Application Name:"); 125 mAppNameFilterText = new Text(c, SWT.BORDER); 126 mAppNameFilterText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); 127 mAppNameFilterText.setText(mAppName); 128 129 createLabel(c, "by Log Level:"); 130 mLogLevelCombo = new Combo(c, SWT.READ_ONLY | SWT.DROP_DOWN); 131 mLogLevelCombo.setItems(getLogLevels().toArray(new String[0])); 132 mLogLevelCombo.select(getLogLevels().indexOf(mLogLevel)); 133 134 /* call validateDialog() whenever user modifies any text field */ 135 ModifyListener m = new ModifyListener() { 136 @Override 137 public void modifyText(ModifyEvent arg0) { 138 DialogStatus status = validateDialog(); 139 mOkButton.setEnabled(status.valid); 140 setErrorMessage(status.message); 141 } 142 }; 143 mFilterNameText.addModifyListener(m); 144 mTagFilterText.addModifyListener(m); 145 mTextFilterText.addModifyListener(m); 146 mPidFilterText.addModifyListener(m); 147 mAppNameFilterText.addModifyListener(m); 148 149 return c; 150 } 151 152 153 @Override createButtonsForButtonBar(Composite parent)154 protected void createButtonsForButtonBar(Composite parent) { 155 super.createButtonsForButtonBar(parent); 156 157 mOkButton = getButton(IDialogConstants.OK_ID); 158 159 DialogStatus status = validateDialog(); 160 mOkButton.setEnabled(status.valid); 161 } 162 163 /** 164 * A tuple that specifies whether the current state of the inputs 165 * on the dialog is valid or not. If it is not valid, the message 166 * field stores the reason why it isn't. 167 */ 168 private final class DialogStatus { 169 final boolean valid; 170 final String message; 171 DialogStatus(boolean isValid, String errMessage)172 private DialogStatus(boolean isValid, String errMessage) { 173 valid = isValid; 174 message = errMessage; 175 } 176 } 177 validateDialog()178 private DialogStatus validateDialog() { 179 /* check that there is some name for the filter */ 180 if (mFilterNameText.getText().trim().equals("")) { 181 return new DialogStatus(false, 182 "Please provide a name for this filter."); 183 } 184 185 /* if a pid is provided, it should be a +ve integer */ 186 String pidText = mPidFilterText.getText().trim(); 187 if (pidText.trim().length() > 0) { 188 int pid = 0; 189 try { 190 pid = Integer.parseInt(pidText); 191 } catch (NumberFormatException e) { 192 return new DialogStatus(false, 193 "PID should be a positive integer."); 194 } 195 196 if (pid < 0) { 197 return new DialogStatus(false, 198 "PID should be a positive integer."); 199 } 200 } 201 202 /* tag field must use a valid regex pattern */ 203 String tagText = mTagFilterText.getText().trim(); 204 if (tagText.trim().length() > 0) { 205 try { 206 Pattern.compile(tagText); 207 } catch (PatternSyntaxException e) { 208 return new DialogStatus(false, 209 "Invalid regex used in tag field: " + e.getMessage()); 210 } 211 } 212 213 /* text field must use a valid regex pattern */ 214 String messageText = mTextFilterText.getText().trim(); 215 if (messageText.trim().length() > 0) { 216 try { 217 Pattern.compile(messageText); 218 } catch (PatternSyntaxException e) { 219 return new DialogStatus(false, 220 "Invalid regex used in text field: " + e.getMessage()); 221 } 222 } 223 224 /* app name field must use a valid regex pattern */ 225 String appNameText = mAppNameFilterText.getText().trim(); 226 if (appNameText.trim().length() > 0) { 227 try { 228 Pattern.compile(appNameText); 229 } catch (PatternSyntaxException e) { 230 return new DialogStatus(false, 231 "Invalid regex used in application name field: " + e.getMessage()); 232 } 233 } 234 235 return new DialogStatus(true, null); 236 } 237 createSeparator(Composite c)238 private void createSeparator(Composite c) { 239 Label l = new Label(c, SWT.SEPARATOR | SWT.HORIZONTAL); 240 GridData gd = new GridData(GridData.FILL_HORIZONTAL); 241 gd.horizontalSpan = 2; 242 l.setLayoutData(gd); 243 } 244 createLabel(Composite c, String text)245 private void createLabel(Composite c, String text) { 246 Label l = new Label(c, SWT.NONE); 247 l.setText(text); 248 GridData gd = new GridData(); 249 gd.horizontalAlignment = SWT.RIGHT; 250 l.setLayoutData(gd); 251 } 252 253 @Override okPressed()254 protected void okPressed() { 255 /* save values from the widgets before the shell is closed. */ 256 mFilterName = mFilterNameText.getText(); 257 mTag = mTagFilterText.getText(); 258 mText = mTextFilterText.getText(); 259 mLogLevel = mLogLevelCombo.getText(); 260 mPid = mPidFilterText.getText(); 261 mAppName = mAppNameFilterText.getText(); 262 263 super.okPressed(); 264 } 265 266 /** 267 * Obtain the name for this filter. 268 * @return user provided filter name, maybe empty. 269 */ getFilterName()270 public String getFilterName() { 271 return mFilterName; 272 } 273 274 /** 275 * Obtain the tag regex to filter by. 276 * @return user provided tag regex, maybe empty. 277 */ getTag()278 public String getTag() { 279 return mTag; 280 } 281 282 /** 283 * Obtain the text regex to filter by. 284 * @return user provided tag regex, maybe empty. 285 */ getText()286 public String getText() { 287 return mText; 288 } 289 290 /** 291 * Obtain user provided PID to filter by. 292 * @return user provided pid, maybe empty. 293 */ getPid()294 public String getPid() { 295 return mPid; 296 } 297 298 /** 299 * Obtain user provided application name to filter by. 300 * @return user provided app name regex, maybe empty 301 */ getAppName()302 public String getAppName() { 303 return mAppName; 304 } 305 306 /** 307 * Obtain log level to filter by. 308 * @return log level string. 309 */ getLogLevel()310 public String getLogLevel() { 311 return mLogLevel; 312 } 313 314 /** 315 * Obtain the string representation of all supported log levels. 316 * @return an array of strings, each representing a certain log level. 317 */ getLogLevels()318 public static List<String> getLogLevels() { 319 List<String> logLevels = new ArrayList<String>(); 320 321 for (LogLevel l : LogLevel.values()) { 322 logLevels.add(l.getStringValue()); 323 } 324 325 return logLevels; 326 } 327 } 328