Home | History | Annotate | Download | only in event
      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.CompareMethod;
     20 import com.android.ddmlib.log.EventContainer.EventValueType;
     21 import com.android.ddmlib.log.EventLogParser;
     22 import com.android.ddmlib.log.EventValueDescription;
     23 import com.android.ddmuilib.log.event.EventDisplay.OccurrenceDisplayDescriptor;
     24 import com.android.ddmuilib.log.event.EventDisplay.ValueDisplayDescriptor;
     25 
     26 import org.eclipse.swt.SWT;
     27 import org.eclipse.swt.events.ModifyEvent;
     28 import org.eclipse.swt.events.ModifyListener;
     29 import org.eclipse.swt.events.SelectionAdapter;
     30 import org.eclipse.swt.events.SelectionEvent;
     31 import org.eclipse.swt.graphics.Rectangle;
     32 import org.eclipse.swt.layout.GridData;
     33 import org.eclipse.swt.layout.GridLayout;
     34 import org.eclipse.swt.widgets.Button;
     35 import org.eclipse.swt.widgets.Combo;
     36 import org.eclipse.swt.widgets.Composite;
     37 import org.eclipse.swt.widgets.Dialog;
     38 import org.eclipse.swt.widgets.Display;
     39 import org.eclipse.swt.widgets.Event;
     40 import org.eclipse.swt.widgets.Label;
     41 import org.eclipse.swt.widgets.Listener;
     42 import org.eclipse.swt.widgets.Shell;
     43 import org.eclipse.swt.widgets.Text;
     44 
     45 import java.util.ArrayList;
     46 import java.util.Map;
     47 import java.util.Set;
     48 
     49 final class EventValueSelector extends Dialog {
     50     private static final int DLG_WIDTH = 400;
     51     private static final int DLG_HEIGHT = 300;
     52 
     53     private Shell mParent;
     54     private Shell mShell;
     55     private boolean mEditStatus;
     56     private Combo mEventCombo;
     57     private Combo mValueCombo;
     58     private Combo mSeriesCombo;
     59     private Button mDisplayPidCheckBox;
     60     private Combo mFilterCombo;
     61     private Combo mFilterMethodCombo;
     62     private Text mFilterValue;
     63     private Button mOkButton;
     64 
     65     private EventLogParser mLogParser;
     66     private OccurrenceDisplayDescriptor mDescriptor;
     67 
     68     /** list of event integer in the order of the combo. */
     69     private Integer[] mEventTags;
     70 
     71     /** list of indices in the {@link EventValueDescription} array of the current event
     72      * that are of type string. This lets us get back the {@link EventValueDescription} from the
     73      * index in the Series {@link Combo}.
     74      */
     75     private final ArrayList<Integer> mSeriesIndices = new ArrayList<Integer>();
     76 
     77     public EventValueSelector(Shell parent) {
     78         super(parent, SWT.DIALOG_TRIM | SWT.BORDER | SWT.APPLICATION_MODAL);
     79     }
     80 
     81     /**
     82      * Opens the display option dialog to edit a new descriptor.
     83      * @param decriptorClass the class of the object to instantiate. Must extend
     84      * {@link OccurrenceDisplayDescriptor}
     85      * @param logParser
     86      * @return true if the object is to be created, false if the creation was canceled.
     87      */
     88     boolean open(Class<? extends OccurrenceDisplayDescriptor> descriptorClass,
     89             EventLogParser logParser) {
     90         try {
     91             OccurrenceDisplayDescriptor descriptor = descriptorClass.newInstance();
     92             setModified();
     93             return open(descriptor, logParser);
     94         } catch (InstantiationException e) {
     95             return false;
     96         } catch (IllegalAccessException e) {
     97             return false;
     98         }
     99     }
    100 
    101     /**
    102      * Opens the display option dialog, to edit a {@link OccurrenceDisplayDescriptor} object or
    103      * a {@link ValueDisplayDescriptor} object.
    104      * @param descriptor The descriptor to edit.
    105      * @return true if the object was modified.
    106      */
    107     boolean open(OccurrenceDisplayDescriptor descriptor, EventLogParser logParser) {
    108         // make a copy of the descriptor as we'll use a working copy.
    109         if (descriptor instanceof ValueDisplayDescriptor) {
    110             mDescriptor = new ValueDisplayDescriptor((ValueDisplayDescriptor)descriptor);
    111         } else if (descriptor instanceof OccurrenceDisplayDescriptor) {
    112             mDescriptor = new OccurrenceDisplayDescriptor(descriptor);
    113         } else {
    114             return false;
    115         }
    116 
    117         mLogParser = logParser;
    118 
    119         createUI();
    120 
    121         if (mParent == null || mShell == null) {
    122             return false;
    123         }
    124 
    125         loadValueDescriptor();
    126 
    127         checkValidity();
    128 
    129         // Set the dialog size.
    130         try {
    131             mShell.setMinimumSize(DLG_WIDTH, DLG_HEIGHT);
    132             Rectangle r = mParent.getBounds();
    133             // get the center new top left.
    134             int cx = r.x + r.width/2;
    135             int x = cx - DLG_WIDTH / 2;
    136             int cy = r.y + r.height/2;
    137             int y = cy - DLG_HEIGHT / 2;
    138             mShell.setBounds(x, y, DLG_WIDTH, DLG_HEIGHT);
    139         } catch (Exception e) {
    140             e.printStackTrace();
    141         }
    142 
    143         mShell.layout();
    144 
    145         // actually open the dialog
    146         mShell.open();
    147 
    148         // event loop until the dialog is closed.
    149         Display display = mParent.getDisplay();
    150         while (!mShell.isDisposed()) {
    151             if (!display.readAndDispatch())
    152                 display.sleep();
    153         }
    154 
    155         return mEditStatus;
    156     }
    157 
    158     OccurrenceDisplayDescriptor getDescriptor() {
    159         return mDescriptor;
    160     }
    161 
    162     private void createUI() {
    163         GridData gd;
    164 
    165         mParent = getParent();
    166         mShell = new Shell(mParent, getStyle());
    167         mShell.setText("Event Display Configuration");
    168 
    169         mShell.setLayout(new GridLayout(2, false));
    170 
    171         Label l = new Label(mShell, SWT.NONE);
    172         l.setText("Event:");
    173 
    174         mEventCombo = new Combo(mShell, SWT.DROP_DOWN | SWT.READ_ONLY);
    175         mEventCombo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
    176 
    177         // the event tag / event name map
    178         Map<Integer, String> eventTagMap = mLogParser.getTagMap();
    179         Map<Integer, EventValueDescription[]> eventInfoMap = mLogParser.getEventInfoMap();
    180         Set<Integer> keys = eventTagMap.keySet();
    181         ArrayList<Integer> list = new ArrayList<Integer>();
    182         for (Integer i : keys) {
    183             if (eventInfoMap.get(i) != null) {
    184                 String eventName = eventTagMap.get(i);
    185                 mEventCombo.add(eventName);
    186 
    187                 list.add(i);
    188             }
    189         }
    190         mEventTags = list.toArray(new Integer[list.size()]);
    191 
    192         mEventCombo.addSelectionListener(new SelectionAdapter() {
    193             /* (non-Javadoc)
    194              * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
    195              */
    196             @Override
    197             public void widgetSelected(SelectionEvent e) {
    198                 handleEventComboSelection();
    199                 setModified();
    200             }
    201         });
    202 
    203         l = new Label(mShell, SWT.NONE);
    204         l.setText("Value:");
    205 
    206         mValueCombo = new Combo(mShell, SWT.DROP_DOWN | SWT.READ_ONLY);
    207         mValueCombo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
    208         mValueCombo.addSelectionListener(new SelectionAdapter() {
    209             /* (non-Javadoc)
    210              * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
    211              */
    212             @Override
    213             public void widgetSelected(SelectionEvent e) {
    214                 handleValueComboSelection();
    215                 setModified();
    216             }
    217         });
    218 
    219         l = new Label(mShell, SWT.NONE);
    220         l.setText("Series Name:");
    221 
    222         mSeriesCombo = new Combo(mShell, SWT.DROP_DOWN | SWT.READ_ONLY);
    223         mSeriesCombo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
    224         mSeriesCombo.addSelectionListener(new SelectionAdapter() {
    225             /* (non-Javadoc)
    226              * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
    227              */
    228             @Override
    229             public void widgetSelected(SelectionEvent e) {
    230                 handleSeriesComboSelection();
    231                 setModified();
    232             }
    233         });
    234 
    235         // empty comp
    236         new Composite(mShell, SWT.NONE).setLayoutData(gd = new GridData());
    237         gd.heightHint = gd.widthHint = 0;
    238 
    239         mDisplayPidCheckBox = new Button(mShell, SWT.CHECK);
    240         mDisplayPidCheckBox.setText("Also Show pid");
    241         mDisplayPidCheckBox.setEnabled(false);
    242         mDisplayPidCheckBox.addSelectionListener(new SelectionAdapter() {
    243             /* (non-Javadoc)
    244              * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
    245              */
    246             @Override
    247             public void widgetSelected(SelectionEvent e) {
    248                 mDescriptor.includePid = mDisplayPidCheckBox.getSelection();
    249                 setModified();
    250             }
    251         });
    252 
    253         l = new Label(mShell, SWT.NONE);
    254         l.setText("Filter By:");
    255 
    256         mFilterCombo = new Combo(mShell, SWT.DROP_DOWN | SWT.READ_ONLY);
    257         mFilterCombo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
    258         mFilterCombo.addSelectionListener(new SelectionAdapter() {
    259             /* (non-Javadoc)
    260              * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
    261              */
    262             @Override
    263             public void widgetSelected(SelectionEvent e) {
    264                 handleFilterComboSelection();
    265                 setModified();
    266             }
    267         });
    268 
    269         l = new Label(mShell, SWT.NONE);
    270         l.setText("Filter Method:");
    271 
    272         mFilterMethodCombo = new Combo(mShell, SWT.DROP_DOWN | SWT.READ_ONLY);
    273         mFilterMethodCombo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
    274         for (CompareMethod method : CompareMethod.values()) {
    275             mFilterMethodCombo.add(method.toString());
    276         }
    277         mFilterMethodCombo.select(0);
    278         mFilterMethodCombo.addSelectionListener(new SelectionAdapter() {
    279             /* (non-Javadoc)
    280              * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
    281              */
    282             @Override
    283             public void widgetSelected(SelectionEvent e) {
    284                 handleFilterMethodComboSelection();
    285                 setModified();
    286             }
    287         });
    288 
    289         l = new Label(mShell, SWT.NONE);
    290         l.setText("Filter Value:");
    291 
    292         mFilterValue = new Text(mShell, SWT.BORDER | SWT.SINGLE);
    293         mFilterValue.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
    294         mFilterValue.addModifyListener(new ModifyListener() {
    295             @Override
    296             public void modifyText(ModifyEvent e) {
    297                 if (mDescriptor.filterValueIndex != -1) {
    298                     // get the current selection in the event combo
    299                     int index = mEventCombo.getSelectionIndex();
    300 
    301                     if (index != -1) {
    302                         // match it to an event
    303                         int eventTag = mEventTags[index];
    304                         mDescriptor.eventTag = eventTag;
    305 
    306                         // get the EventValueDescription for this tag
    307                         EventValueDescription valueDesc = mLogParser.getEventInfoMap()
    308                             .get(eventTag)[mDescriptor.filterValueIndex];
    309 
    310                         // let the EventValueDescription convert the String value into an object
    311                         // of the proper type.
    312                         mDescriptor.filterValue = valueDesc.getObjectFromString(
    313                                 mFilterValue.getText().trim());
    314                         setModified();
    315                     }
    316                 }
    317             }
    318         });
    319 
    320         // add a separator spanning the 2 columns
    321 
    322         l = new Label(mShell, SWT.SEPARATOR | SWT.HORIZONTAL);
    323         gd = new GridData(GridData.FILL_HORIZONTAL);
    324         gd.horizontalSpan = 2;
    325         l.setLayoutData(gd);
    326 
    327         // add a composite to hold the ok/cancel button, no matter what the columns size are.
    328         Composite buttonComp = new Composite(mShell, SWT.NONE);
    329         gd = new GridData(GridData.FILL_HORIZONTAL);
    330         gd.horizontalSpan = 2;
    331         buttonComp.setLayoutData(gd);
    332         GridLayout gl;
    333         buttonComp.setLayout(gl = new GridLayout(6, true));
    334         gl.marginHeight = gl.marginWidth = 0;
    335 
    336         Composite padding = new Composite(mShell, SWT.NONE);
    337         padding.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
    338 
    339         mOkButton = new Button(buttonComp, SWT.PUSH);
    340         mOkButton.setText("OK");
    341         mOkButton.setLayoutData(new GridData(GridData.CENTER));
    342         mOkButton.addSelectionListener(new SelectionAdapter() {
    343             /* (non-Javadoc)
    344              * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
    345              */
    346             @Override
    347             public void widgetSelected(SelectionEvent e) {
    348                 mShell.close();
    349             }
    350         });
    351 
    352         padding = new Composite(mShell, SWT.NONE);
    353         padding.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
    354 
    355         padding = new Composite(mShell, SWT.NONE);
    356         padding.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
    357 
    358         Button cancelButton = new Button(buttonComp, SWT.PUSH);
    359         cancelButton.setText("Cancel");
    360         cancelButton.setLayoutData(new GridData(GridData.CENTER));
    361         cancelButton.addSelectionListener(new SelectionAdapter() {
    362             /* (non-Javadoc)
    363              * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
    364              */
    365             @Override
    366             public void widgetSelected(SelectionEvent e) {
    367                 // cancel the edit
    368                 mEditStatus = false;
    369                 mShell.close();
    370             }
    371         });
    372 
    373         padding = new Composite(mShell, SWT.NONE);
    374         padding.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
    375 
    376         mShell.addListener(SWT.Close, new Listener() {
    377             @Override
    378             public void handleEvent(Event event) {
    379                 event.doit = true;
    380             }
    381         });
    382     }
    383 
    384     private void setModified() {
    385         mEditStatus = true;
    386     }
    387 
    388     private void handleEventComboSelection() {
    389         // get the current selection in the event combo
    390         int index = mEventCombo.getSelectionIndex();
    391 
    392         if (index != -1) {
    393             // match it to an event
    394             int eventTag = mEventTags[index];
    395             mDescriptor.eventTag = eventTag;
    396 
    397             // get the EventValueDescription for this tag
    398             EventValueDescription[] values = mLogParser.getEventInfoMap().get(eventTag);
    399 
    400             // fill the combo for the values
    401             mValueCombo.removeAll();
    402             if (values != null) {
    403                 if (mDescriptor instanceof ValueDisplayDescriptor) {
    404                     ValueDisplayDescriptor valueDescriptor = (ValueDisplayDescriptor)mDescriptor;
    405 
    406                     mValueCombo.setEnabled(true);
    407                     for (EventValueDescription value : values) {
    408                         mValueCombo.add(value.toString());
    409                     }
    410 
    411                     if (valueDescriptor.valueIndex != -1) {
    412                         mValueCombo.select(valueDescriptor.valueIndex);
    413                     } else {
    414                         mValueCombo.clearSelection();
    415                     }
    416                 } else {
    417                     mValueCombo.setEnabled(false);
    418                 }
    419 
    420                 // fill the axis combo
    421                 mSeriesCombo.removeAll();
    422                 mSeriesCombo.setEnabled(false);
    423                 mSeriesIndices.clear();
    424                 int axisIndex = 0;
    425                 int selectionIndex = -1;
    426                 for (EventValueDescription value : values) {
    427                     if (value.getEventValueType() == EventValueType.STRING) {
    428                         mSeriesCombo.add(value.getName());
    429                         mSeriesCombo.setEnabled(true);
    430                         mSeriesIndices.add(axisIndex);
    431 
    432                         if (mDescriptor.seriesValueIndex != -1 &&
    433                                 mDescriptor.seriesValueIndex == axisIndex) {
    434                             selectionIndex = axisIndex;
    435                         }
    436                     }
    437                     axisIndex++;
    438                 }
    439 
    440                 if (mSeriesCombo.isEnabled()) {
    441                     mSeriesCombo.add("default (pid)", 0 /* index */);
    442                     mSeriesIndices.add(0 /* index */, -1 /* value */);
    443 
    444                     // +1 because we added another item at index 0
    445                     mSeriesCombo.select(selectionIndex + 1);
    446 
    447                     if (selectionIndex >= 0) {
    448                         mDisplayPidCheckBox.setSelection(mDescriptor.includePid);
    449                         mDisplayPidCheckBox.setEnabled(true);
    450                     } else {
    451                         mDisplayPidCheckBox.setEnabled(false);
    452                         mDisplayPidCheckBox.setSelection(false);
    453                     }
    454                 } else {
    455                     mDisplayPidCheckBox.setSelection(false);
    456                     mDisplayPidCheckBox.setEnabled(false);
    457                 }
    458 
    459                 // fill the filter combo
    460                 mFilterCombo.setEnabled(true);
    461                 mFilterCombo.removeAll();
    462                 mFilterCombo.add("(no filter)");
    463                 for (EventValueDescription value : values) {
    464                     mFilterCombo.add(value.toString());
    465                 }
    466 
    467                 // select the current filter
    468                 mFilterCombo.select(mDescriptor.filterValueIndex + 1);
    469                 mFilterMethodCombo.select(getFilterMethodIndex(mDescriptor.filterCompareMethod));
    470 
    471                 // fill the current filter value
    472                 if (mDescriptor.filterValueIndex != -1) {
    473                     EventValueDescription valueInfo = values[mDescriptor.filterValueIndex];
    474                     if (valueInfo.checkForType(mDescriptor.filterValue)) {
    475                         mFilterValue.setText(mDescriptor.filterValue.toString());
    476                     } else {
    477                         mFilterValue.setText("");
    478                     }
    479                 } else {
    480                     mFilterValue.setText("");
    481                 }
    482             } else {
    483                 disableSubCombos();
    484             }
    485         } else {
    486             disableSubCombos();
    487         }
    488 
    489         checkValidity();
    490     }
    491 
    492     /**
    493      *
    494      */
    495     private void disableSubCombos() {
    496         mValueCombo.removeAll();
    497         mValueCombo.clearSelection();
    498         mValueCombo.setEnabled(false);
    499 
    500         mSeriesCombo.removeAll();
    501         mSeriesCombo.clearSelection();
    502         mSeriesCombo.setEnabled(false);
    503 
    504         mDisplayPidCheckBox.setEnabled(false);
    505         mDisplayPidCheckBox.setSelection(false);
    506 
    507         mFilterCombo.removeAll();
    508         mFilterCombo.clearSelection();
    509         mFilterCombo.setEnabled(false);
    510 
    511         mFilterValue.setEnabled(false);
    512         mFilterValue.setText("");
    513         mFilterMethodCombo.setEnabled(false);
    514     }
    515 
    516     private void handleValueComboSelection() {
    517         ValueDisplayDescriptor valueDescriptor = (ValueDisplayDescriptor)mDescriptor;
    518 
    519         // get the current selection in the value combo
    520         int index = mValueCombo.getSelectionIndex();
    521         valueDescriptor.valueIndex = index;
    522 
    523         // for now set the built-in name
    524 
    525         // get the current selection in the event combo
    526         int eventIndex = mEventCombo.getSelectionIndex();
    527 
    528         // match it to an event
    529         int eventTag = mEventTags[eventIndex];
    530 
    531         // get the EventValueDescription for this tag
    532         EventValueDescription[] values = mLogParser.getEventInfoMap().get(eventTag);
    533 
    534         valueDescriptor.valueName = values[index].getName();
    535 
    536         checkValidity();
    537     }
    538 
    539     private void handleSeriesComboSelection() {
    540         // get the current selection in the axis combo
    541         int index = mSeriesCombo.getSelectionIndex();
    542 
    543         // get the actual value index from the list.
    544         int valueIndex = mSeriesIndices.get(index);
    545 
    546         mDescriptor.seriesValueIndex = valueIndex;
    547 
    548         if (index > 0) {
    549             mDisplayPidCheckBox.setEnabled(true);
    550             mDisplayPidCheckBox.setSelection(mDescriptor.includePid);
    551         } else {
    552             mDisplayPidCheckBox.setSelection(false);
    553             mDisplayPidCheckBox.setEnabled(false);
    554         }
    555     }
    556 
    557     private void handleFilterComboSelection() {
    558         // get the current selection in the axis combo
    559         int index = mFilterCombo.getSelectionIndex();
    560 
    561         // decrement index by 1 since the item 0 means
    562         // no filter (index = -1), and the rest is offset by 1
    563         index--;
    564 
    565         mDescriptor.filterValueIndex = index;
    566 
    567         if (index != -1) {
    568             mFilterValue.setEnabled(true);
    569             mFilterMethodCombo.setEnabled(true);
    570             if (mDescriptor.filterValue instanceof String) {
    571                 mFilterValue.setText((String)mDescriptor.filterValue);
    572             }
    573         } else {
    574             mFilterValue.setText("");
    575             mFilterValue.setEnabled(false);
    576             mFilterMethodCombo.setEnabled(false);
    577         }
    578     }
    579 
    580     private void handleFilterMethodComboSelection() {
    581         // get the current selection in the axis combo
    582         int index = mFilterMethodCombo.getSelectionIndex();
    583         CompareMethod method = CompareMethod.values()[index];
    584 
    585         mDescriptor.filterCompareMethod = method;
    586     }
    587 
    588     /**
    589      * Returns the index of the filter method
    590      * @param filterCompareMethod the {@link CompareMethod} enum.
    591      */
    592     private int getFilterMethodIndex(CompareMethod filterCompareMethod) {
    593         CompareMethod[] values = CompareMethod.values();
    594         for (int i = 0 ; i < values.length ; i++) {
    595             if (values[i] == filterCompareMethod) {
    596                 return i;
    597             }
    598         }
    599         return -1;
    600     }
    601 
    602 
    603     private void loadValueDescriptor() {
    604         // get the index from the eventTag.
    605         int eventIndex = 0;
    606         int comboIndex = -1;
    607         for (int i : mEventTags) {
    608             if (i == mDescriptor.eventTag) {
    609                 comboIndex = eventIndex;
    610                 break;
    611             }
    612             eventIndex++;
    613         }
    614 
    615         if (comboIndex == -1) {
    616             mEventCombo.clearSelection();
    617         } else {
    618             mEventCombo.select(comboIndex);
    619         }
    620 
    621         // get the event from the descriptor
    622         handleEventComboSelection();
    623     }
    624 
    625     private void checkValidity() {
    626         mOkButton.setEnabled(mEventCombo.getSelectionIndex() != -1 &&
    627                 (((mDescriptor instanceof ValueDisplayDescriptor) == false) ||
    628                         mValueCombo.getSelectionIndex() != -1));
    629     }
    630 }
    631