int colTwoX = colZeroWidth + colOneWidth;
int colTwoX = (margin / 2) + colZeroWidth + colOneWidth;
  public TrackTable(Composite composite, TrackDatabase trackDatabase, SkinManager skinManager) {    display = composite.getDisplay();    this.trackDatabase = trackDatabase;    basicSkinable = new BasicSkinable(this.display);    table = new Table(composite, SWT.NONE);    table.setEnabled(false);    TableColumn col = new TableColumn(table, SWT.LEFT);    col.setWidth(200);    addColumnListener(col, comparator = new TrackComparator() {      public int compareTrack(Track track0, Track track1) {          return magicStringCompare(track0.getArtist(), track1.getArtist());      }            });    skinManager.addItem(col, "TrackTable.Heading.Artist");     col = new TableColumn(table, SWT.LEFT);    col.setWidth(200);    addColumnListener(col, new TrackComparator() {      public int compareTrack(Track track0, Track track1) {        return magicStringCompare(track0.getTitle(), track1.getTitle());      }            });    skinManager.addItem(col, "TrackTable.Heading.Track");     col = new TableColumn(table, SWT.LEFT);    col.setWidth(120);    // Setting the alighnment to left doesn't seem to make a difference for images on GTK    col.setAlignment(SWT.LEFT);    addColumnListener(col, new TrackComparator() {      public int compareTrack(Track track0, Track track1) {        return magicStringCompare(track0.getState(), track1.getState());      }            });    skinManager.addItem(col, "TrackTable.Heading.Rating");    col = new TableColumn(table, SWT.LEFT);    col.setAlignment(SWT.LEFT);    col.setWidth(50);    addColumnListener(col, new TrackComparator() {      public int compareTrack(Track track0, Track track1) {        return new Integer(track0.getNoOfTimesPlayed()).compareTo(new Integer(track1.getNoOfTimesPlayed()));      }            });    skinManager.addItem(col, "TrackTable.Heading.Plays");    col = new TableColumn(table, SWT.LEFT);    col.setWidth(120);    addColumnListener(col, new TrackComparator() {      public int compareTrack(Track track0, Track track1) {        return track0.getLastPlayed().compareTo(track1.getLastPlayed());      }            });    table.setHeaderVisible(true);    skinManager.addItem(col, "TrackTable.Heading.Last");     col = new TableColumn(table, SWT.LEFT);    col.setWidth(60);    addColumnListener(col, new TrackComparator() {      public int compareTrack(Track track0, Track track1) {          return licenseIndex.get(track0).compareTo(licenseIndex.get(track1));      }            });    skinManager.addItem(col, "TrackTable.Heading.License");    skinManager.add(basicSkinable, "TrackTable");        GridData gridData = new GridData();    gridData.horizontalAlignment = GridData.FILL;    gridData.grabExcessHorizontalSpace = true;    gridData.verticalAlignment = GridData.FILL;    gridData.grabExcessVerticalSpace = true;    gridData.horizontalSpan = 3;    table.setLayoutData(gridData);    table.pack();//    This code updates table items as they get selected and unselected. It would be good//    if the background colour for selected items could be predicted however there doesn't//    appear to be an easy way to find this colour.//    //    table.addSelectionListener(new SelectionAdapter() {//      private TableItem[] selection;//      private void update(TableItem[] tableItems) {//        if (tableItems != null)//          for (int i = 0 ; i < tableItems.length; i++) {//            TableItem tableItem = tableItems[i];//            Track track = (Track) hashByTableItem.get(tableItems[i]);//            if (track != null)//              updateTableItem(tableItem, track);//          }//      }//      public void widgetSelected(SelectionEvent e) {//        update(selection);//        selection = table.getSelection();//        update(selection);//      }//    });        DragSource source = new DragSource(table, DND.DROP_COPY);    source.setTransfer(new Transfer[] { FileTransfer.getInstance() });    source.addDragListener(new DragSourceListener() {            /** The track that we're dragging. */      private Track track;            public void dragStart(DragSourceEvent e) {        track = clickedTrack;        e.doit = track != null;      }            public void dragSetData(DragSourceEvent e) {        try {          e.data = new String[] { track.getFile().getAbsoluteFile().getAbsolutePath() };        }        catch (Exception ex) {          ex.printStackTrace();        }      }             public void dragFinished(DragSourceEvent e) {      }    });    table.addMouseListener(new MouseAdapter() {      public void mouseDown(MouseEvent e)       {        int colZeroWidth = table.getColumn(0).getWidth();        int colOneWidth = table.getColumn(1).getWidth();        int colTwoWidth = table.getColumn(2).getWidth();                int colTwoX = colZeroWidth + colOneWidth;                TableItem item = table.getItem(new Point(0, e.y));        if (item == null)          clickedTrack = null;        else          clickedTrack = (Track) hashByTableItem.get(item);          // If the user clicked on the rating column, then bring up the          // pop-up menu.          // NOTE: WIDTH OF RATING ICON IS HARD-CODED HERE!        if (e.x >= colTwoX && e.x < (colTwoX+colTwoWidth) && e.x < (colTwoX+80)) {          if (popupMenu != null && clickedTrack != null) {            menuSelectedTrack = clickedTrack;              // Select and scroll to the selected track.            select(selected, true);              // Put the menu 10 pixels below the mouse position so there is less risk of              // choosing "THIS SUX" accidentally.            popupMenu.popUp(menuSelectedTrack, table.toDisplay(e.x, e.y+10));              // Note: We will now receive a 'widgetSelected' event.  This will call              // select(selected, false) - this will ensure the correct track is              // highlighted, because menuSelectedTrack overrides the 'selected' track.          }        }      }    });    table.addSelectionListener(new SelectionAdapter() {      public void widgetSelected(SelectionEvent e) {          // Prevent the track table from ever having a track other than the          // currently playing one selected by switching back to the currently          // playing one whenever a track is selected.          // (Unless there is a track selected by the pop-up menu.)        if (menuSelectedTrack == null)          select(selected, false);      }    });  }