gt:                 for (int plusminus = 0; plusminus <= 2; plusminus++) {
context: package org.herac.tuxguitar.gui.editors.chord;
  /* Created on 05-March-2007
  */
  
  import java.util.ArrayList;
  
  import org.eclipse.swt.SWT;
  import org.eclipse.swt.events.SelectionAdapter;
  import org.eclipse.swt.events.SelectionEvent;
  import org.eclipse.swt.layout.GridData;
  import org.eclipse.swt.layout.GridLayout;
  import org.eclipse.swt.widgets.Composite;
  import org.eclipse.swt.widgets.List;
  import org.herac.tuxguitar.song.models.TGChord;
  import org.herac.tuxguitar.util.TGSynchronizer;
  
  /**
   * @author Nikola Kolarovic
   * 
   */
  public class ChordRecognizer extends Composite {
  	
  	// index for parameter array
  	protected static final int TONIC_INDEX = 0;
  	protected static final int CHORD_INDEX = 1;
  	protected static final int ALTERATION_INDEX = 2;
  	protected static final int PLUSMINUS_INDEX = 3;
  	protected static final int BASS_INDEX = 4;
  	protected static final int ADDCHK_INDEX = 5;
  	protected static final int I5_INDEX = 6;
  	protected static final int I9_INDEX = 7;
  	protected static final int I11_INDEX = 8;
  	
  	private ChordDialog dialog;
  	private List proposalList;
  	private java.util.List<int[]> proposalParameters;
  	
  	// this var keep a control to running threads.
  	private long runningProcess;
  	
  	public ChordRecognizer(ChordDialog dialog, Composite parent,int style) {
  		super(parent,style);
  		this.setLayout(dialog.gridLayout(1,false,0,0));
  		this.setLayoutData(makeGridData());
  		this.runningProcess = 0;
  		this.dialog = dialog;
  		this.init();
  	}
  	
  	public GridData makeGridData(){
  		GridData data = new GridData(SWT.FILL,SWT.FILL,true,true);
  		data.minimumWidth = 180;
  		return data;
  	}
  	
  	public void init(){
  		Composite composite = new Composite(this,SWT.NONE);
  		composite.setLayout(new GridLayout());
  		composite.setLayoutData(new GridData(SWT.FILL,SWT.FILL,true,true));
  		
  		this.proposalParameters = new ArrayList<int[]>();
  		
  		this.proposalList = new List(composite,SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);
  		this.proposalList.setLayoutData(new GridData(SWT.FILL,SWT.FILL,true,true));
  		this.proposalList.addSelectionListener(new SelectionAdapter() {
  			public void widgetSelected(SelectionEvent e) {
  				if(getDialog().getEditor() != null){
  					showChord(getProposalList().getSelectionIndex());
  				}
  			}
  		});
  		
  	}
  	
  	/** sets the current chord to be selected proposal */
  	protected void showChord(int index) {
  		int[] params = (int[])this.proposalParameters.get(index);
  		this.dialog.getSelector().adjustWidgets(params[TONIC_INDEX],
  		                                        params[CHORD_INDEX],
  		                                        params[ALTERATION_INDEX],
  		                                        params[BASS_INDEX],
  		                                        params[PLUSMINUS_INDEX],
  		                                        params[ADDCHK_INDEX],
  		                                        params[I5_INDEX],
  		                                        params[I9_INDEX],
  		                                        params[I11_INDEX]);
  		String chordName = this.proposalList.getItem(index);
  		chordName = chordName.substring(0, chordName.indexOf('(')-1);
  		this.dialog.getEditor().getChordName().setText(chordName);
  		this.dialog.getEditor().redraw();
  	}
  	
  	/**
  	 * - Recognizes the chord string
  	 * - Fills the component's list with alternative names
  	 * - Sets all the ChordSelector fields into recognized chord (tonic, bass, chord, alterations)
  	 * - Makes the alternatives and puts them into ChordList
  	 * - Writes the chord formula into appropriate label
  	 *  @param chord chord structure (frets, strings)
  	 *  @param redecorate is the Chord Editor in editing mode, or it is just changed by ChordSelector
  	 */
  	
  	public void recognize(final TGChord chord,final boolean redecorate,final boolean setChordName) {
  		
  		final long processId = (++ this.runningProcess);
  		final boolean sharp = this.dialog.getSelector().getSharpButton().getSelection();
  		
  		this.clearProposals();
  		
  		new Thread( new Runnable() {
  			public void run() {
  				if(!getDialog().isDisposed() && isValidProcess(processId)){
  					
  					final int params[] = makeProposals(processId, chord,sharp);
  					
  					if (params == null) { // could not recognize anything!?
  						if (isValidProcess(processId) && setChordName) {
  							try {
  								TGSynchronizer.instance().addRunnable(new TGSynchronizer.TGRunnable() {
  									public void run() {
  										if(!getDialog().isDisposed() && isValidProcess(processId)){
  											getDialog().getEditor().setChordName("");
  										}
  									}
  								});
  							} catch (Throwable e) {
  								e.printStackTrace();
  							}
  						}
  						return;
  					}
  					
  					final String chordName = getChordName(params,sharp);
  					
  					// Sets all the ChordSelector fields into recognized chord (tonic, bass, chord, alterations)
  					if (isValidProcess(processId) && redecorate) {
  						try {
  							TGSynchronizer.instance().addRunnable(new TGSynchronizer.TGRunnable() {
  								public void run() {
  									if(!getDialog().isDisposed()){
  										redecorate(params);
  									}
  								}
  							});
  						} catch (Throwable e) {
  							e.printStackTrace();
  						}
  					}
  					
  					if (isValidProcess(processId) && setChordName) {
  						try {
  							TGSynchronizer.instance().addRunnable(new TGSynchronizer.TGRunnable() {
  								public void run() {
  									if(!getDialog().isDisposed()){
  										getDialog().getEditor().setChordName( (chordName != null ? chordName : "" ) );
  									}
  								}
  							});
  						} catch (Throwable e) {
  							e.printStackTrace();
  						}
  					}
  				}
  			}
  		} ).start();
  	}
  	
  	/** Fills the component's list with alternative names
  	 * @param chord TGChord to be recognized
  	 * @return parameters for adjustWidgets and getChordName methods 
  	 */
  	protected int[] makeProposals(final long processId, TGChord chord,final boolean sharp) {
  		
  		int[] tuning = this.dialog.getSelector().getTuning();
  		java.util.List<Integer> notesInside = new ArrayList<Integer>();
  		
  		// find and put in all the distinct notes
  		for (int i=0; i<tuning.length; i++) {
  			int fret = chord.getStrings()[i];
  			if (fret!=-1) {
  				Integer note = (tuning[tuning.length - 1 - i] + fret) % 12;
  				boolean found=false;
                  for (Integer aNotesInside : notesInside)
                      if (aNotesInside.equals(note))
                          found = true;
  				if (!found)
  					notesInside.add(note);
  			}
  		}
  		
  		// Now search:
  		// go through all the possible tonics
  		// it is required because tonic isn't mandatory in a chord
  		java.util.List<Proposal> allProposals = new ArrayList<Proposal>(10);
  		
  		for (int tonic=0; tonic<12; tonic++) {
  			
  			Proposal currentProp = null;
  			
  			// first check for the basic chord tones
  			for (int chordIndex = 0; chordIndex < ChordDatabase.length(); chordIndex ++) {
  				ChordDatabase.ChordInfo info = ChordDatabase.get(chordIndex);
  				
  				currentProp = new Proposal(notesInside);
  				// it is more unusual the more we go down the index
  				// except chords "5" and "m", they are quite usual :)
  				currentProp.unusualGrade-=(chordIndex!=ChordDatabase.length() && chordIndex!=4 ? 2*chordIndex : 0);
  				
  				//ChordDatabase.ChordInfo info = (ChordDatabase.ChordInfo)chordItr.next();
  				boolean foundNote = false;
  				for (int i=0; i<info.getRequiredNotes().length; i++) { // go through all the requred notes
                      for (Integer aNotesInside : notesInside)
                          if (aNotesInside == (tonic + info.getRequiredNotes()[i] - 1) % 12) {
                              foundNote = true;
                              if (tonic + info.getRequiredNotes()[i] - 1 == tonic)
                                  currentProp.dontHaveGrade += 15; // this means penalty for not having tonic is -65
                              currentProp.foundNote(tonic + info.getRequiredNotes()[i] - 1); // found a note in a chord
                          }
  					
  				}
  				// if something found, add it into a proposal if it's worth
  				if (foundNote) {
  					currentProp.params[TONIC_INDEX] = tonic;
  					currentProp.params[CHORD_INDEX] = chordIndex;//possibleChords.indexOf(info);
  					int foundNotesCount = currentProp.missingNotes.length-currentProp.missingCount;
  					
  					// it is worth if it is missing 1 essential note and/or fifth
  					if (!info.getName().startsWith("dim") && !info.getName().startsWith("aug"))
  						if (!currentProp.isFound(tonic+8-1)) {
  							
  							// hmmm. maybe it's altered fifth? Create a branch for it.
  							if (currentProp.isNeeded(tonic+7-1) || currentProp.isNeeded(tonic+9-1)) {
  								Proposal branchProp = (Proposal)currentProp.clone();
  								if (branchProp.isNeeded(tonic+9-1)) {
  									branchProp.params[I5_INDEX] = 1;
  									branchProp.foundNote(tonic+8);
  								}
  								else {
  									branchProp.params[I5_INDEX] = 2;
  									branchProp.foundNote(tonic+6);
  								}
  								branchProp.unusualGrade-=35;
  								if (foundNotesCount+1>=info.getRequiredNotes().length-1) {
  									branchProp.dontHaveGrade-=(info.getRequiredNotes().length-(foundNotesCount+1))*50;
  									allProposals.add(branchProp);
  								}
  								
  							}
  							else {
  								currentProp.params[I5_INDEX] = 0;
  								currentProp.dontHaveGrade+=30;
  							}
  						}
  					
  					currentProp.params[I5_INDEX] = 0;
  					if (foundNotesCount>=info.getRequiredNotes().length-1 ) {
  							currentProp.dontHaveGrade-=(info.getRequiredNotes().length-foundNotesCount)*50;
  							allProposals.add(currentProp);
  					}
  				}
  				currentProp=null;
  			}
  		}
  		
  		java.util.List<Proposal> unsortedProposals = new ArrayList<Proposal>(5);
          for (Proposal current : allProposals) {
              // place the still missing alterations notes accordingly... bass also
              ///////////////////////////////////////////////////////////////
  
              boolean bassIsOnlyInBass = true;
              // ---------------- bass tone ----------------
              for (int i = chord.getStrings().length - 1; i >= 0; i--) {
                  if (chord.getStrings()[i] != -1) {
                      if (current.params[BASS_INDEX] == -1) {// if we still didn't determine bass
                          current.params[BASS_INDEX] = (tuning[tuning.length - 1 - i] + chord.getStrings()[i]) % 12;
                          if (current.params[BASS_INDEX] != current.params[TONIC_INDEX])
                              current.unusualGrade -= 20;
                      }
                      if (current.params[BASS_INDEX] == (tuning[tuning.length - 1 - i] + chord.getStrings()[i]) % 12)
                          bassIsOnlyInBass = false; // if we stumbled upon bass tone again
                  }
              }
  
              if (current.isNeeded(current.params[BASS_INDEX]) && bassIsOnlyInBass) {
                  // do not mark as FOUND if bass is somewhere other than in bass only
                  current.foundNote(current.params[BASS_INDEX]);
                  current.unusualGrade -= 20;
              }
              // <=11 means "not DIM or AUG or 5"
              if (current.missingCount > 0 && current.params[CHORD_INDEX] <= 11) {
                  // ---------------- alteration tones ----------------
                  // determine seventh -->> 2 is HARDCODED!
                  int seventh;
                  if (current.params[CHORD_INDEX] == 2) seventh = current.params[TONIC_INDEX] + 12 - 1; // plain 7
                  else seventh = current.params[TONIC_INDEX] + 11 - 1; // b7
                  if (current.isExisting(seventh)) {
                      if (!current.isFound(seventh)) {
                          current.filled[3] = true;
                          current.foundNote(seventh);
                      }
                  }
  