1 /* 2 * Copyright (C) 2008 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 17 package com.android.ddmuilib.log.event; 18 19 import com.android.ddmlib.log.EventContainer; 20 import com.android.ddmlib.log.EventLogParser; 21 import com.android.ddmlib.log.EventValueDescription; 22 import com.android.ddmlib.log.InvalidTypeException; 23 import com.android.ddmuilib.DdmUiPreferences; 24 import com.android.ddmuilib.TableHelper; 25 import org.eclipse.jface.preference.IPreferenceStore; 26 import org.eclipse.swt.SWT; 27 import org.eclipse.swt.events.ControlAdapter; 28 import org.eclipse.swt.events.ControlEvent; 29 import org.eclipse.swt.events.DisposeEvent; 30 import org.eclipse.swt.events.DisposeListener; 31 import org.eclipse.swt.layout.GridData; 32 import org.eclipse.swt.layout.GridLayout; 33 import org.eclipse.swt.widgets.Composite; 34 import org.eclipse.swt.widgets.Control; 35 import org.eclipse.swt.widgets.Label; 36 import org.eclipse.swt.widgets.ScrollBar; 37 import org.eclipse.swt.widgets.Table; 38 import org.eclipse.swt.widgets.TableColumn; 39 import org.eclipse.swt.widgets.TableItem; 40 41 import java.util.ArrayList; 42 import java.util.Calendar; 43 44 public class DisplayLog extends EventDisplay { 45 public DisplayLog(String name) { 46 super(name); 47 } 48 49 private final static String PREFS_COL_DATE = "EventLogPanel.log.Col1"; //$NON-NLS-1$ 50 private final static String PREFS_COL_PID = "EventLogPanel.log.Col2"; //$NON-NLS-1$ 51 private final static String PREFS_COL_EVENTTAG = "EventLogPanel.log.Col3"; //$NON-NLS-1$ 52 private final static String PREFS_COL_VALUENAME = "EventLogPanel.log.Col4"; //$NON-NLS-1$ 53 private final static String PREFS_COL_VALUE = "EventLogPanel.log.Col5"; //$NON-NLS-1$ 54 private final static String PREFS_COL_TYPE = "EventLogPanel.log.Col6"; //$NON-NLS-1$ 55 56 /** 57 * Resets the display. 58 */ 59 @Override 60 void resetUI() { 61 mLogTable.removeAll(); 62 } 63 64 /** 65 * Adds event to the display. 66 */ 67 @Override 68 void newEvent(EventContainer event, EventLogParser logParser) { 69 addToLog(event, logParser); 70 } 71 72 /** 73 * Creates the UI for the event display. 74 * 75 * @param parent the parent composite. 76 * @param logParser the current log parser. 77 * @return the created control (which may have children). 78 */ 79 @Override 80 Control createComposite(Composite parent, EventLogParser logParser, ILogColumnListener listener) { 81 return createLogUI(parent, listener); 82 } 83 84 /** 85 * Adds an {@link EventContainer} to the log. 86 * 87 * @param event the event. 88 * @param logParser the log parser. 89 */ 90 private void addToLog(EventContainer event, EventLogParser logParser) { 91 ScrollBar bar = mLogTable.getVerticalBar(); 92 boolean scroll = bar.getMaximum() == bar.getSelection() + bar.getThumb(); 93 94 // get the date. 95 Calendar c = Calendar.getInstance(); 96 long msec = (long) event.sec * 1000L; 97 c.setTimeInMillis(msec); 98 99 // convert the time into a string 100 String date = String.format("%1$tF %1$tT", c); 101 102 String eventName = logParser.getTagMap().get(event.mTag); 103 String pidName = Integer.toString(event.pid); 104 105 // get the value description 106 EventValueDescription[] valueDescription = logParser.getEventInfoMap().get(event.mTag); 107 if (valueDescription != null) { 108 for (int i = 0; i < valueDescription.length; i++) { 109 EventValueDescription description = valueDescription[i]; 110 try { 111 String value = event.getValueAsString(i); 112 113 logValue(date, pidName, eventName, description.getName(), value, 114 description.getEventValueType(), description.getValueType()); 115 } catch (InvalidTypeException e) { 116 logValue(date, pidName, eventName, description.getName(), e.getMessage(), 117 description.getEventValueType(), description.getValueType()); 118 } 119 } 120 121 // scroll if needed, by showing the last item 122 if (scroll) { 123 int itemCount = mLogTable.getItemCount(); 124 if (itemCount > 0) { 125 mLogTable.showItem(mLogTable.getItem(itemCount - 1)); 126 } 127 } 128 } 129 } 130 131 /** 132 * Adds an {@link EventContainer} to the log. Only add the values/occurrences defined by 133 * the list of descriptors. If an event is configured to be displayed by value and occurrence, 134 * only the values are displayed (as they mark an event occurrence anyway). 135 * <p/>This method is only called when at least one of the descriptor list is non empty. 136 * 137 * @param event 138 * @param logParser 139 * @param valueDescriptors 140 * @param occurrenceDescriptors 141 */ 142 protected void addToLog(EventContainer event, EventLogParser logParser, 143 ArrayList<ValueDisplayDescriptor> valueDescriptors, 144 ArrayList<OccurrenceDisplayDescriptor> occurrenceDescriptors) { 145 ScrollBar bar = mLogTable.getVerticalBar(); 146 boolean scroll = bar.getMaximum() == bar.getSelection() + bar.getThumb(); 147 148 // get the date. 149 Calendar c = Calendar.getInstance(); 150 long msec = (long) event.sec * 1000L; 151 c.setTimeInMillis(msec); 152 153 // convert the time into a string 154 String date = String.format("%1$tF %1$tT", c); 155 156 String eventName = logParser.getTagMap().get(event.mTag); 157 String pidName = Integer.toString(event.pid); 158 159 if (valueDescriptors.size() > 0) { 160 for (ValueDisplayDescriptor descriptor : valueDescriptors) { 161 logDescriptor(event, descriptor, date, pidName, eventName, logParser); 162 } 163 } else { 164 // we display the event. Since the StringBuilder contains the header (date, event name, 165 // pid) at this point, there isn't anything else to display. 166 } 167 168 // scroll if needed, by showing the last item 169 if (scroll) { 170 int itemCount = mLogTable.getItemCount(); 171 if (itemCount > 0) { 172 mLogTable.showItem(mLogTable.getItem(itemCount - 1)); 173 } 174 } 175 } 176 177 178 /** 179 * Logs a value in the ui. 180 * 181 * @param date 182 * @param pid 183 * @param event 184 * @param valueName 185 * @param value 186 * @param eventValueType 187 * @param valueType 188 */ 189 private void logValue(String date, String pid, String event, String valueName, 190 String value, EventContainer.EventValueType eventValueType, EventValueDescription.ValueType valueType) { 191 192 TableItem item = new TableItem(mLogTable, SWT.NONE); 193 item.setText(0, date); 194 item.setText(1, pid); 195 item.setText(2, event); 196 item.setText(3, valueName); 197 item.setText(4, value); 198 199 String type; 200 if (valueType != EventValueDescription.ValueType.NOT_APPLICABLE) { 201 type = String.format("%1$s, %2$s", eventValueType.toString(), valueType.toString()); 202 } else { 203 type = eventValueType.toString(); 204 } 205 206 item.setText(5, type); 207 } 208 209 /** 210 * Logs a value from an {@link EventContainer} as defined by the {@link ValueDisplayDescriptor}. 211 * 212 * @param event the EventContainer 213 * @param descriptor the ValueDisplayDescriptor defining which value to display. 214 * @param date the date of the event in a string. 215 * @param pidName 216 * @param eventName 217 * @param logParser 218 */ 219 private void logDescriptor(EventContainer event, ValueDisplayDescriptor descriptor, 220 String date, String pidName, String eventName, EventLogParser logParser) { 221 222 String value; 223 try { 224 value = event.getValueAsString(descriptor.valueIndex); 225 } catch (InvalidTypeException e) { 226 value = e.getMessage(); 227 } 228 229 EventValueDescription[] values = logParser.getEventInfoMap().get(event.mTag); 230 231 EventValueDescription valueDescription = values[descriptor.valueIndex]; 232 233 logValue(date, pidName, eventName, descriptor.valueName, value, 234 valueDescription.getEventValueType(), valueDescription.getValueType()); 235 } 236 237 /** 238 * Creates the UI for a log display. 239 * 240 * @param parent the parent {@link Composite} 241 * @param listener the {@link ILogColumnListener} to notify on column resize events. 242 * @return the top Composite of the UI. 243 */ 244 private Control createLogUI(Composite parent, final ILogColumnListener listener) { 245 Composite mainComp = new Composite(parent, SWT.NONE); 246 GridLayout gl; 247 mainComp.setLayout(gl = new GridLayout(1, false)); 248 gl.marginHeight = gl.marginWidth = 0; 249 mainComp.addDisposeListener(new DisposeListener() { 250 public void widgetDisposed(DisposeEvent e) { 251 mLogTable = null; 252 } 253 }); 254 255 Label l = new Label(mainComp, SWT.CENTER); 256 l.setText(mName); 257 l.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); 258 259 mLogTable = new Table(mainComp, SWT.MULTI | SWT.FULL_SELECTION | SWT.V_SCROLL | 260 SWT.BORDER); 261 mLogTable.setLayoutData(new GridData(GridData.FILL_BOTH)); 262 263 IPreferenceStore store = DdmUiPreferences.getStore(); 264 265 TableColumn col = TableHelper.createTableColumn( 266 mLogTable, "Time", 267 SWT.LEFT, "0000-00-00 00:00:00", PREFS_COL_DATE, store); //$NON-NLS-1$ 268 col.addControlListener(new ControlAdapter() { 269 @Override 270 public void controlResized(ControlEvent e) { 271 Object source = e.getSource(); 272 if (source instanceof TableColumn) { 273 listener.columnResized(0, (TableColumn) source); 274 } 275 } 276 }); 277 278 col = TableHelper.createTableColumn( 279 mLogTable, "pid", 280 SWT.LEFT, "0000", PREFS_COL_PID, store); //$NON-NLS-1$ 281 col.addControlListener(new ControlAdapter() { 282 @Override 283 public void controlResized(ControlEvent e) { 284 Object source = e.getSource(); 285 if (source instanceof TableColumn) { 286 listener.columnResized(1, (TableColumn) source); 287 } 288 } 289 }); 290 291 col = TableHelper.createTableColumn( 292 mLogTable, "Event", 293 SWT.LEFT, "abcdejghijklmno", PREFS_COL_EVENTTAG, store); //$NON-NLS-1$ 294 col.addControlListener(new ControlAdapter() { 295 @Override 296 public void controlResized(ControlEvent e) { 297 Object source = e.getSource(); 298 if (source instanceof TableColumn) { 299 listener.columnResized(2, (TableColumn) source); 300 } 301 } 302 }); 303 304 col = TableHelper.createTableColumn( 305 mLogTable, "Name", 306 SWT.LEFT, "Process Name", PREFS_COL_VALUENAME, store); //$NON-NLS-1$ 307 col.addControlListener(new ControlAdapter() { 308 @Override 309 public void controlResized(ControlEvent e) { 310 Object source = e.getSource(); 311 if (source instanceof TableColumn) { 312 listener.columnResized(3, (TableColumn) source); 313 } 314 } 315 }); 316 317 col = TableHelper.createTableColumn( 318 mLogTable, "Value", 319 SWT.LEFT, "0000000", PREFS_COL_VALUE, store); //$NON-NLS-1$ 320 col.addControlListener(new ControlAdapter() { 321 @Override 322 public void controlResized(ControlEvent e) { 323 Object source = e.getSource(); 324 if (source instanceof TableColumn) { 325 listener.columnResized(4, (TableColumn) source); 326 } 327 } 328 }); 329 330 col = TableHelper.createTableColumn( 331 mLogTable, "Type", 332 SWT.LEFT, "long, seconds", PREFS_COL_TYPE, store); //$NON-NLS-1$ 333 col.addControlListener(new ControlAdapter() { 334 @Override 335 public void controlResized(ControlEvent e) { 336 Object source = e.getSource(); 337 if (source instanceof TableColumn) { 338 listener.columnResized(5, (TableColumn) source); 339 } 340 } 341 }); 342 343 mLogTable.setHeaderVisible(true); 344 mLogTable.setLinesVisible(true); 345 346 return mainComp; 347 } 348 349 /** 350 * Resizes the <code>index</code>-th column of the log {@link Table} (if applicable). 351 * <p/> 352 * This does nothing if the <code>Table</code> object is <code>null</code> (because the display 353 * type does not use a column) or if the <code>index</code>-th column is in fact the originating 354 * column passed as argument. 355 * 356 * @param index the index of the column to resize 357 * @param sourceColumn the original column that was resize, and on which we need to sync the 358 * index-th column width. 359 */ 360 @Override 361 void resizeColumn(int index, TableColumn sourceColumn) { 362 if (mLogTable != null) { 363 TableColumn col = mLogTable.getColumn(index); 364 if (col != sourceColumn) { 365 col.setWidth(sourceColumn.getWidth()); 366 } 367 } 368 } 369 370 /** 371 * Gets display type 372 * 373 * @return display type as an integer 374 */ 375 @Override 376 int getDisplayType() { 377 return DISPLAY_TYPE_LOG_ALL; 378 } 379 } 380