/**
  * Processes a change in the contents of the filter widget.
  *
  * @param inValue a <code>String</code> value containing the text of the filter widget
  */
 protected final void handleFilter(String inValue) {
   // inValue contains the full text of what the user entered in the filter widget, e.g. Side=B
   if (inValue.length() > 0) {
     // some filter value has been entered, process that value
     Matcher regexMatcher = mFilterPattern.matcher(inValue);
     // if the value is meaningful, continue, otherwise, exit and do nothing (no filtering changes)
     if (regexMatcher.matches()) {
       // the first match of the regex must be the field against which to match
       String fieldSpecifier = regexMatcher.group(1);
       try {
         // the second is the operator (either '=' or '~=' as dictated by the regex pattern)
         String operator = regexMatcher.group(2);
         // the third is the value to match
         String value = regexMatcher.group(3);
         // the field name may be one that we've translated to a shorter or more readable version
         // try to translate it back first
         String fieldNameToUse = FIXFieldLocalizer.readFIXFieldNameFromCache(fieldSpecifier);
         // dig out the field object indicated by the fieldSpecified (a failure will throw a
         // CoreException)
         Field<?> fixField = FIXMessageUtil.getQuickFixFieldFromName(fieldNameToUse);
         // this is the int value of the FIX field which we now know is valid
         int fixFieldInt = fixField.getField();
         // create a matcher depending on the operator entered by the user
         if ("=".equals(operator)) { // $NON-NLS-1$
           // use a straight string matcher
           getFilterMatcherEditor().setMatcher(createStringMatcher(fixFieldInt, value));
         } else {
           // use a regex matcher
           assert "~=".equals(operator); // $NON-NLS-1$
           getFilterMatcherEditor().setMatcher(createRegexMatcher(fixFieldInt, value));
         }
       } catch (Throwable t) {
         PhotonPlugin.getMainConsoleLogger().error(UNRECOGNIZED_FIELD.getText(fieldSpecifier));
       }
     }
   } else {
     // the value entered by the user is of zero length, use the default matcher
     getFilterMatcherEditor().setMatcher(getDefaultMatcher());
   }
 }
  @Override
  public void createPartControl(Composite parent) {
    final IActionBars actionBars = getViewSite().getActionBars();
    IToolBarManager toolbar = actionBars.getToolBarManager();
    mSymbolEntryText = new TextContributionItem(""); // $NON-NLS-1$
    toolbar.add(mSymbolEntryText);
    toolbar.add(new AddSymbolAction(mSymbolEntryText, this));

    final Table table =
        new Table(parent, SWT.MULTI | SWT.FULL_SELECTION | SWT.V_SCROLL | SWT.BORDER);
    table.setHeaderVisible(true);
    mViewer = new TableViewer(table);
    GridDataFactory.defaultsFor(table).applyTo(table);

    final MarketDataItemComparator comparator = new MarketDataItemComparator();
    mViewer.setComparator(comparator);

    SelectionListener listener =
        new SelectionAdapter() {
          @Override
          public void widgetSelected(SelectionEvent e) {
            // determine new sort column and direction
            TableColumn sortColumn = table.getSortColumn();
            TableColumn currentColumn = (TableColumn) e.widget;
            final int index = table.indexOf(currentColumn);
            int dir = table.getSortDirection();
            if (sortColumn == currentColumn) {
              dir = dir == SWT.UP ? SWT.DOWN : SWT.UP;
            } else {
              table.setSortColumn(currentColumn);
              dir = SWT.UP;
            }
            table.setSortDirection(dir);
            comparator.setSort(dir == SWT.UP ? 1 : -1);
            comparator.setIndex(index);
            mViewer.refresh();
          }
        };

    // create columns, using FIXFieldLocalizer to preserve backwards
    // compatibility
    TableViewerColumn symbolColumn =
        new TableViewerColumn(
            mViewer,
            createColumn(
                table,
                FIXFieldLocalizer.getLocalizedFIXFieldName(Symbol.class.getSimpleName()),
                SWT.LEFT,
                listener));
    symbolColumn.setEditingSupport(new SymbolEditingSupport());
    createColumn(
        table,
        FIXFieldLocalizer.getLocalizedFIXFieldName(LastPx.class.getSimpleName()),
        SWT.RIGHT,
        listener);
    createColumn(
        table,
        FIXFieldLocalizer.getLocalizedFIXFieldName(LastQty.class.getSimpleName()),
        SWT.RIGHT,
        listener);
    createColumn(
        table,
        FIXFieldLocalizer.getLocalizedFIXFieldName(BidSize.class.getSimpleName()),
        SWT.RIGHT,
        listener);
    createColumn(
        table,
        FIXFieldLocalizer.getLocalizedFIXFieldName(BidPx.class.getSimpleName()),
        SWT.RIGHT,
        listener);
    createColumn(
        table,
        FIXFieldLocalizer.getLocalizedFIXFieldName(OfferPx.class.getSimpleName()),
        SWT.RIGHT,
        listener);
    createColumn(
        table,
        FIXFieldLocalizer.getLocalizedFIXFieldName(OfferSize.class.getSimpleName()),
        SWT.RIGHT,
        listener);

    // restore table state if it exists
    if (mViewState != null) {
      ColumnState.restore(table, mViewState);
      for (TableColumn column : table.getColumns()) {
        if (column.getWidth() == 0) {
          column.setResizable(false);
        }
      }
    }

    registerContextMenu();
    getSite().setSelectionProvider(mViewer);

    ObservableListContentProvider content = new ObservableListContentProvider();
    mViewer.setContentProvider(content);
    IObservableSet domain = content.getKnownElements();
    IObservableMap[] maps =
        new IObservableMap[] {
          BeansObservables.observeMap(domain, MarketDataViewItem.class, "symbol"), // $NON-NLS-1$
          createCompositeMap(
              domain, "latestTick", MDPackage.Literals.MD_LATEST_TICK__PRICE), // $NON-NLS-1$
          createCompositeMap(
              domain, "latestTick", MDPackage.Literals.MD_LATEST_TICK__SIZE), // $NON-NLS-1$
          createCompositeMap(
              domain, "topOfBook", MDPackage.Literals.MD_TOP_OF_BOOK__BID_SIZE), // $NON-NLS-1$
          createCompositeMap(
              domain, "topOfBook", MDPackage.Literals.MD_TOP_OF_BOOK__BID_PRICE), // $NON-NLS-1$
          createCompositeMap(
              domain, "topOfBook", MDPackage.Literals.MD_TOP_OF_BOOK__ASK_PRICE), // $NON-NLS-1$
          createCompositeMap(
              domain, "topOfBook", MDPackage.Literals.MD_TOP_OF_BOOK__ASK_SIZE) // $NON-NLS-1$
        };
    mViewer.setLabelProvider(new ObservableMapLabelProvider(maps));
    mViewer.setUseHashlookup(true);
    mItems = WritableList.withElementType(MarketDataViewItem.class);
    mViewer.setInput(mItems);
  }