/*
 * AlignGui.java
 *
 * ...
 * ...
 * ...
 */

package aksis.alignment;

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.*;
import javax.swing.*;
import javax.swing.text.*;
import java.awt.geom.*;
import java.awt.font.*;
import org.w3c.dom.*;
import java.applet.AudioClip;
import java.nio.charset.*;
import java.util.regex.*;

//import aksis.awt2.AwtUtil;   // Oystein flyttet denne inn sammen med alt det andre. den var sÃ¥ensom der den satt helt for seg selv

/**
 *
 * @author Oystein Reigem and Johan Utne Poppe
 */

class AlignGui extends JPanel {

    // hvor har j dette?
    //public static final int FIRST = 1;
    //public static final int NEXT = 2;
    //public static final int THIRD = 3;
    //public static final String[] whichAsWord = { "", "first", "second", "third" };

    // basic layout is
    //                     FIRST_COL = 0    DO_COL = 1    SECOND_COL = 2
    //                   +---------------+---------------+---------------+
    //                   |  <file_1>     |  <options>    |  <file_2>     |
    // FILE_ROW = 0      |  open/save    |  options      |  open/save    |
    //                   |  buttons      |               |  buttons      |
    //                   +---------------+---------------+---------------+
    //                   |  <aligned_1>  |  <unalign>    |  <aligned_2>  |
    // ALIGNED_ROW = 1   |  aligned      |  unalign      |  aligned      |
    //                   |  elements     |  button       |  elements     |
    //                   +---------------+---------------+---------------+
    //                   |  <work_1>     |  <do>         |  <work_2>     |
    // WORK_ROW = 2      |  elements     |  align & edit |  elements     |
    //                   |  under work   |  buttons      |  under work   |
    //                   +---------------+---------------+---------------+
    //                   |  <change_1>   |               |  <change_2>   |
    // CHANGE_ROW = 3    |  more/less    |               |  more/less    |
    //                   |  buttons      |               |  buttons      |
    //                   +---------------+---------------+---------------+
    //                   |  <unaligned_1>|  <batch>      |  <unaligned_2>|
    // UNALIGNED_ROW = 4 |  unaligned    |  batch align  |  unaligned    |
    //                   |  elements     |  button       |  elements     |
    //                   +---------------+---------------+---------------+
    // STATUS_ROW = 5    |  status line                                  |
    //                   +-----------------------------------------------+
    // (layout is gridbag not so much because we have merged cells but because we need cells of varying sizes)

    // hvor har j dette?
    public static final int FIRST_COL = 0;
    public static final int DO_COL = 1;
    public static final int SECOND_COL = 2;
    public static final int THIRD_COL = 3;   // not used

    //public static final int TEXT_COL_WEIGHT = 1;
    public static final int TEXT_COL_WEIGHT = 2;
    public static final int DO_COL_WEIGHT = 0;   //  hvis det stï¿½ 0 funker ikke MinimumSize
                                                 // har jeg skrevet for lenge siden.
                                                 // 2006-03-23 oppdaget jeg at 0 ordnet problem med bredden pï¿½do-kolonnen.
                                                 // med 1 ble do-kolonnen bredere enn ndvendig
    //public static final int DO_COL_WEIGHT = 1;

    public static final int FILE_ROW = 0;
    public static final int ALIGNED_ROW = 1;
    public static final int WORK_ROW = 2;
    public static final int CHANGE_ROW = 3;
    public static final int UNALIGNED_ROW = 4;
    public static final int STATUS_ROW = 5;
    public static final int FILE_ROW_WEIGHT = 0;
    //public static final int ALIGNED_ROW_WEIGHT = 5;
    public static final int ALIGNED_ROW_WEIGHT = 2;
    //public static final int WORK_ROW_WEIGHT = 3;
    public static final int WORK_ROW_WEIGHT = 0;
    public static final int CHANGE_ROW_WEIGHT = 0;
    //public static final int UNALIGNED_ROW_WEIGHT = 500;
    public static final int UNALIGNED_ROW_WEIGHT = 5;
    public static final int STATUS_ROW_WEIGHT = 0;

    public static final int MIN_DO_WIDTH = 200;
    //public static final int MIN_WORK_HEIGHT = 150;   // ### blir ikke sï¿½mye som 150?
    public static final int MIN_WORK_HEIGHT = 200;

    public static final int[] TEXT_COLS = { FIRST_COL, SECOND_COL, THIRD_COL };   // THIRD_COL not used

    //public static final int NUM_FILES = 2;

    // ...
    //
	private JButton openFileButton[];
	//private JButton saveFileButton[];
	private JButton saveAllFileButton;
	private JButton purgeButton;
	protected JPanel savePurgePanel;
	private JLabel filenameLabel[];
	private JFileChooser chooser;
	//
	//options 
	private JButton anchorFileButton;
	private JLabel anchorFilenameLabel;
	private JLabel settingsFilenameLabel;   // 2006-09-21
	//
	//DefaultListModel alignedModel[];   // package access
	JList alignedListBox[];   // package access
	JScrollPane alignedScrollPane[];   // package access
	//
	private JButton unalignButton;
	//
	//DefaultListModel toAlignModel[];   // package access
	JList toAlignListBox[];   // package access
	JScrollPane toAlignScrollPane[];   // package access
	//
	//protected JCheckBox skip11CheckBox;   // burde vï¿½t private, med get-metode?
	//protected JLabel skip11LimitLabel1;
	//protected JLabel skip11LimitLabel2;
	protected JLabel runLimitLabel1;
	protected JLabel runLimitLabel2;
	//protected JTextField skip11LimitTextField;
	protected JTextField runLimitTextField;
	//protected JPanel skip11Panel;
	//protected JPanel modePanel;
	protected JPanel runPanel;
	protected ModeRadioButtonPanel modeRadioButtonPanel;
	protected JPanel settingsPanel;
	protected JPanel logPanel;
	protected JPanel skipPanel;
	protected JPanel breakPanel;   // 2006-08-15
	protected JButton alignButton;   // triks. "trykker" pï¿½knappen programmatisk, fra model
	//private JButton editButton;   // for text editing. and element editing?????
	private JButton settingsButton;   // brings up dialog for various settings
	//private JButton logButton;   // turns logging on or off
	private JButton startLoggingButton;
	private JButton stopLoggingButton;
	private JButton breakButton;   // 2006-08-15
	private JLabel logFilenameLabel;
	private JButton skipButton;   // button for use when opening half-aligned files. to skip the already aligned beginning of the files
	//private JButton changeButton;   // test
	//private JButton linkButton;  // for detailed editing of correspondences
	//&&//private JButton correspButton;  // for detailed editing of correspondences
	//private JLabel alignArrow;
	//
	//protected JPanel compareInfoPanel;
	protected CompareInfo compareInfoPanel;
	private JScrollPane compareInfoScrollPane;
	protected Graphics compareInfoGraphics;
	//private JTextArea anchorWordMatches;
	//private JTextArea matchInfoTextArea;
	protected JList matchInfoList;
	//private JScrollPane anchorWordMatchesScrollPane;
	private JScrollPane matchInfoScrollPane;
	//JTextArea anchorWordMatches;   // component for display of the current anchor word matches   // package access
	//JList anchorWordMatchesListBox;   // component for display of the current anchor word matches   // package access
	//
	private JButton moreButton[];
	private JButton lessButton[];
	//private JLabel moreLessArrow[];
	//
	//DefaultListModel unalignedModel[];   // package access
	JList unalignedListBox[];   // package access
	JScrollPane unalignedScrollPane[];   // package access
	//
	//private JButton batchButton;  //  kan vi srge for at knappen fï¿½ en tekst som sier hvor mange linjer den vil ta???
	private JButton suggestButton;

	////  burde vï¿½t private, med set-metoder? skal jeg lage et statuslinjeobjekt?
	//protected JTextField counter;
	////protected javax.swing.text.Document counterDoc;
	protected AlignStatusLine statusLine;

	// arrays of all the components lying in the same row.
	// for resizing of rows
	protected Component[] row2, row3, row5;
	protected double row2weighty, row5weighty;

	JMenuBar menuBar;   // package access

	// mitt
    protected OpenAction[]
    	openActions;
    /*protected SaveAction[]
    	saveActions;*/
    protected SaveAllAction
    	saveAllAction;
    protected PurgeAction
    	purgeAction;
    protected AnchorAction
    	anchorAction;
    protected UnalignAction
    	unalignAction;
    protected AlignAction
    	alignAction;
    //protected EditAction
    //	editAction;
    protected SettingsAction
    	settingsAction;
    //protected LogAction
    //	logAction;
    protected StartLoggingAction
    	startLoggingAction;
    protected StopLoggingAction
    	stopLoggingAction;
    protected SkipCorrespAction
    	skipCorrespAction;
    protected BreakAction   // 2006-08-15
    	breakAction;
    //protected ChangeAction
    //	changeAction;
    //protected LinkAction
    //	linkAction;
    //&&//protected CorrespAction
    //&&//	correspAction;
    protected MoreAction[]
    	moreActions;
    protected LessAction[]
    	lessActions;
    //protected BatchAction
    //	batchAction;
    protected SuggestAction
    	suggestAction;
    protected HelpAction
    	helpAction;   // 
    protected ToolTipAction
    	toolTipAction;   // 

    // j
    AlignmentModel model;    // package access

    GridBagLayout layout;    // package access

    private AnchorDialog anchorDialog;

    private SettingsDialog settingsDialog;

	//############ skulle class modeRadioButtonPanel ogsï¿½vï¿½t her?

    //&&//// dialog for manually editing correspondences/links
    //&&//private CorrespDialog correspDialog;

    // mitt

	// <http://java.sun.com/developer/technicalArticles/InnerWorkings/customjlist/>
	//
	// Here's an example of a class that models the items in a list.
	// The class encapsulates the background color and text.
	//
	// ... -> AElement
	// String -> Object

	// forts.
	//
	// Here's an example of a class that implements the ListCellRenderer interface.
	//
	// Notice a few things about MyCellRenderer:
	//
	// It extends JLabel, another JFC Project Swing component.
	// JLabel is used to display text or images.
	// Extending JLabel is a convenient way to display selectable text or images.
	//
	// It sets opaque to true in the constructor.
	// This instructs the paint system to use the background of that particular component.
	//
	// It implements getListCellRendererComponent,
	// the only method in the ListCellRenderer interface.
	// This method sets the attributes of the class
	// and then returns a reference to the class.
	//
	// The setText method uses the string value stored
	// in the AElement object to set the JLabel text,
	// and the setBackground method uses the color value stored
	// in the AElement object to set the background color of the JLabel.
	//
	// If the list item is selected, that is the iss parameter
	// of getListCellRendererComponent is true,
	// MyCellRenderer uses the setBorder method to set
	// a two-pixel blue border around the list item.
	// The border around the item signals that the item is selected
	//
	// ... -> AElement
	// etc
	//
	// The customization possibilities don't end here.
	// By having the MyCellRenderer class extend a component other than JLabel,
	// you can create a wide variety of visually engaging lists.

	//class MyCellRenderer extends JLabel implements ListCellRenderer {   // ===
	class MyCellRenderer extends JTextArea implements ListCellRenderer {   // ===
	//class MyCellRenderer extends JTextPane implements ListCellRenderer {
	//class MyCellRenderer extends JTextField implements ListCellRenderer {

		public MyCellRenderer () {
			// Don't paint behind the component
			setOpaque(true);
		}

		// Set the attributes of the
		// class and return a reference
		public Component getListCellRendererComponent(
			JList list,
			Object value, // value to display
			int index,    // cell index
			boolean iss,  // is selected
			boolean chf)  // cell has focus?
		{

			// Set the text and
			// background color for rendering
			////System.out.println("value har klasse " + value.getClass().getName());
			//AElement test = (AElement)value; //  java.lang.ClassCastException. men prver det pï¿½nytt. hmm. problemer i aligned, men ikke i toAlign!
			//AElement temp = new AElement(value); //  men fï¿½ det til pï¿½denne mï¿½en. ok?
			////System.out.println(temp);
			//Object test = value;
			//setText(((AElement)(Object)value).getValue().toString());
			//setText(test.element.toString());
			String text = ((AElement)(value)).toString();
			//### flgende test gir litt merkelig resultat.
			// hyden er nemlig gjerne basert pï¿½et annet innhold enn du ser,
			// fordi denne metoden stadig trigges til ï¿½regne pï¿½nytt
			//text = "abcde".substring(0, (int)(5 * Math.random() + 1));   // #######test 2006-09-19
			//text = "abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc abc x";   // #######test 2006-09-19

			/* ###didn't help. LineBreakMeasurer deler alle mulige steder: " ' .
			// 2006-9-15
			// ###replace all " by ' because of a bug in LineBreakMeasurer
			//System.out.println("3");
			Pattern pattern = Pattern.compile("\"");
			Matcher matcher = pattern.matcher(text);
			//text = matcher.replaceAll("'");
			text = matcher.replaceAll("'");
			// end 2006-9-15
			*/

			//String escapedText = "<html><![CDATA[" + text + "]]></html>";   // === escape. ###nei, dette skjnner visst ikke JLabel. kodene og ]]> viser
			//String escapedText = "<html>" + Utils.stringToHTMLString(text) + "</html>";   // if extends JLabel
			setText(text);   // if extends JTextArea
			//setText(escapedText);   // if extends JLabel
			//setBackground(((AElement)value).getColor());
			//setBackground(test.getColor());
			setBackground(((AElement)(value)).getColor());
			//  Wrap-greier funker ikke. eneste virkning at horiz scroll forsvant.
			// aha. er det wrappet, men sï¿½ser vi bare frste linjen?
			//  prvde for sikkerhets skyld alle kombinasjoner av de to.
			// ### hjalp ikke ï¿½flytte dette foran setText etc.
			//setLineWrap(false); ### hjalp ikke ï¿½riste i det
			setLineWrap(true);   // if extends JTextArea
			setWrapStyleWord(true);   // if extends JTextArea
			//setWrapStyleWord(false);
			//...
			// 
			//System.out.println("width=" + getScrollableTracksViewportWidth()); printer false hvis wrapping pï¿½lï¿½t og true ellers

			// Set a border if the
			// list item is selected
			if (iss) {
				setBorder(BorderFactory.createLineBorder(Color.blue, 1));   // 1 = width of border in pixels
			} else {
				setBorder(BorderFactory.createLineBorder(list.getBackground(), 1));   // 1 = width of border in pixels
			}

			//int rowHeight = (int)getPreferredSize().getHeight();
			//if (list.getHeight() != rowHeight) table.setHeight(rowHeight);
			//System.out.println("(int)getPreferredSize().getHeight() = " + (int)getPreferredSize().getHeight());
			//System.out.println("getHeight() = " + getHeight());   ### 0
			//System.out.println("list.getFixedCellWidth() = " + list.getFixedCellWidth());   // ### -1
			//System.out.println("getFixedCellHeight() = " + getFixedCellHeight());

			//System.out.println("list.getWidth()=" + list.getWidth());
			//System.out.println("getWidth()=" + getWidth());   ### 0

			//list.revalidate();   // ### hjelper ikke. fï¿½ ikke resizet cellene. men dette skulle vel ikke stï¿½t akkurat her heller

			//if (false) {   // ###for ï¿½kjre uten word wrap
				//System.out.println("fr getGraphics()");
				//Graphics2D gg = (Graphics2D)list.getGraphics();   // ###dette er vel feil for JTextArea i hvert fall! mï¿½vel fï¿½graphics fra cellen, ikke listen
				// use font from list for cell    // 2006-09-19
				setFont(list.getFont());    // 2006-09-19
				//System.out.println("etter getGraphics()");
				Graphics2D gg = (Graphics2D)getGraphics();    // 2006-09-19   // for extends JLabel. and JTextArea???
				if (gg != null) {   // for extends JLabel. and JTextArea???
					//System.out.println("this.getWidth()=" + this.getWidth());   // 0
					//System.out.println("list.getWidth()=" + list.getWidth());
					setSize(new Dimension(list.getWidth() - 30, 0));   // 2006-09-19
					//System.out.println("gg != null");
					//Font font = gg.getFont();
					/* 2006-09-15. dette er vel foreldet for en stund siden
					FontRenderContext frc = gg.getFontRenderContext();
					Rectangle2D textBounds = font.getStringBounds(text, frc);  // (original text, not escaped)
					int textWidth = (int)textBounds.getWidth();
					*/
					// 2006-03-24. there seems to be a bug in font.getStringBounds(text, frc).getWidth()
					// if the text contains e.g the &mdash; character the height is returned as 3 instead of 15
					//int textHeight = (int)textBounds.getHeight();
					//Rectangle2D textBounds2 = font.getStringBounds("XXX", frc); <<<===
					//int textHeight = (int)textBounds2.getHeight(); <<<===
					// now that was clunky...
					//int numLines = (int)(textWidth / list.getWidth()) + 1;   // ### altfor primitivt. hvordan kan vi finne textrect <<<===
					//  getWidth() returnerer forskjellige verdier!!!!!
					// 2006-09-15. bï¿½e riktig verdi og lavere enn riktig verdi.
					// det er vel noe med at det beregnes ut fra innholdet.
					// men innholdet er jo det som vi nsker ï¿½....
					// ###og verdien er forresten aldri riktig, for det er ikke trukket fra for scrollbar!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
					// ###ah! det hjelper ï¿½sette vertical scrollbar policy always! da blir det rett verdi, og samme verdi alltid
					//int listWidth = (int)list.getWidth();
					//System.out.println("listWidth = " + listWidth);
					//int viewportWidth = (int)list.getPreferredScrollableViewportSize().getWidth();
					//System.out.println("gg != null");
					//setRows(numLines);
					// ### 30: hack for ï¿½trekke fra plass til vert scrollbar.
					// +1: ser at det blir 1 pixel luft mellom linjene i tillegg til det getHeight() sier.
					// +5: for ï¿½fï¿½nok luft nede. blir nï¿½4 oppe og 4 nede
					//setPreferredSize(new Dimension(listWidth - 30, ((textHeight + 1) * numLines) + 5));   // ### listWidth may change from line to line. should have used a fixed value
					//int h = ((textHeight + 1) * numLines) + 5; <<<===
					//int h = Utils.wrappedTextHeight(text, font, list.getWidth());   // 2006-08-15 <<<==============PRï¿½ DENNE
					//int h = Utils.wrappedTextHeight(" " + text, font, list.getWidth() - 6);   // 2006-09-15 ###forbannet triks. JLabel, som er den som gjr linjebrettingen, rykker visst inn frste linje ï¿½ pixel. simulerer dette med en space foran teksten. ###men dette var ikke nok. prver ogsï¿½med mindre bredde
					//int h = Utils.wrappedTextHeight(" " + text, gg, list.getWidth());   // 2006-09-15
					// 2006-09-18. prvde JTextArea igjen. wrapper ok.
					// men cellen blir forferdelig hy hvis ikke noe setter hyden
					// men for lav hvis jeg bruker Utils.wrappedTextHeight().
					// og _formodentlig_ med samme bug i brekkingen ("'.)
					//int h = Utils.wrappedTextHeight(text, gg, list.getWidth());   // 2006-09-15   // for extends JLabel
					//setPreferredSize(new Dimension(0, h));   //  width 0 seems to disturb width less   // for extends JLabel
					//setVerticalAlignment(SwingConstants.TOP);   // if extends JLabel
					// ### 30 funker ikke. ingen forskjell om ker til 100 eller 200.
					// ### og ingen forskjell om setMaximumSize i tillegg
					//setMaximumSize(new Dimension(listWidth - 30, ((textHeight + 1) * numLines) + 5));   // ### hjelper ikke
					//setSize(new Dimension(list.getWidth() - 30, textHeight * numLines));   // ### gï¿½ ikke bedre med setSize enn setPreferredSize
					//setPreferredSize(new Dimension(getWidth() - 30, textHeight * numLines));   // ### getWidth() er 0

					/*
					if (index < 250) {
						System.out.println("----------------");
						System.out.println("index = " + index);
						//System.out.println("font = " + font);
						System.out.println("text = " + text);
						//System.out.println("textBounds = " + textBounds);
						System.out.println("textWidth = " + textWidth + ", textHeight = " + textHeight);
						System.out.println("numLines = " + numLines);
						System.out.println("setPreferredSize 0, " + h);
					}
					*/
				}   // for extends JLabel. and JTextArea???
			//}

			//layout.layoutContainer(this);   // ### hjelper ikke. fï¿½ ikke resizet cellene. kommenterer den ut igjen i tilfelle den tar ressurser

			return this;

		}

	}

	// mitt

	// hvor skal denne?
	/** Returns an ImageIcon, or null if the path was invalid. */
	protected static ImageIcon createImageIcon(String path, String description) {
		java.net.URL imgURL = AlignGui.class.getResource(path);
		if (imgURL != null) {
			return new ImageIcon(imgURL, description);
		} else {
			//System.err.println("Couldn't find file: " + path);
			return null;
		}
	}

	// hvor skal denne?
	private int getWhich(String command) throws MyException {
        for (int t=0; t<Alignment.NUM_FILES; t++) {
			if (command.indexOf(Integer.toString(t+1)) != -1) {
				return t;   // the action command contains the number ... . assume the command is about file ... 
			}
		}
		throw new MyException();
	}

	// hvor skal denne? har laget denne etter en AwtUtil-metode getTopFrame for johan
    public static JFrame getTopJFrame(Component c) {
		//System.out.println(c);
        while (!(c instanceof JFrame) && c != null) {
            c = c.getParent();
            //System.out.println(c);
        }
        return (JFrame)c;
    }

	// hvor skal denne?
	// create the menu bar
	private JMenuBar createMenu(OpenAction[] openActions,
	                            //SaveAction[] saveActions,
	                            SaveAllAction saveAllAction,
	                            PurgeAction purgeAction,
	                            UnalignAction unalignAction,
	                            AnchorAction anchorAction,
	                            AlignAction alignAction,
	                            //EditAction editAction,
	                            SettingsAction settingsAction,
	                            //LogAction logAction,
	                            StartLoggingAction startLoggingAction,
	                            StopLoggingAction stopLoggingAction,
	                            SkipCorrespAction skipCorrespAction,
	                            BreakAction breakAction,   // 2006-08-15
	                            //ChangeAction changeAction,
	                            //&&//CorrespAction correspAction,
	                            //LinkAction linkAction,
	                            MoreAction[] moreActions,
	                            LessAction[] lessActions,
	                            //BatchAction batchAction,
	                            SuggestAction suggestAction,
	                            HelpAction helpAction,
	                            ToolTipAction toolTipAction) {

		JMenuBar mb = new JMenuBar();

		JMenu file = new JMenu("File");
		mb.add(file);
		for (int t=0; t<Alignment.NUM_FILES; t++) {
			file.add(openActions[t]);
		}
		/*for (int t=0; t<Alignment.NUM_FILES; t++) {
			file.add(saveActions[t]);
		}*/
		file.add(saveAllAction);
		file.add(purgeAction);

		JMenu edit = new JMenu("Edit");
		mb.add(edit);
		for (int t=0; t<Alignment.NUM_FILES; t++) {
			edit.add(moreActions[t]);
			edit.add(lessActions[t]);
		}
		edit.add(unalignAction);
		edit.add(alignAction);
		edit.add(suggestAction);

		JMenu help = new JMenu("Help");
		mb.add(help);
		help.add(helpAction);
		JCheckBoxMenuItem menuItem = new JCheckBoxMenuItem(toolTipAction);
		help.add(menuItem);   // JCheckBoxMenuItem() creates a menu item whose properties are taken from the Action supplied
		ToolTipManager.sharedInstance().setEnabled(false);   // ### uelegant?
		menuItem.setState(false);
		////System.out.println("har laget menu bar" + mb);

		return mb;

	}

	public AudioClip sound;   // ################


	public abstract class MyAbstractAction extends AbstractAction {
		//public MyAbstractAction(String text, ImageIcon icon, String desc, Integer mnemonic) {
		//public MyAbstractAction(String text, ImageIcon icon, String desc, String accelerator, Integer mnemonic) {
		//public MyAbstractAction(String text, ImageIcon icon, String desc, Integer accelerator, Integer mnemonic) {
		public MyAbstractAction(String text, ImageIcon icon, String desc, KeyStroke accelerator, Integer mnemonic) {
			super(text, icon);
			putValue(SHORT_DESCRIPTION, desc);
			putValue(ACCELERATOR_KEY, accelerator);
			putValue(MNEMONIC_KEY, mnemonic);   // alt+...
		}
	}

	public class OpenAction extends MyAbstractAction {
		//public OpenAction(String text, ImageIcon icon, String desc, Integer mnemonic) {
		public OpenAction(String text, ImageIcon icon, String desc, KeyStroke accelerator, Integer mnemonic) {
			//super(text, icon, desc, mnemonic);
			super(text, icon, desc, accelerator, mnemonic);
		}
		public void actionPerformed(ActionEvent e) {

			//  gjentas mange ganger
			AlignGui.this.statusLine.clear();

			//  gjentas mange ganger. skill ut i funk? eller kan dette gjres helt om pï¿½
			int t;
			String command = e.getActionCommand();
			////System.out.println("command er " + command);
			// the command contains a '1' or '2'
			// t is 0 or 1 and tells if this action regards file 1 or file 2
			try {
				t = getWhich(command);
			} catch (MyException ex) {
				//System.err.println("Program error. Can't determine which file to open");
				//System.err.println("command is '" + command + "'");
				ErrorMessage.programError("Can't determine which file to open. command is '" + command + "'");   // 2006-08-10
				return;
			}

			// check if a file has already been read in

			if (model.docs[t] == null) {

				// no

				chooser = new JFileChooser();
				chooser.setApproveButtonText("Open file " + (t+1));  // fikk null fra chooser.getApproveButtonText(). resultat: "null file 1"
				if (model.currentOpenDirectory != null) {
					chooser.setCurrentDirectory(model.currentOpenDirectory);
				} else {
					chooser.setCurrentDirectory(null);
				}
				int returnVal = chooser.showOpenDialog(AlignGui.this);   // arg fï¿½ dialog til ï¿½ligge sentrert over gui. hvis null havner dialog i senter av skjerm
				if(returnVal == JFileChooser.APPROVE_OPTION) {
					////System.out.println("chooser.getSelectedFile() = " + chooser.getSelectedFile());

			        try {   // 2006-09-19
			            model.loadFile(AlignGui.this, chooser.getSelectedFile(), t);
					//} catch (EmptyElementException ex2) {   // 2006-09-19
					} catch (Exception ex2) {   // 2006-09-22
						//ErrorMessage.error("Error. The text contains an empty alignable element.\n\n(You might need to restart the program when this error occurs)");   // 2006-09-19
						ErrorMessage.error("Error. The text contains an empty alignable element:\n\n" + ex2.getMessage() + "\n\n\n(Note that the element might be differently formatted in the input file.\nAlso you might need to restart the program when this error occurs)");   // 2006-09-19 2006-09-22
					}   // 2006-09-19

					filenameLabel[t].setText(chooser.getSelectedFile().getName());
					model.currentOpenDirectory = chooser.getCurrentDirectory();
				////} else {
				////	System.out.println("cancel");
				}

			} else {

				// yes.
				// can't read in new file

				//  should be a message here too
				Toolkit.getDefaultToolkit().beep();
				//System.out.println("BEEEEEEEEEEEEEEEEP OpenAction");
				System.out.println("Can't read in new file. Not implemented");

			}

		}
	}

	/*public class SaveAction extends MyAbstractAction {
		public SaveAction(String text, ImageIcon icon, String desc, KeyStroke accelerator, Integer mnemonic) {
			super(text, icon, desc, accelerator, mnemonic);
		}
		public void actionPerformed(ActionEvent e) {

			// ### midlertidig satt ut av spill. bruk save all-knappen
			Toolkit.getDefaultToolkit().beep();
			System.out.println("Not working. Use Save All button instead");
			if (true) { return; }

			//  gjentas mange ganger
			AlignGui.this.statusLine.clear();

			int t;
			String command = e.getActionCommand();
			// the command contains a '1' or '2'
			// t is 0 or 1 and tells if this action regards file 1 or file 2
			try {
				t = getWhich(command);
			} catch (MyException ex) {
				System.err.println("Program error. Can't determine which file to save");
				System.err.println("command is '" + command + "'");
				return;
			}

			chooser = new JFileChooser();
			chooser.setApproveButtonText("Save file " + (t+1));  // har ikke prvd dette. det stï¿½ en komm i tilsv sted for open
			if (model.currentSaveDirectory != null) {
				chooser.setCurrentDirectory(model.currentSaveDirectory);
			} else if (model.currentOpenDirectory != null) {
				chooser.setCurrentDirectory(model.currentOpenDirectory);
			} else {
				chooser.setCurrentDirectory(null);
			}
			int returnVal = chooser.showSaveDialog(AlignGui.this);   // vil helst ha en fornuftig parent, men
			if (returnVal == JFileChooser.APPROVE_OPTION) {
				//AlignGui.this.model.saveFile(chooser.getSelectedFile(), t);
				//AlignGui.this.model.saveCorrespFormatFile(chooser.getSelectedFile(), t);
				AlignGui.this.model.saveCorrespFormatFile(chooser.getSelectedFile(), t, AlignGui.this.model.getCharset(t));
				model.currentSaveDirectory = chooser.getCurrentDirectory();
			}

		}
	}*/

	public class SaveAllAction extends MyAbstractAction {
		public SaveAllAction(String text, ImageIcon icon, String desc, KeyStroke accelerator, Integer mnemonic) {
			super(text, icon, desc, accelerator, mnemonic);
		}
		public void actionPerformed(ActionEvent e) {

			//  gjentas mange ganger
			AlignGui.this.statusLine.clear();

			// establish corresp attributes in dom for all texts.
			// methods for saving in "corresp" and "external" formats depend on this
			for (int t=0; t<Alignment.NUM_FILES; t++) {
				AlignGui.this.model.setCorrespAttributes(t);
			}

			File tempPath;
			String outputFilenameSuggestion;
			File outputFilepathSuggestion;
			int returnVal;

			// save in "external" format

			// the basis for the suggestion is the input file paths
			outputFilenameSuggestion = "";
			for (int t=0; t<Alignment.NUM_FILES; t++) {
				tempPath = new File(AlignGui.this.model.inputFilepath[t]);
				// but the suggestion must obey the current directory for saving files,
				// so we need just the file names, without the extension.
				// we string them together with an underscore between them
				String tempFilename = tempPath.getName();
				if (outputFilenameSuggestion != "") {
					outputFilenameSuggestion += "_";
				}
				outputFilenameSuggestion += ExtensionUtils.getFilenameWithoutExtension(tempFilename);
			}
			// finally add extension
			outputFilenameSuggestion += ".xml";

			// the suggestion must obey the current directory for saving files// ##########chooser? men er den satt, da?
			outputFilepathSuggestion = new File(chooser.getCurrentDirectory(), outputFilenameSuggestion);

			// dialog
			chooser.setSelectedFile(outputFilepathSuggestion);
			returnVal = chooser.showSaveDialog(AlignGui.this);   // vil helst ha en fornuftig parent, men
			if (returnVal == JFileChooser.APPROVE_OPTION) {
				// save in "external" format
				AlignGui.this.model.saveExternalFormatFile(chooser.getSelectedFile());
				model.currentSaveDirectory = chooser.getCurrentDirectory();
			}

			for (int t=0; t<Alignment.NUM_FILES; t++) {

				// the basis for the suggestion is the input file path
				tempPath = new File(AlignGui.this.model.inputFilepath[t]);
				// but the suggestion must obey the current directory for saving files,
				// so we need just the file name
				String tempFilename = tempPath.getName();

				for (int fi=0; fi<2; fi++) {

					chooser = new JFileChooser();

					String approveButtonText = "Save file " + (t+1);
					if (fi == 0) {
						// save in corresp format
						approveButtonText += " in corresp format";
					//} else {
					} else if (fi == 1) {
						// save in newline format
						approveButtonText += " in newline format";
					} else {
						// save in "external" format
						approveButtonText += " in 'external' format";
					}
					chooser.setApproveButtonText(approveButtonText);   // ### funker ikke. merkelig. funker nemlig i de individuelle save-knappene. funker ikke her, selv om jeg endrer til samme tekst som i de individuelle. eneste forskjell er at denne har en setSelectedFile(). hjalp ikke ï¿½ta den bort

					if (model.currentSaveDirectory != null) {
						chooser.setCurrentDirectory(model.currentSaveDirectory);
					} else if (model.currentOpenDirectory != null) {
						chooser.setCurrentDirectory(model.currentOpenDirectory);
					} else {
						chooser.setCurrentDirectory(null);
					}

					if (fi == 0) {
						// save in corresp format
						/*
						if (t == 0) {
						*/
							/*// which output file naming method?
							if (AlignGui.this.model.getOutputFileNamingMethod() == 1) {
								// output file naming method = change extension
								outputFilenameSuggestion = ExtensionUtils.changeExtension(tempFilename, AlignGui.this.model.getFileNamingCorrespExtension());   // ### 
							} else {
								// output file naming method = keep extension, append suffix to name
								outputFilenameSuggestion = ExtensionUtils.appendName(tempFilename, AlignGui.this.model.getFileNamingCorrespSuffix());   // ### 
							}
							*/
							outputFilenameSuggestion = ExtensionUtils.appendName(tempFilename, "_cor");   // ###  ##########################
						/*
						} else {
							// which output file naming method?
							if (AlignGui.this.model.getOutputFileNamingMethod() == 1) {
								// output file naming method = change extension
								outputFilenameSuggestion = ExtensionUtils.changeExtension(tempFilename, AlignGui.this.model.getFileNamingCorrespExtension());   // ### 
							} else {
								// output file naming method = keep extension, append suffix to name
								outputFilenameSuggestion = ExtensionUtils.appendName(tempFilename, AlignGui.this.model.getFileNamingCorrespSuffix());   // ### 
							}
						}
						*/
					} else {
						// save in newline format
						/*
						if (t == 0) {
						*/
							/*
							// which output file naming method?
							if (AlignGui.this.model.getOutputFileNamingMethod() == 1) {
								// output file naming method = change extension
								outputFilenameSuggestion = ExtensionUtils.changeExtension(tempFilename, AlignGui.this.model.getFileNamingNewlineExtension());   // ### 
							} else {
								// output file naming method = keep extension, append to name
								outputFilenameSuggestion = ExtensionUtils.appendName(tempFilename, AlignGui.this.model.getFileNamingNewlineSuffix());   // ### 
							}
							*/
							outputFilenameSuggestion = ExtensionUtils.changeExtension(ExtensionUtils.appendName(tempFilename, "_new"), "txt");   // ###  ###########
						/*
						} else {
							// which output file naming method?
							if (AlignGui.this.model.getOutputFileNamingMethod() == 1) {
								// output file naming method = change extension
								outputFilenameSuggestion = ExtensionUtils.changeExtension(tempFilename, AlignGui.this.model.getFileNamingNewlineExtension());   // ### 
							} else {
								// output file naming method = keep extension, append to name
								outputFilenameSuggestion = ExtensionUtils.appendName(tempFilename, AlignGui.this.model.getFileNamingNewlineSuffix());   // ### 
							}
						}
						*/
					}

					// the suggestion must obey the current directory for saving files
					outputFilepathSuggestion = new File(chooser.getCurrentDirectory(), outputFilenameSuggestion);

					// dialog
					chooser.setSelectedFile(outputFilepathSuggestion);
					returnVal = chooser.showSaveDialog(AlignGui.this);   // vil helst ha en fornuftig parent, men
					if (returnVal == JFileChooser.APPROVE_OPTION) {
						if (fi == 0) {
							// save in corresp format
							//AlignGui.this.model.saveCorrespFormatFile(chooser.getSelectedFile(), t);
							AlignGui.this.model.saveCorrespFormatFile(chooser.getSelectedFile(), t, AlignGui.this.model.getCharset(t));
						} else {
							// save in newline format
							//AlignGui.this.model.saveNewlineFormatFile(chooser.getSelectedFile(), t);
							// ###note! the saveNewlineFormatFile() method
							// clears all corresp attributes in the dom for the current text!
							// so newline format saving must be done last
							AlignGui.this.model.saveNewlineFormatFile(chooser.getSelectedFile(), t, AlignGui.this.model.getCharset(t), AlignGui.this.model.getAncestorFilter());
						}
						model.currentSaveDirectory = chooser.getCurrentDirectory();
					}

				} // for fi

			} // for t

		}
	}

	public class PurgeAction extends MyAbstractAction {

		public PurgeAction(String text, ImageIcon icon, String desc, KeyStroke accelerator, Integer mnemonic) {
			super(text, icon, desc, accelerator, mnemonic);
		}
		public void actionPerformed(ActionEvent e){

			//  gjentas mange ganger
			AlignGui.this.statusLine.clear();

			//... ... ...

			//System.out.println("purge/clear ikke implementert");
			//Toolkit.getDefaultToolkit().beep();
			//JOptionPane.showMessageDialog(null, "Clear all data - not implemented", "Not implemented", JOptionPane.INFORMATION_MESSAGE);

			AlignGui.this.model.purge(AlignGui.this);

		}
	}

	public class AnchorAction extends MyAbstractAction {
		public AnchorAction(String text, ImageIcon icon, String desc, KeyStroke accelerator, Integer mnemonic) {
			super(text, icon, desc, accelerator, mnemonic);
		}
		public void actionPerformed(ActionEvent e){

			//  gjentas mange ganger
			AlignGui.this.statusLine.clear();

			//System.out.println("skal ta opp ankerdialogen");
			//System.out.println("antall entries i ankerordlisten = " + AlignGui.this.model.anchorWordList.entries.size());
			//anchorDialog = new AnchorDialog(null, AlignGui.this.model);
			//anchorDialog = new AnchorDialog(null, AlignGui.this.model, -1);
			anchorDialog = new AnchorDialog(null, AlignGui.this, -1);
			anchorDialog.setLocationRelativeTo(AlignGui.this);
			//anchorDialog.setLocationRelativeTo(anchorButton);   //  funker ogsï¿½
			//anchorDialog.show();   // Deprecated
			anchorDialog.setVisible(true);
			if (anchorDialog.approved) {
				// reset compare stuff (info about elements in each text and how elements combine).
				// necessary to reset because info is based on old version of anchor words
				AlignGui.this.model.compare = new Compare();
			} else {
				//System.out.println("cancel");
				//anchorFilenameLabel.setText("");   // ### old value should be left alone
			}

		}
	}

	public class MoreAction extends MyAbstractAction {
		public MoreAction(String text, ImageIcon icon, String desc, KeyStroke accelerator, Integer mnemonic) {
			super(text, icon, desc, accelerator, mnemonic);
		}
		public void actionPerformed(ActionEvent e){

			//  gjentas mange ganger
			AlignGui.this.statusLine.clear();

			int t;
			String command = e.getActionCommand();
			// the command contains a '1' or '2'
			// t is 0 or 1 and tells if this action regards file 1 or file 2
			try {
				t = getWhich(command);
			} catch (MyException ex) {
				//System.err.println("Program error. Can't determine which text you're working on");
				//System.err.println("command is '" + command + "'");
				ErrorMessage.programError("Can't determine which text you're working on. command is '" + command + "'");   // 2006-08-10
				return;
			}

			model.more(AlignGui.this, t);
			//model.more(t);

		}
	}

	public class LessAction extends MyAbstractAction {
		public LessAction(String text, ImageIcon icon, String desc, KeyStroke accelerator, Integer mnemonic) {
			super(text, icon, desc, accelerator, mnemonic);
		}
		public void actionPerformed(ActionEvent e) {

			//  gjentas mange ganger
			AlignGui.this.statusLine.clear();

			int t;
			String command = e.getActionCommand();
			// the command contains a '1' or '2'
			// t is 0 or 1 and tells if this action regards file 1 or file 2
			try {
				t = getWhich(command);
			} catch (MyException ex) {
				//System.err.println("Program error. Can't determine which text you're working on");
				//System.err.println("command is '" + command + "'");
				ErrorMessage.programError("Can't determine which text you're working on. command is '" + command + "'");   // 2006-08-10
				return;
			}

			//model.less(AlignGui.this, t);
			////System.out.println("calling model.less()");
			model.less(AlignGui.this, t);
			//model.less(t);

		}
	}

	public class AlignAction extends MyAbstractAction {
		public AlignAction(String text, ImageIcon icon, String desc, KeyStroke accelerator, Integer mnemonic) {
			super(text, icon, desc, accelerator, mnemonic);
		}
		public void actionPerformed(ActionEvent e) {

			//  gjentas mange ganger
			AlignGui.this.statusLine.clear();

			model.align(AlignGui.this, true);   // true = scroll aligned

		}
	}

	public class UnalignAction extends MyAbstractAction {
		public UnalignAction(String text, ImageIcon icon, String desc, KeyStroke accelerator, Integer mnemonic) {
			super(text, icon, desc, accelerator, mnemonic);
		}
		public void actionPerformed(ActionEvent e) {

			//  gjentas mange ganger
			AlignGui.this.statusLine.clear();

			model.unalign(AlignGui.this);
			//model.unalign();

		}
	}

	/*public class EditAction extends MyAbstractAction {
		public EditAction(String text, ImageIcon icon, String desc, KeyStroke accelerator, Integer mnemonic) {
			super(text, icon, desc, accelerator, mnemonic);
		}
		public void actionPerformed(ActionEvent e) {
			//  gjentas mange ganger
			AlignGui.this.statusLine.clear();

			JOptionPane.showMessageDialog(null, "This is action " + e.paramString(), "Title", JOptionPane.INFORMATION_MESSAGE);
		}
	}*/

	public class SettingsAction extends MyAbstractAction {
		public SettingsAction(String text, ImageIcon icon, String desc, KeyStroke accelerator, Integer mnemonic) {
			super(text, icon, desc, accelerator, mnemonic);
		}
		public void actionPerformed(ActionEvent e) {

			//  gjentas mange ganger
			AlignGui.this.statusLine.clear();

			//System.out.println("skal ta opp settingdialogen");
			//settingsDialog = new SettingsDialog(null, AlignGui.this.model);
			settingsDialog = new SettingsDialog(null, AlignGui.this);   // 2006-09-21
			settingsDialog.setLocationRelativeTo(AlignGui.this);
			//settingsDialog.setLocationRelativeTo(settingsButton);   //  funker ogsï¿½
			//settingsDialog.show();   // Deprecated
			settingsDialog.setVisible(true);
			if (settingsDialog.approved) {
				// reset compare stuff (info about elements in each text and how elements combine).
				// might be necessary to reset because info might be based on old settings.
				// probably not always though
				//System.out.println("skal ta new Compare()");
				//System.out.println("AlignGui.this.model.compare.matrix = " + AlignGui.this.model.compare.matrix);
				AlignGui.this.model.compare = new Compare();
				//System.out.println("har tatt new Compare()");
				//System.out.println("AlignGui.this.model.compare.matrix = " + AlignGui.this.model.compare.matrix);
			}

		}
	}

	//public class LogAction extends MyAbstractAction {
	public class StartLoggingAction extends MyAbstractAction {

		public StartLoggingAction(String text, ImageIcon icon, String desc, KeyStroke accelerator, Integer mnemonic) {
			super(text, icon, desc, accelerator, mnemonic);
		}
		public void actionPerformed(ActionEvent e) {

			//  gjentas mange ganger
			AlignGui.this.statusLine.clear();

			// ...
			//Toolkit.getDefaultToolkit().beep();

			// start logging

			if (model.logFileOut == null) {

				// open log file

				////System.out.println("Skal ï¿½ne loggfil:");
				//File f = new File(model.logFilename);

				// ####dupl kode
				// the basis for the suggestion is the input file names
				String logFilenameSuggestion = "";
				for (int t=0; t<Alignment.NUM_FILES; t++) {
					String tempFilename;
					// find name of input file t - just the file name - no path, no extension
					if (AlignGui.this.model.inputFilepath[t] != null) {
						File tempPath = new File(AlignGui.this.model.inputFilepath[t]);
						tempFilename = tempPath.getName();
						tempFilename = ExtensionUtils.getFilenameWithoutExtension(tempFilename);
					} else {
						// no inputfile. use a number (1, 2) as a surrogate
						tempFilename = "" + (t+1);   // ######
					}
					// but the suggestion must obey the current directory for saving files,
					// so we need just the file names, without the extension.
					// we string them together with an underscore between them
					if (logFilenameSuggestion == "") {
						logFilenameSuggestion += "log_";
					} else {
						logFilenameSuggestion += "_";
					}
					logFilenameSuggestion += tempFilename;
				}
				// finally add extension
				logFilenameSuggestion += ".txt";

				chooser = new JFileChooser();
				chooser.setApproveButtonText("Save log file");  // ###
				if (model.currentSaveDirectory != null) {
					chooser.setCurrentDirectory(model.currentSaveDirectory);
				} else {
					if (model.currentOpenDirectory != null) {
						chooser.setCurrentDirectory(model.currentOpenDirectory);
					} else {
						chooser.setCurrentDirectory(null);
					}
				}

				// the suggestion must obey the current directory for ...
				File logFilepathSuggestion = new File(chooser.getCurrentDirectory(), logFilenameSuggestion);

				// dialog
				chooser.setSelectedFile(logFilepathSuggestion);
				int returnVal = chooser.showSaveDialog(AlignGui.this);   // vil helst ha en fornuftig parent, men
				if (returnVal == JFileChooser.APPROVE_OPTION) {

					File f = chooser.getSelectedFile();

					try {

						OutputStream fOut = new FileOutputStream(f);
						OutputStream bOut = new BufferedOutputStream(fOut);
						Charset cs = Charset.forName("UTF-8");
						model.logFileOut = new OutputStreamWriter(bOut, cs);

					} catch (Exception ex) {

						//  PLAIN_MESSAGE, INFORMATION_MESSAGE, WARNING_MESSAGE, ERROR_MESSAGE?
						// advarselsdialog her eller i kallende kode?
						JOptionPane.showMessageDialog(
							null,
							"Can't open log file " + f.getName(),
							"Title",
							JOptionPane.ERROR_MESSAGE
						);
						//System.err.println("Exception when opening " + model.getLogFilename() + ": ");
						//System.err.println(ex.toString());
						ErrorMessage.error("Exception when opening " + model.getLogFilename() + ":\n" + ex.toString());   // 2006-08-10
						//ex.printStackTrace();

						//men hva sï¿½

					}

					model.setLogging(true);
					// ... file name ...
					model.setLogFilename(f.getName());
					// also show in gui
					AlignGui.this.setLogFilenameLabel(f.getName());

					//logButton.set...("Stop logging");
					// ###############dupl kode
					startLoggingButton.setVisible(!model.getLogging());
					stopLoggingButton.setVisible(model.getLogging());

					//System.out.println("Skal skrive header til loggfil:");
					try {
						//String text = ">>> Start logging <<<\n\n";
						String text = ">>> Logging started <<<\n\n";   // 2006-04-18
						//System.out.println(text);
						model.logFileOut.write(text, 0, text.length());
					} catch (Exception ex) {
						//System.err.println("Exception when writing to " + model.getLogFilename() + ": ");
						//System.err.println(ex.toString());
						ErrorMessage.error("Exception when writing to " + model.getLogFilename() + ":\n" + ex.toString());   // 2006-08-10
						//ex.printStackTrace();
					}

				}

			} else {

				// log file already open

				model.setLogging(true);
				//logButton.set...("Stop logging");
				startLoggingButton.setVisible(!model.getLogging());
				stopLoggingButton.setVisible(model.getLogging());

				try {
					//String text = ">>> Restart logging <<<\n\n";
					String text = ">>> Logging restarted <<<\n\n";   // 2006-04-18
					model.logFileOut.write(text, 0, text.length());
				} catch (Exception ex) {
					//System.err.println("Exception when writing to " + model.getLogFilename() + ": ");
					//System.err.println(ex.toString());
					ErrorMessage.error("Exception when writing to " + model.getLogFilename() + ":\n" + ex.toString());   // 2006-08-10
					//ex.printStackTrace();
				}

			}

		}
	}

	//boolean logging = mode.getLogging();
	//if (logging) {

	public class StopLoggingAction extends MyAbstractAction {

		public StopLoggingAction(String text, ImageIcon icon, String desc, KeyStroke accelerator, Integer mnemonic) {
			super(text, icon, desc, accelerator, mnemonic);
		}
		public void actionPerformed(ActionEvent e) {

			//  gjentas mange ganger
			AlignGui.this.statusLine.clear();

			// ...
			//Toolkit.getDefaultToolkit().beep();

			// stop logging

			try {
				//String text = "\n\n>>> Stop logging <<<\n\n";
				String text = ">>> Logging stopped <<<\n\n";   // 2006-04-18
				model.logFileOut.write(text, 0, text.length());
			} catch (Exception ex) {
				//System.err.println("Exception when writing to " + model.getLogFilename() + ": ");
				//System.err.println(ex.toString());
				ErrorMessage.error("Exception when writing to " + model.getLogFilename() + ":\n" + ex.toString());   // 2006-08-10
				//ex.printStackTrace();
			}

			model.setLogging(false);
			//logButton.set...("Start logging");
			startLoggingButton.setVisible(!model.getLogging());
			stopLoggingButton.setVisible(model.getLogging());

		}
	}

	public class SkipCorrespAction extends MyAbstractAction {
		public SkipCorrespAction(String text, ImageIcon icon, String desc, KeyStroke accelerator, Integer mnemonic) {
			super(text, icon, desc, accelerator, mnemonic);
		}
		public void actionPerformed(ActionEvent e) {

			//  gjentas mange ganger
			AlignGui.this.statusLine.clear();

			model.skipCorresp(AlignGui.this);

		}
	}

	// 2006-08-15
	public class BreakAction extends MyAbstractAction {
		public BreakAction(String text, ImageIcon icon, String desc, KeyStroke accelerator, Integer mnemonic) {
			super(text, icon, desc, accelerator, mnemonic);
		}
		public void actionPerformed(ActionEvent e) {

			//  gjentas mange ganger
			AlignGui.this.statusLine.clear();

			model.break_(AlignGui.this);

		}
	}
	// end 2006-08-15

	/*
	public class ChangeAction extends MyAbstractAction {
		public ChangeAction(String text, ImageIcon icon, String desc, KeyStroke accelerator, Integer mnemonic) {
			super(text, icon, desc, accelerator, mnemonic);
		}
		public void actionPerformed(ActionEvent e) {
			//  gjentas mange ganger
			AlignGui.this.statusLine.clear();

			//JOptionPane.showMessageDialog(null, "This is action " + e.paramString(), "Title", JOptionPane.INFORMATION_MESSAGE);
			// ######### funker ikke
			//Dimension dim = alignedListBox[0].getSize();
			//int w = (int)Math.round(dim.getWidth());
			//int h = (int)Math.round(dim.getHeight());
			//h += 10;
			//AlignGui.this.alignedListBox[0].setSize(w, h);
			// dette funker. men ikke nok ï¿½ta ï¿½ komponent. mï¿½ta alle i en hel rad for ï¿½endre hyden pï¿½raden
			GridBagConstraints c = new GridBagConstraints();
			//c = AlignGui.this.layout.getConstraints(AlignGui.this.alignedListBox[0]);
			//c = AlignGui.this.layout.getConstraints(AlignGui.this.statusLine);
			//System.out.println("c.getWeighty()=" + c.getWeighty()); nei
			//c.weighty = 100;
			//AlignGui.this.layout.setConstraints(AlignGui.this.alignedListBox[0], c);
			//AlignGui.this.layout.setConstraints(AlignGui.this.statusLine, c);
			// switch weighty between aligned and unaligned
			double alignedWeighty = AlignGui.this.layout.getConstraints(row2[0]).weighty;
			System.out.println("alignedWeighty=" + alignedWeighty);
			double unalignedWeighty = AlignGui.this.layout.getConstraints(row5[0]).weighty;
			System.out.println("unalignedWeighty=" + unalignedWeighty);
			for (int i = 0; i < row2.length; i++) {
				c = AlignGui.this.layout.getConstraints(row2[i]);
				//c.weighty = unalignedWeighty;
				c.weighty = row5weighty;
				AlignGui.this.layout.setConstraints(row2[i], c);
			}
			for (int i = 0; i < row5.length; i++) {
				c = AlignGui.this.layout.getConstraints(row5[i]);
				//c.weighty = alignedWeighty;
				c.weighty = row2weighty;
				AlignGui.this.layout.setConstraints(row5[i], c);
			}
			double temp = row5weighty;
			row5weighty = row2weighty;
			row2weighty = temp;
			AlignGui.this.invalidate();
         	AlignGui.this.validate();
		}
	}
	*/

	/*
	//&&//
	public class CorrespAction extends MyAbstractAction {
		public CorrespAction(String text, ImageIcon icon, String desc, KeyStroke accelerator, Integer mnemonic) {
			super(text, icon, desc, accelerator, mnemonic);
		}
		public void actionPerformed(ActionEvent e) {

			//  gjentas mange ganger
			AlignGui.this.statusLine.clear();

			//correspDialog = new CorrespDialog(AlignGui.this);   //  gï¿½ ikke
			correspDialog = new CorrespDialog(null, toAlignModel);
			correspDialog.setLocationRelativeTo(AlignGui.this);
			//correspDialog.setLocationRelativeTo(correspButton);   //  funker ogsï¿½
			correspDialog.show();   // Deprecated
			correspDialog.setVisible(true);
			if (correspDialog.approved) {
				for (int t=0; t<Alignment.NUM_FILES; t++) {
					toAlignModel[t].clear();
					////System.out.println("cleared " + (t+1));
					for (int i=0; i < correspDialog.toAlignModel[t].getSize(); i++) {
						toAlignModel[t].addElement(correspDialog.toAlignModel[t].getElementAt(i));
						////System.out.println("element " + i + " added to " + (t+1));
					}
				}
			}

			////JOptionPane.showMessageDialog(null, "This is action " + e.paramString(), "Title", JOptionPane.INFORMATION_MESSAGE);

		}
	}
	*/
	//&&//

	/*
	public class LinkAction extends MyAbstractAction {
		public LinkAction(String text, ImageIcon icon, String desc, KeyStroke accelerator, Integer mnemonic) {
			super(text, icon, desc, accelerator, mnemonic);
		}
		public void actionPerformed(ActionEvent e) {
			*/

			/*
			//  gjentas mange ganger
			AlignGui.this.statusLine.clear();

			Object[][] selectedElements = new Object[Alignment.NUM_FILES][];
			for (int t=0; t<Alignment.NUM_FILES; t++) {
				selectedElements[t] = toAlignListBox[t].getSelectedValues();
			}
			model.align();
			*/

			/*
			JOptionPane.showMessageDialog(null, "This is action " + e.paramString(), "Title", JOptionPane.INFORMATION_MESSAGE);

		}
	}
	*/

	/*
	public class BatchAction extends MyAbstractAction {
		public BatchAction(String text, ImageIcon icon, String desc, KeyStroke accelerator, Integer mnemonic) {
			super(text, icon, desc, accelerator, mnemonic);
		}
		public void actionPerformed(ActionEvent e) {
			//  gjentas mange ganger
			AlignGui.this.statusLine.clear();

			JOptionPane.showMessageDialog(null, "This is action " + e.paramString(), "Title", JOptionPane.INFORMATION_MESSAGE);
		}
	}
	*/

	public class SuggestAction extends MyAbstractAction {
		public SuggestAction(String text, ImageIcon icon, String desc, KeyStroke accelerator, Integer mnemonic) {
			super(text, icon, desc, accelerator, mnemonic);
		}
		public void actionPerformed(ActionEvent e) {

			//  gjentas mange ganger
			AlignGui.this.statusLine.clear();

			//JOptionPane.showMessageDialog(null, "This is action " + e.paramString(), "Title", JOptionPane.INFORMATION_MESSAGE);
			// test lyd.  br vel lage clip en gang for alle ved oppstart
			//AudioClip sound = JApplet.getAudioClip(JApplet.getCodeBase(),"audio/ding.wav");
			//AlignGui.this.sound.play();
			model.suggest(AlignGui.this);

		}
	}

	// ???
	public class HelpAction extends MyAbstractAction {
		public HelpAction(String text, ImageIcon icon, String desc, KeyStroke accelerator, Integer mnemonic) {
			super(text, icon, desc, accelerator, mnemonic);
		}
		public void actionPerformed(ActionEvent e) {

			//  gjentas mange ganger
			AlignGui.this.statusLine.clear();

			//JOptionPane.showMessageDialog(null, "This is action " + e.paramString(), "Title", JOptionPane.INFORMATION_MESSAGE);
			//JOptionPane.showMessageDialog(null, "Help - not implemented", "Not implemented", JOptionPane.INFORMATION_MESSAGE);
			JOptionPane.showMessageDialog(null, "Help - not implemented.\n\nProgram version: " + Alignment.VERSION, "Not implemented", JOptionPane.INFORMATION_MESSAGE);   // 2006-09-19

		}
	}

	// ... toolTipAction
	public class ToolTipAction extends MyAbstractAction {
		public ToolTipAction(String text, ImageIcon icon, String desc, KeyStroke accelerator, Integer mnemonic) {
			super(text, icon, desc, accelerator, mnemonic);
		}
		public void actionPerformed(ActionEvent e) {

			//  gjentas mange ganger
			AlignGui.this.statusLine.clear();

			////JOptionPane.showMessageDialog(null, "This is action " + e.paramString(), "Title", JOptionPane.INFORMATION_MESSAGE);
			// <http://javaalmanac.com/egs/javax.swing/tooltip_EnableTt.html>
			if (ToolTipManager.sharedInstance().isEnabled()) {
				// enable tool tips for the entire application
				ToolTipManager.sharedInstance().setEnabled(false);
			} else {
				// disable tool tips for the entire application
				ToolTipManager.sharedInstance().setEnabled(true);
			}

		}
	}

	public int getMode() {
		int mnemonic = AlignGui.this.modeRadioButtonPanel.rbg.getSelection().getMnemonic();
		if (mnemonic == KeyEvent.VK_O) {
			return Alignment.MODE_ONE;
		} else if (mnemonic == KeyEvent.VK_S) {
			return Alignment.MODE_SKIP11;
		} else if (mnemonic == KeyEvent.VK_A) {
			return Alignment.MODE_AUTO;
		} else {
			// ##### program error ####
			return Alignment.MODE_ONE;
		}
	}

	public void setAnchorFilenameLabel(String fileName) {
		anchorFilenameLabel.setText(fileName);
	}

	// 2006-09-21
	public void setSettingsFilenameLabel(String fileName) {
		settingsFilenameLabel.setText(fileName);
	}
	// end 2006-09-21

	public void setLogFilenameLabel(String fileName) {
		logFilenameLabel.setText(fileName);
	}

    AlignGui(AlignmentModel model) {

		// set to Windows look & feel

		String plafClassName =
			 // de som ser normale ut er kanskje ikke tilgjengelige/til stede, altsï¿½at vi fï¿½ default isteden
			 "com.sun.java.swing.plaf.windows.WindowsLookAndFeel";   // denne er annerledes
			 //"com.sun.java.swing.plaf.gtk.GTKLookAndFeel";   // ser "normal" ut
			 //"javax.swing.plaf.metal.MetalLookAndFeel";   // ser "normal" ut
			 //"com.sun.java.swing.plaf.motif.MotifLookAndFeel";   // denne er annerledes
			 //UIManager.getCrossPlatformLookAndFeelClassName();   // ser "normal" ut
			 //"it.unitn.ing.swing.plaf.macos.MacOSLookAndFeel";   // ser "normal" ut
			 //"com.incors.plaf.kunststoff.KunststoffLookAndFeel";   // ser "normal" ut
		try {
			UIManager.setLookAndFeel(plafClassName);
		} catch(Exception ex) {
			System.out.println(ex);
		}
		SwingUtilities.updateComponentTreeUI(this);

		// ...

		this.model = model;

		String key;   // 2006-08-15

        // make the important objects

		// create actions shared by buttons, menus, etc.

		// open file actions

		OpenAction[] openActions = new OpenAction[Alignment.NUM_FILES];
		for (int t=0; t<Alignment.NUM_FILES; t++) {
			//System.out.println(t);
			// 2006-08-15
			if (t == 0) {
				key = "control O";
			} else {
				key = "shift control O";
			}
			// end 2006-08-15
			openActions[t] = new
				OpenAction(
					"Open file " + (t+1),
					createImageIcon("images/Read.gif", "read from disc"),
					"Open file " + (t+1),
					//null,
					KeyStroke.getKeyStroke(key),   // 2006-08-15 #######
					new Integer(0)
					//new Integer(KeyEvent.VK_X) denne er for alt+X, ikke bare X
				);
		}

		/*// save file actions

		SaveAction[] saveActions = new SaveAction[Alignment.NUM_FILES];
		for (int t=0; t<Alignment.NUM_FILES; t++) {
			//System.out.println(t);
			saveActions[t] = new
				SaveAction(
					"Save file " + (t+1),
					createImageIcon("images/Write.gif", "write to disc"),
					"Save file " + (t+1),
					null,
					new Integer(0)
				);
		}*/

		//// save all files action
		// save result action

		SaveAllAction saveAllAction = new
			SaveAllAction(
				//"Save all files",
				"Save result",
				createImageIcon("images/Write.gif", "write to disc"),
				"Save result",
				//null,
				KeyStroke.getKeyStroke("control S"),   // 2006-08-15
				new Integer(0)
			);

		// purge action

		PurgeAction purgeAction = new
			PurgeAction(
				"Clear all data",
				createImageIcon("images/Purge.gif", "clear all data"),
				"Clear all data",
				//null,
				KeyStroke.getKeyStroke("control X"),   // 2006-08-15 #########X
				new Integer(0)
			);

		// anchor word file action

		AnchorAction anchorAction = new
			AnchorAction(
				//"\u2693 Anchor words",  var visst tull. finnes kanskje ikke noe anker i unicode. bare et forslag???
				//"\u263B Anchor words",   svart smiley
				"Anchor words",
				//createImageIcon("images/Select.gif", "a face"),
				createImageIcon("images/Anchor.gif", "anchor"),
				"Unalign",
				null,
				new Integer(0)
			);

		// unalign action

		UnalignAction unalignAction = new
			UnalignAction(
				"Unalign",
				createImageIcon("images/Down.gif", "arrow down"),
				"Unalign",
				KeyStroke.getKeyStroke("pressed DOWN"),
				new Integer(0)
			);

		// align action

		AlignAction alignAction = new
			AlignAction(
				"Align",
				createImageIcon("images/Up.gif", "arrow up"),
				"Align",
				//null,
				KeyStroke.getKeyStroke("control UP"),   // 2006-08-15 ######
				new Integer(0)
			);

		/*// edit action

		EditAction editAction = new
			EditAction(
				"Edit",
				createImageIcon("images/Blank.gif", "blank"),
				"Edit",
				null,
				new Integer(0)
			);*/

		// settings action

		SettingsAction settingsAction = new
			SettingsAction(
				"Settings",
				createImageIcon("images/Settings.gif", "dialog form"),
				"Settings",
				null,
				new Integer(0)
			);

		// 'start logging' action

		StartLoggingAction startLoggingAction = new
			StartLoggingAction(
				"Start logging",
				createImageIcon("images/Log.gif", "log"),
				"Start logging",
				null,
				new Integer(0)
			);

		// 'stop logging' action

		StopLoggingAction stopLoggingAction = new
			StopLoggingAction(
				"Stop logging",
				createImageIcon("images/Log.gif", "log"),
				"Stop logging",
				null,
				new Integer(0)
			);

		SkipCorrespAction skipCorrespAction = new
			SkipCorrespAction(
				"Skip what's already aligned",
				createImageIcon("images/SkipAligned.gif", "aligned elements above unaligned ones, with arrow passing the aligned ones"),
				"Skip what's already aligned",
				null,
				new Integer(0)
			);

		// 2006-08-15
		// break action

		BreakAction breakAction = new
			BreakAction(
				"Break",
				createImageIcon("images/Break.gif", "log"),
				"Break",
				KeyStroke.getKeyStroke("control C"),
				new Integer(0)
			);
		// end 2006-08-15

		/*
		// change layout action - test

		ChangeAction changeAction = new
			ChangeAction(
				"Change",
				createImageIcon("images/Blank.gif", "blank"),
				"Change",
				null,
				new Integer(0)
			);
		*/

		// link action

		/*
		LinkAction linkAction = new
			LinkAction(
				"Link",
				createImageIcon("images/Blank.gif", "blank"),
				"Link",
				null,
				new Integer(0)
			);
		*/

		//&&//// corresp action
		//&&//
		//&&//CorrespAction correspAction = new CorrespAction("corresp",
		//&&//                                                createImageIcon("images/test1.gif", "a face"),
		//&&//                                                "corresp",
		//&&//                                                new Integer(0));

		// more actions

		//String key;

		MoreAction[] moreActions = new MoreAction[Alignment.NUM_FILES];
		for (int t=0; t<Alignment.NUM_FILES; t++) {
			if (t == 0) {
				key = "pressed LEFT";
			} else {
				key = "pressed RIGHT";
			}
			moreActions[t] = new
				MoreAction(
					//"More " + (t+1),
					"Up (text " + (t+1) + ")",
					createImageIcon("images/Up.gif", "arrow up"),
					//"More " + (t+1),
					"Up (text " + (t+1) + ")",
					//KeyStroke.getKeyStroke("typed j"),
					KeyStroke.getKeyStroke(key),
					new Integer(0)
				);
		}

		// less actions

		LessAction[] lessActions = new LessAction[Alignment.NUM_FILES];
		for (int t=0; t<Alignment.NUM_FILES; t++) {
			if (t == 0) {
				key = "shift pressed LEFT";
			} else {
				key = "shift pressed RIGHT";
			}
			lessActions[t] = new
				LessAction(
					//"Less " + (t+1),
					"Down (text " + (t+1) + ")",
					createImageIcon("images/Down.gif", "arrow down"),
					//"Less " + (t+1),
					"Down (text " + (t+1) + ")",
					//KeyStroke.getKeyStroke("typed k"),
					KeyStroke.getKeyStroke(key),
					new Integer(0)
				);
		}

		// batch action

		/*
		BatchAction batchAction = new
			BatchAction(
				"Batch",
				createImageIcon("images/Blank.gif", "blank"),
				"Batch",
				null,
				new Integer(0)
			);
		*/

		// suggest action

		SuggestAction suggestAction = new
			SuggestAction(
				"Suggest",
				createImageIcon("images/Up.gif", "arrow up"),
				"Suggest",
				//new Integer(KeyEvent.VK_UP),
				// ### fï¿½ f### ikke accelerator til ï¿½virke.
				// bare mnemonic (som er alt+tast).
				// de virker ikke, og de lager kludder for menu
				//new Integer(KeyEvent.VK_X),
				// ### nei, her fï¿½ jeg det til.
				// men det ser ut til at accelerators KUN virker for det som er i menu!!!!!!!!!!!!!!!!!
				KeyStroke.getKeyStroke("pressed UP"),
				new Integer(0)
			);

		// help action

		HelpAction helpAction = new
			HelpAction(
				"Help",
				createImageIcon("images/Help.gif", "question mark"),
				"Help",
				//null,
				//KeyEvent.VK_F1,
				KeyStroke.getKeyStroke("F1"),   // 2006-08-15
				new Integer(0)
			);

		ToolTipAction toolTipAction = new
			ToolTipAction(
				"ToolTip",
				createImageIcon("images/ToolTip.gif", "yellow tooltip rectangle"),
				"ToolTip",
				//null,
				KeyStroke.getKeyStroke("control T"),   // 2006-08-15 ########T
				new Integer(0)
			);

		// ... actions ...

		// colours

        // Marlï¿½'s colours
        Color bgColor = new Color(0xF5DEB3);   // #F5DEB3
        Color buttonColor = new Color(0x94BA45);   // #94BA45
        Color buttonTextColor = new Color(0x006400);   // #006400

        Font plainFont = this.getFont().deriveFont(Font.PLAIN);

		// create menu that uses the above actions

		// midlertidig komm ut

		/*menu*/
		menuBar =
			createMenu(
				openActions,
				//saveActions,
				saveAllAction,
				purgeAction,
				unalignAction,
				anchorAction,
				alignAction,
				//editAction,
				settingsAction,
				//logAction,
				startLoggingAction,
				stopLoggingAction,
				skipCorrespAction,
				breakAction,   // 2006-08-15
				//changeAction,
				//&&//correspAction,
				//linkAction,
				moreActions,
				lessActions,
				//batchAction,
				suggestAction,
				helpAction,
				toolTipAction
			);


        // gui objects

		openFileButton = new JButton[Alignment.NUM_FILES];
		//saveFileButton = new JButton[Alignment.NUM_FILES];
		filenameLabel = new JLabel[Alignment.NUM_FILES];
		saveAllFileButton = new JButton(saveAllAction);
		purgeButton = new JButton(purgeAction);
		savePurgePanel = new JPanel();

		anchorFileButton = new JButton(anchorAction);
		//anchorFileButton.setFont(new Font("Arial Unicode MS", Font.PLAIN, 16));
		anchorFilenameLabel = new JLabel("");
		anchorFilenameLabel.setFont(anchorFilenameLabel.getFont().deriveFont(10.0f));

		settingsFilenameLabel = new JLabel("");   // 2006-09-21
		settingsFilenameLabel.setFont(settingsFilenameLabel.getFont().deriveFont(10.0f));   // 2006-09-21

        //alignedModel = new DefaultListModel[Alignment.NUM_FILES];
        alignedListBox = new JList[Alignment.NUM_FILES];
        alignedScrollPane = new JScrollPane[Alignment.NUM_FILES];

		unalignButton = new JButton(unalignAction);

        //toAlignModel = new DefaultListModel[Alignment.NUM_FILES];
        toAlignListBox = new JList[Alignment.NUM_FILES];
        toAlignScrollPane = new JScrollPane[Alignment.NUM_FILES];

		//modePanel = new JPanel();
		//modePanel.setMaximumSize(new Dimension(350, 0));
		////skipBox = new JCheckBox("Skip 1-1", true);
		//skip11CheckBox = new JCheckBox("Skip 1-1.", false);
		//skip11LimitLabel1 = new JLabel("Limit:");
		runLimitLabel1 = new JLabel("Skip/auto limit:");
		//skip11LimitTextField = new JTextField("999999");   // ##########
		runLimitTextField = new JTextField("999999");   // ########## for ï¿½fï¿½bredde pï¿½feltet
		//runLimitTextField = new JTextField("10");   // ########## klapper sammen
		runLimitTextField.setFont(plainFont);
		// 2006-08-14
		// select all when the fields gets focus
		runLimitTextField.addFocusListener(new FocusAdapter() {
			public void focusGained(FocusEvent e) {
				JTextField field = (JTextField)e.getSource();
				field.selectAll();
			}
		});
		// end 2006-08-14
		////skip11LimitTextField.setMinimumSize(new Dimension(40, 20));
		////skip11LimitTextField.setMaximumSize(new Dimension(40, 20));
		//skip11LimitLabel2 = new JLabel("alignments");
		runLimitLabel2 = new JLabel("alignments");
		//skip11Panel = new JPanel();
		runPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
		////skip11Panel.setMaximumSize(new Dimension(250, 20));   // ###without this the panel gets wider than its content, resulting in indentation of the content
		//skip11Panel.setMaximumSize(new Dimension(250, 0));   // ###without this the panel gets wider than its content, resulting in indentation of the content
		runPanel.setMaximumSize(new Dimension(300, 0));   // ###without this the panel gets wider than its content, resulting in indentation of the content

		//modeRadioButtonPanel = new ModeRadioButtonPanel();
		modeRadioButtonPanel = new ModeRadioButtonPanel(bgColor, plainFont);
		modeRadioButtonPanel.setMaximumSize(new Dimension(300, 0));

		alignButton = new JButton(alignAction);
		//editButton = new JButton(editAction);
		//settingsPanel = new JPanel();
		settingsPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));   // ### prvde LEFT. ble da venstrejust, og det ville jeg ha, men det kom litt padding foran, og det ville jeg ikke ha. box + strut mellom de to knappene + glue pï¿½slutten hadde sikkert vï¿½t bedre. eller springlayout, som jeg aldri har prvd. flow center er default og ikke ndvendig
		logPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
		skipPanel = new JPanel();
		breakPanel = new JPanel();   // 2006-08-15
		//settingsPanel.setMaximumSize(new Dimension(250, 20));   // ###see runPanel
		settingsPanel.setMaximumSize(new Dimension(300, 0));   // ###see runPanel
		settingsButton = new JButton(settingsAction);
		logPanel.setMaximumSize(new Dimension(300, 0));
		//logButton = new JButton(logAction);
		startLoggingButton = new JButton(startLoggingAction);
		stopLoggingButton = new JButton(stopLoggingAction);
		breakPanel.setMaximumSize(new Dimension(300, 0));   // 2006-08-15
		breakButton = new JButton(breakAction);   // 2006-08-15
		logFilenameLabel = new JLabel("");
		logFilenameLabel.setFont(logFilenameLabel.getFont().deriveFont(10.0f));
		skipPanel.setMaximumSize(new Dimension(300, 0));
		skipButton = new JButton(skipCorrespAction);
		//changeButton = new JButton(changeAction);
		//&&//correspButton = new JButton(correspAction);
		//linkButton = new JButton(linkAction);
		//alignArrow = new JLabel("");

		//compareInfoPanel = new JPanel();
		compareInfoPanel = new CompareInfo();
		compareInfoPanel.setSize(1000, 1000);   // ###########
		compareInfoPanel.setPreferredSize(new Dimension (1000, 1000));   // ###########
		compareInfoPanel.setMinimumSize(new Dimension (1000, 1000));   // ###########
		compareInfoPanel.setGui(this);
		//compareInfoGraphics = compareInfoPanel.getGraphics();   ### for tidlig ï¿½gjre dette nï¿½
		compareInfoScrollPane = new JScrollPane(compareInfoPanel);
		//compareInfoScrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
		//compareInfoScrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);

		//anchorWordMatchesListBox = new JList(this.model.anchorWordMatches.list);
		//anchorWordMatchesScrollPane = new JScrollPane(anchorWordMatchesListBox);
		//matchInfoTextArea = new JTextArea();
		matchInfoList = new JList(this.model.matchInfo.displayableList);
		//matchInfoList.setMaximumSize(new Dimension(300, 0)); ### ikke noe hjelp i
		//matchInfoTextArea.setEditable(false);
		//matchInfoList.setEditable(false);
		//matchInfoScrollPane = new JScrollPane(matchInfoTextArea);
		matchInfoScrollPane = new JScrollPane(matchInfoList);
		//matchInfoTextArea.setName("M");
		matchInfoList.setName("M");
		Font font = matchInfoList.getFont();
		matchInfoList.setFont(new Font(font.getName(), Font.PLAIN, font.getSize()));

		moreButton = new JButton[Alignment.NUM_FILES];
		lessButton = new JButton[Alignment.NUM_FILES];
		//moreLessArrow = new JLabel[Alignment.NUM_FILES];

        //unalignedModel = new DefaultListModel[Alignment.NUM_FILES];
        unalignedListBox = new JList[Alignment.NUM_FILES];
        unalignedScrollPane = new JScrollPane[Alignment.NUM_FILES];
		//batchButton = new JButton(batchAction);
		suggestButton = new JButton(suggestAction);

		//  status line stuff
		//counter = new JTextField("");
		//counter.setEditable(false);
		////counterDoc = new PlainDocument();
		////counter.setDocument(counterDoc);
		statusLine = new AlignStatusLine();

        for (int t=0; t<Alignment.NUM_FILES; t++) {

			openFileButton[t] = new JButton(openActions[t]);
			openFileButton[t].setName("O" + t);
			//saveFileButton[t] = new JButton(saveActions[t]);
			//saveFileButton[t].setName("S" + t);
			//filenameLabel[t] = new JLabel("<filename>");
			filenameLabel[t] = new JLabel("");

	        //alignedModel[t] = new DefaultListModel();
	        ////System.out.println("--------------");
	        ////this.model.aligned.hello();
	        ////System.out.println("--------------");
	        ////System.out.println(this.model.getClass().getName());
	        ////System.out.println(this.model.aligned.getClass().getName());
	        ////System.out.println(this.model.aligned.elements.getClass().getName());
	        ////System.out.println(this.model.aligned.elements[t].getClass().getName());
	        alignedListBox[t] = new JList(this.model.aligned.elements[t]);
	        // mitt
	        alignedListBox[t].setName("A" + t);
	        alignedListBox[t].setCellRenderer(new MyCellRenderer());   // ### MyCellRenderer burde vel hete ettellerannetelementsCellRenderer
	        //alignedListBox[t].setFont(new Font("Arial Unicode MS", Font.PLAIN, 10));   // 2006-09-15

	        //toAlignModel[t] = new DefaultListModel();
	        toAlignListBox[t] = new JList(this.model.toAlign.elements[t]);
	        // mitt
	        toAlignListBox[t].setName("T" + t);   // mouse event handler needs a name, to be able to find out which list box was clicked
	        toAlignListBox[t].setCellRenderer(new MyCellRenderer());
	        //toAlignListBox[t].setFont(new Font("Arial Unicode MS", Font.PLAIN, 10));   // 2006-09-15

			lessButton[t] = new JButton(lessActions[t]);
			moreButton[t] = new JButton(moreActions[t]);
			//moreLessArrow[t] = new JLabel("");

	        //unalignedModel[t] = new DefaultListModel();
	        unalignedListBox[t] = new JList(this.model.unaligned.elements[t]);
	        // mitt
	        unalignedListBox[t].setName("U" + t);
	        //  nï¿½ forsvant horiz scroll? nï¿½ jeg prvde JTextArea? og tekst kappet ved ordgrense dvs ser flere ord hvis resizer hor
	        //unalignedListBox[t].setFixedCellWidth(10);   //  for JTextArea. gjorde ingen forskjell
	        //unalignedListBox[t].setPrototypeCellValue("xxxxxxxxxxxxxxx");   //  for JTextArea. gjorde ingen forskjell?
	        //System.out.print("width:");
	        //System.out.println(unalignedListBox[t].getFixedCellWidth());
	        unalignedListBox[t].setCellRenderer(new MyCellRenderer());
	        //System.out.print("width:");
	        //System.out.println(unalignedListBox[t].getFixedCellWidth());
	        //unalignedListBox[t].setFont(new Font("Arial Unicode MS", Font.PLAIN, 10));   // 2006-09-15

		}

		// handler for mouse events in toAlign

		//  kan vi ha denne som en action?
		//  er det mulig ï¿½gjre dette uten mus?
		MouseListener toAlignMouseListener = new MouseAdapter() {

			public void mouseClicked(MouseEvent e) {

				//Toolkit.getDefaultToolkit().beep();

				// 2006-09-25
				Object[] options = { "Yes", "No" };   // button texts
				int n = JOptionPane.showOptionDialog(
					null,
					"Do you want to change the suggested alignment(s)",
					"Change alignment(s)",
					JOptionPane.YES_NO_OPTION,
					JOptionPane.QUESTION_MESSAGE,
					null,
					options,
					options[1]   // the choice that is initially selected
				);
				if(n == 0) {
					// YES
					// end 2006-09-25

					//  gjentas mange ganger
					AlignGui.this.statusLine.clear();

					/*
					String type = "";
					if (e.getClickCount() == 2) {
						type = "Double";
					} else {
						type = "Single";
					}
					*/

					//System.out.println("toAlignMouseListener");
					int tClicked = Integer.parseInt(e.getComponent().getName().substring(1, 2));
					//System.out.println("Clicked in text " + (tClicked+1));
					int indexClicked = ((JList)(e.getComponent())).locationToIndex(e.getPoint());
					//System.out.println("Clicked on JList item " + indexClicked);
					int elementNumberClicked = ((AElement)(AlignGui.this.model.toAlign.elements[tClicked].get(0))).elementNumber + indexClicked;
					//System.out.println("Clicked on element " + elementNumberClicked);
					int alignmentNumberClicked = ((AElement)(AlignGui.this.model.toAlign.elements[tClicked].get(indexClicked))).alignmentNumber;
					//System.out.println("Clicked on alignment " + alignmentNumberClicked);

					//// forelpig: linker til verste pending
					//AlignGui.this.model.link(AlignGui.this, tClicked, indexClicked, elementNumberClicked);
					AlignGui.this.model.link(AlignGui.this, tClicked, indexClicked, elementNumberClicked, -2);  // being told to link to alignment number -2 is a signal to link to next available pending alignment
					//

				}   // 2006-09-25

			}

		};
		for (int t=0; t<Alignment.NUM_FILES; t++) {
			toAlignListBox[t].addMouseListener(toAlignMouseListener);
		}

		// handler for mouse events in aligned and unaligned.
		// synchronizes texts for the various languages

		//  kan vi ha denne som en action?
		//  er det mulig ï¿½gjre dette uten mus?
		MouseListener alignedAndUnalignedMouseListener = new MouseAdapter() {

			public void mouseClicked(MouseEvent e) {

				//  gjentas mange ganger
				AlignGui.this.statusLine.clear();

				/*
				String type = "";
				if (e.getClickCount() == 2) {
					type = "Double";
				} else {
					type = "Single";
				}
				*/

				String componentName = e.getComponent().getName();
				String aClicked = componentName.substring(0, 1);   // "A" for aligned, or "U" for unaligned
				int tClicked = Integer.parseInt(componentName.substring(1, 2));
				//System.out.println("Clicked in component of type " + aClicked);
				//System.out.println("Clicked in text " + (tClicked+1));
				int indexClicked = ((JList)(e.getComponent())).locationToIndex(e.getPoint());
				//System.out.println("Clicked on JList item " + indexClicked);

				if (aClicked.equals("A")) {

					// user clicked in aligned

					int elementNumberClicked = indexClicked;
					//System.out.println("Clicked on element " + elementNumberClicked);
					int alignmentNumberClicked = ((AElement)(AlignGui.this.model.aligned.elements[tClicked].get(indexClicked))).alignmentNumber;
					//System.out.println("Clicked on alignment " + alignmentNumberClicked);

					for (int t=0; t<Alignment.NUM_FILES; t++) {
						//System.out.println("t=" + t);
						//if (t != tClicked) { // ### commented out. i decide to treat all texts equally, with respect to highlighting and scroll, both the clicked one and the other(s)
							//System.out.println("t != tClicked");
							//alignedListBox[t].ensureIndexIsVisible(indexClicked);
							Link alignment = (Link)(AlignGui.this.model.aligned.alignments.get(alignmentNumberClicked));
							Set elementNumbers = alignment.getElementNumbers(t);
							if (elementNumbers.size() > 0) {
								//System.out.println("elementNumbers.size() > 0");
								// find smallest index of aligned element in other text
								int smallestIndex = Integer.MAX_VALUE;
								int highestIndex = Integer.MIN_VALUE;
								//System.out.println("smallestIndex = " + smallestIndex);
								//System.out.println("highestIndex = " + highestIndex);
								Iterator eIt = alignment.elementNumbers[t].iterator();
								while (eIt.hasNext()) {
									int elementNumber = ((Integer)(eIt.next())).intValue();
									if (elementNumber < smallestIndex) {
										smallestIndex = elementNumber;
									}
									if (elementNumber > highestIndex) {
										highestIndex = elementNumber;
									}
									//System.out.println("smallestIndex = " + smallestIndex);
									//System.out.println("highestIndex = " + highestIndex);
								}
								// first scroll the last element of the alignment into view...
								// ###### better alternative might be to scroll very last element
								// of the list box into view. this will - in the next step -
								// make the first element appear at the very top of the list box,
								// if possible, securing a better *visual* alignment
								alignedListBox[t].ensureIndexIsVisible(highestIndex);
								// ...then the first element.
								// now all the elements should be visible,
								// unless the elements are long and many in number.
								// in the worst case at least the first one should be visible now
								alignedListBox[t].ensureIndexIsVisible(smallestIndex);
								alignedListBox[t].setSelectedIndex(smallestIndex);
							} else {
								//System.out.println("!(elementNumbers.size() > 0)");
								// ### forelpig programmering.
								// ### n-0-alignment. mï¿½lete opp en etterflger. i.g.n.m
								Toolkit.getDefaultToolkit().beep();
								//System.out.println("BEEEEEEEEEEEEEEEEP mouseClicked");
								//System.out.println("Some programming missing here?");   // kommentert ut 2006-10-04, uten at jeg har sett pï¿½saken
							}
						//}
					}

				} else { // "U"

					// user clicked in unaligned

					int elementNumberClicked = ((AElement)(AlignGui.this.model.unaligned.elements[tClicked].get(0))).elementNumber + indexClicked;
					//System.out.println("Clicked on element " + elementNumberClicked);

					int numThis = unalignedListBox[tClicked].getModel().getSize();
					int numOther = -1;
					int otherIndex = -1;
					for (int t=0; t<Alignment.NUM_FILES; t++) {
						if (t != tClicked) {
							//unalignedListBox[t].ensureIndexIsVisible(indexClicked);
							numOther = unalignedListBox[t].getModel().getSize();;
							//System.out.println("numOther = " + numOther);
							if (numOther > 0) {
								//System.out.println("float = " + (((((float)(indexClicked + 1) * numOther) - 1) / numThis) - 1));
								otherIndex =          Math.round(((((float)(indexClicked + 1) * numOther) - 1) / numThis) - 1);
								//System.out.println("otherIndex = " + otherIndex);
								unalignedListBox[t].ensureIndexIsVisible(otherIndex);
								unalignedListBox[t].setSelectedIndex(otherIndex);
							}
						}
					}

				}

				// ...

			}

		};
		for (int t=0; t<Alignment.NUM_FILES; t++) {
			alignedListBox[t].addMouseListener(alignedAndUnalignedMouseListener);
			unalignedListBox[t].addMouseListener(alignedAndUnalignedMouseListener);
		}

		//// handler for mouse events in matchInfoTextArea
		// handler for mouse events in matchInfoList

		//MouseListener matchInfoTextAreaMouseListener = new MouseAdapter() {
		MouseListener matchInfoListMouseListener = new MouseAdapter() {

			public void mouseClicked(MouseEvent e) {

				//  gjentas mange ganger
				AlignGui.this.statusLine.clear();

				//String nameClicked = e.getComponent().getName();
				//System.out.println("Clicked in " + nameClicked);

				//\\//System.out.println("1");
				int indexClicked = matchInfoList.locationToIndex(e.getPoint());
				//\\//System.out.println("indexClicked = " + indexClicked);
				if (indexClicked != -1) {
					//\\//System.out.println("3");
					String line = (String)AlignGui.this.model.matchInfo.displayableList.get(indexClicked);
					//\\//System.out.println("Clicked line " + line);
					String w = line.trim().split(" ")[0];   // ######### grisete
					//\\//System.out.println("number(?) = " + w);
					try {
						int n = Integer.parseInt(w) - 1;
						//\\//System.out.println("number = " + n);
						//anchorDialog = new AnchorDialog(null, AlignGui.this.model, n);
						anchorDialog = new AnchorDialog(null, AlignGui.this, n);
						anchorDialog.setLocationRelativeTo(AlignGui.this);
						anchorDialog.setVisible(true);
						if (anchorDialog.approved) {
							//anchorFilenameLabel.setText("yyy");   //    // ### dialog takes care of setting file name in gui
							AlignGui.this.model.compare = new Compare();
						} else {
							//anchorFilenameLabel.setText("");   // ### old value should be left alone
						}
					} catch (Exception ex) {
					}
				} else {
					//\\//System.out.println("Clicked outside lines");
				}

			}

		};
		//matchInfoTextArea.addMouseListener(matchInfoTextAreaMouseListener);
		matchInfoList.addMouseListener(matchInfoListMouseListener);

		// tool tip

		//saveAllFileButton.setToolTipText("Save texts");
		saveAllFileButton.setToolTipText("Save aligned result");
		purgeButton.setToolTipText("Claer all data from the system and make ready for new input files");
		anchorFileButton.setToolTipText("Select and/or edit anchor list");
		//anchorFilenameLabel.setToolTipText("
		//skip11CheckBox.setToolTipText("When this box is ticked, alignment will proceed automatically as long as suggested alignments are 1-1");
		modeRadioButtonPanel.setToolTipText("Select between various modes ...blah blah...");
		unalignButton.setToolTipText("Drop latest alignment");
		alignButton.setToolTipText("Accept the alignment(s) under manual consideration");
		//editButton.setToolTipText("Edit the current elements");
		settingsButton.setToolTipText("Set various parameters");
		//logButton.setToolTipText("Turn logging on or off");
		startLoggingButton.setToolTipText("Start logging");
		stopLoggingButton.setToolTipText("Stop logging");
		breakButton.setToolTipText("Break alignment process");   // 2006--08-15
		skipButton.setToolTipText("Skip already aligned elements (relevant when opening half-aligned texts)");
		//changeButton.setToolTipText("Test av endring av layout");
		//&&//correspButton.setToolTipText("Edit the correspondences between the current elements");
		//linkButton.setToolTipText("Link the selected elements");
		//batchButton.setToolTipText("Get several unaligned elements for alignment");
		suggestButton.setToolTipText("Suggest elements to align");
		//matchInfoTextArea.setToolTipText("<html>Information about how well the elements under manual consideration match,<br>nwith details about anchor word matches, Dice, etc.<br>Note: The information is based solely on the elements under consideration.<br>There is no look-ahead.<br>Note: The elements under consideration may belong to more than one alignment<br>(they have more than one colour), but this box doesn't know anything about that</html>");
		matchInfoList.setToolTipText("<html>Information about how well the elements under manual consideration match,<br>nwith details about anchor word matches, Dice, etc.<br>Note: The information is based solely on the elements under consideration.<br>There is no look-ahead.<br>Note: The elements under consideration may belong to more than one alignment<br>(they have more than one colour), but this box doesn't know anything about that</html>");

        for (int t=0; t<Alignment.NUM_FILES; t++) {

			openFileButton[t].setToolTipText("Open text " + (t+1));
			//saveFileButton[t].setToolTipText("Save text " + (t+1));

			alignedListBox[t].setToolTipText("Contains the aligned elements of text " + (t+1));

			toAlignListBox[t].setToolTipText("<html>Contains the element(s) under manual consideration for alignment, from text " + (t+1) + ".<br>Click elements to include them in alignments<html>");
			////toAlignListBox[t].setVisible(false);

			moreButton[t].setToolTipText("Move one unaligned element up in " + (t+1) + ". file");
			lessButton[t].setToolTipText("Drop one element under consideration in " + (t+1) + ". file");

			unalignedListBox[t].setToolTipText("Contains the not yet aligned elements of text " + (t+1));

		}

		////////////
		// layout //
		////////////

        layout = new GridBagLayout();
        setLayout(layout);
        GridBagConstraints c = new GridBagConstraints();
        c.insets = new Insets(3,3,3,3);
		c.anchor = GridBagConstraints.NORTH;
        AwtUtil util = new AwtUtil(this, layout, c);

        //// colours
        // set background colour

        /* Girlie Edition colours
        //Color[] bgColors = { Color.pink, Color.yellow, Color.white, Color.cyan };   // ### disse kan ikke bli .brighter()
        Color[] bgColors = { Color.pink, Color.yellow, Color.cyan };   // ### disse kan ikke bli .brighter()
        Random rand = new Random();
        int r = rand.nextInt(100000) % bgColors.length;
        this.setBackground(bgColors[r]);

        //Color buttonColor = this.getBackground().darker();
        int r2;
        do {
	        r2 = rand.nextInt(100000) % bgColors.length;
		} while (r2 == r);
        Color buttonColor = bgColors[r2];

        int r3;
        do {
	        r3 = rand.nextInt(100000) % bgColors.length;
		} while ((r3 == r) || (r3 == r2));
        Color buttonTextColor = bgColors[r3];
        */

        //// Marlï¿½'s colours
        //Color bgColor = new Color(0xF5DEB3);   // #F5DEB3

        this.setBackground(bgColor); // ### kommenterte ut denne for ï¿½prve bakgrunnsbilde isteden. fikk det til. se Alignment.java og neste linje
        //this.setOpaque(false);   // trenger denne for bakgrunnsbilde

        //Color buttonColor = new Color(0x94BA45);   // #94BA45
        //Color buttonTextColor = new Color(0x006400);   // #006400

        // tenkte jeg skulle ha en felles farge pï¿½det som har med to-align ï¿½gjre, siden det ikke stï¿½ pï¿½linje.
        // men det skjedde bisarre ting nï¿½ jeg gjorde dette. var det noe som skinte igjennom? (har lav alpha.)
        // er det noe feil i grensesnittet? prvde med to-align + dens scroll usynlig, men sï¿½ikke noe da.
        /*Color paleGreen = new Color(0, 255, 0, 5);
        for (int t=0; t<Alignment.NUM_FILES; t++) {
	        toAlignListBox[t].setBackground(paleGreen);
		}
		matchInfoTextArea.setBackground(paleGreen);*/

        //

		/*menu*/
		menuBar.setBackground(buttonColor);
		//menuBar.setForeground(buttonTextColor);   funker ikke

		// (reused)

        JScrollPane s;

		// first row - file buttons and labels

		c.gridy = FILE_ROW;
		c.weighty = FILE_ROW_WEIGHT;

        for (int t=0; t<Alignment.NUM_FILES; t++) {

			c.gridx = TEXT_COLS[t];
			c.gridwidth = 1;
			c.weightx = TEXT_COL_WEIGHT;
			c.fill = GridBagConstraints.HORIZONTAL;

			// color
			openFileButton[t].setBackground(buttonColor);
			openFileButton[t].setForeground(buttonTextColor);
			//saveFileButton[t].setBackground(buttonColor);
			//saveFileButton[t].setForeground(buttonTextColor);

			Box b1 = new Box(BoxLayout.X_AXIS);
			if (t<Alignment.NUM_FILES-1) {
				b1.add(openFileButton[t]);
				b1.add(Box.createHorizontalGlue());
				b1.add(filenameLabel[t]);
				b1.add(Box.createHorizontalGlue());
			} else {
				b1.add(Box.createHorizontalGlue());
				b1.add(filenameLabel[t]);
				b1.add(Box.createHorizontalGlue());
				b1.add(openFileButton[t]);
			}
			//b1.add(saveFileButton[t]);

			/*
			JPanel b1 = new JPanel();
			b1.add(BorderLayout.WEST, openFileButton[t]);
			b1.add(BorderLayout.CENTER, filenameLabel[t]);
			b1.add(BorderLayout.EAST, saveFileButton[t]);
			*/

			b1.setOpaque(false);

			util.addInGridBag(b1);

			//  hvordan fï¿½ jeg dette til ï¿½virke
			// skal naturligvis ikke ha det sï¿½smalt som 20 pixler, men...
			//filenameLabel[t].setMaximumSize(new Dimension(100, filenameLabel[t].getHeight()));  // her skjedde det forresten noe. height-settingen frte til at ikke noe viste. bredden endret seg nï¿½ filnavnet ble satt inn, men ingenting viste
			//filenameLabel[t].setMaximumSize(new Dimension(20, 100));

		}

		c.gridx = DO_COL;
		c.gridwidth = 1;
		c.weightx = DO_COL_WEIGHT;
		//c.fill = GridBagConstraints.BOTH;
		c.fill = GridBagConstraints.NONE;

		//  options

		{
			// color
			//anchorFileButton.setBackground(buttonColor);
			saveAllFileButton.setBackground(buttonColor);
			saveAllFileButton.setForeground(buttonTextColor);
			purgeButton.setBackground(buttonColor);
			purgeButton.setForeground(buttonTextColor);

			savePurgePanel.setBackground(this.getBackground());
			savePurgePanel.add(saveAllFileButton);
			savePurgePanel.add(purgeButton);
			savePurgePanel.setAlignmentX(0.0f);   // ###

			savePurgePanel.setOpaque(false);

			Box b = new Box(BoxLayout.X_AXIS);
			//b.add(anchorFileButton);
			//b.add(Box.createVerticalGlue());
			//b.add(anchorFilenameLabel);
			//b.add(saveAllFileButton);
			b.add(savePurgePanel);

			b.setOpaque(false);

			util.addInGridBag(b);
		}

		// second row - aligned elements

		c.gridy = ALIGNED_ROW;
		c.weighty = ALIGNED_ROW_WEIGHT;

        for (int t=0; t<Alignment.NUM_FILES; t++) {

			c.gridx = TEXT_COLS[t];
			c.gridwidth = 1;
			c.weightx = TEXT_COL_WEIGHT;
			c.fill = GridBagConstraints.BOTH;

			//s = new JScrollPane(alignedListBox[t]);
			alignedScrollPane[t] = new JScrollPane(alignedListBox[t]);
			//s.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
			alignedScrollPane[t].setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
			alignedScrollPane[t].setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);   // 2006-09-15

			//util.addInGridBag(s);
			util.addInGridBag(alignedScrollPane[t]);

		}

		c.gridx = DO_COL;
		c.gridwidth = 1;
		c.weightx = DO_COL_WEIGHT;
		c.fill = GridBagConstraints.BOTH;

		// color
		anchorFileButton.setBackground(buttonColor);
		anchorFileButton.setForeground(buttonTextColor);
		settingsButton.setBackground(buttonColor);
		settingsButton.setForeground(buttonTextColor);
		settingsPanel.setBackground(this.getBackground());
		logPanel.setBackground(this.getBackground());
		//logButton.setBackground(buttonColor);
		//logButton.setForeground(buttonTextColor);
		startLoggingButton.setBackground(buttonColor);
		startLoggingButton.setForeground(buttonTextColor);
		startLoggingButton.setVisible(!model.logging);
		stopLoggingButton.setBackground(buttonColor);
		stopLoggingButton.setForeground(buttonTextColor);
		stopLoggingButton.setVisible(model.logging);
		breakButton.setBackground(buttonColor);   // 2006-08-15
		breakButton.setForeground(buttonTextColor);   // 2006-08-15
		skipButton.setBackground(buttonColor);
		skipButton.setForeground(buttonTextColor);
		//skip11Panel.setBackground(this.getBackground());
		skipPanel.setForeground(buttonTextColor);
		skipPanel.setBackground(this.getBackground());
		breakPanel.setForeground(buttonTextColor);   // 2006-08-15
		breakPanel.setBackground(this.getBackground());   // 2006-08-15
		runPanel.setBackground(this.getBackground());
		//skip11CheckBox.setBackground(this.getBackground());
		//skip11LimitLabel1.setBackground(this.getBackground());
		runLimitLabel1.setBackground(this.getBackground());
		runLimitLabel1.setFont(plainFont);
		//skip11LimitLabel2.setBackground(this.getBackground());
		runLimitLabel2.setBackground(this.getBackground());
		runLimitLabel2.setFont(plainFont);
		modeRadioButtonPanel.setBackground(this.getBackground());
		//###men hva med bg til komp inni panelet? knappene fï¿½ grï¿½bakgrunn

		//changeButton.setBackground(buttonColor);
		//...;
		unalignButton.setBackground(buttonColor);
		unalignButton.setForeground(buttonTextColor);
		alignButton.setBackground(buttonColor);
		alignButton.setForeground(buttonTextColor);

		//Box anchorBox = new Box(BoxLayout.X_AXIS);
		//anchorBox.add(anchorFileButton);
		//anchorBox.add(Box.createHorizontalStrut(6));
		//anchorBox.add(anchorFilenameLabel);

		Box anchorFileBox = new Box(BoxLayout.Y_AXIS);
		anchorFileBox.add(anchorFileButton);
		anchorFileBox.add(anchorFilenameLabel);

		Box settingsFileBox = new Box(BoxLayout.Y_AXIS);   // 2006-09-21
		settingsFileBox.add(settingsButton);   // 2006-09-21
		settingsFileBox.add(settingsFilenameLabel);   // 2006-09-21

		// save some space and make things tidier
		// by having the anchor and settings buttons side by side
		//Box settingsBox = new Box(BoxLayout.X_AXIS);
		//settingsBox.add(anchorFileButton);
		//settingsPanel.add(anchorFileButton);
		settingsPanel.add(anchorFileBox);
		//settingsBox.add(Box.createHorizontalStrut(6));
		//settingsBox.add(settingsButton);
		//settingsPanel.add(settingsButton);
		settingsPanel.add(settingsFileBox);   // 2006-09-21
		settingsPanel.setAlignmentX(0.0f);   // ###
		settingsPanel.setAlignmentY(0.0f);   // ### hjalp ikke. hadde hï¿½et at knappen ble stï¿½nde i flukt med anker-knappen, ogsï¿½etter at ankerfil valgt
		settingsPanel.setOpaque(false);
		////settingsPanel.add(anchorFileButton);

		Box logButtonsBox = new Box(BoxLayout.Y_AXIS);
		logButtonsBox.add(startLoggingButton);
		logButtonsBox.add(stopLoggingButton);
		Box logBox = new Box(BoxLayout.Y_AXIS);
		logBox.add(logButtonsBox);
		logBox.add(logFilenameLabel);
		logPanel.add(logBox);
		logPanel.setAlignmentX(0.0f);   // ###
		logPanel.setOpaque(false);

		//skip11Panel.add(skip11CheckBox);
		//skip11Panel.add(skip11LimitLabel1);
		//skip11Panel.add(skip11LimitTextField);
		//skip11Panel.add(skip11LimitLabel2);
		//modeRadioButtonPanel
		runPanel.add(runLimitLabel1);
		runPanel.add(runLimitTextField);
		runPanel.add(runLimitLabel2);

		//skip11Panel.setAlignmentX(0.0f);   // ###without this the panel aligns left and forces the buttons in the same box rightwards
		modeRadioButtonPanel.setAlignmentX(0.0f);   // ###
		modeRadioButtonPanel.setOpaque(false);
		runPanel.setAlignmentX(0.0f);   // ###
		runPanel.setOpaque(false);

		//Box modeBox = new Box(BoxLayout.Y_AXIS);
		//modePanel.add(modeRadioButtonPanel);
		//modePanel.add(runPanel);
		//modeBox.add(modeRadioButtonPanel);
		//modeBox.add(runPanel);

		skipPanel.add(skipButton);
		skipPanel.setAlignmentX(0.0f);   // ###

		skipPanel.setOpaque(false);

		breakPanel.add(breakButton);   // 2006-08-15
		breakPanel.setAlignmentX(0.0f);   // ###    // 2006-08-15

		breakPanel.setOpaque(false);   // 2006-08-15

		//unalignButton.setMaximumSize(new Dimension(Integer.MAX_VALUE, 0));   // kan se ut som 0 blir ignorert, men det er bare bredden jeg vil sette
		unalignButton.setMaximumSize(new Dimension(300, 0));
		//alignButton.setMaximumSize(new Dimension(Integer.MAX_VALUE, 0));   // kan se ut som 0 blir ignorert, men det er bare bredden jeg vil sette
		alignButton.setMaximumSize(new Dimension(300, 0));
		// (((moved alignButton down))) (((and up again)))

		Box b2 = new Box(BoxLayout.Y_AXIS);
		//b2.add(editButton);
		//b2.add(anchorFileButton);
		//b2.add(settingsBox);
		b2.add(Box.createVerticalGlue());
		b2.add(settingsPanel);
		b2.add(logPanel);
		//b2.add(anchorFilenameLabel);
		//b2.add(anchorBox);
		//b2.add(Box.createVerticalStrut(6));
		//b2.add(settingsButton);
		//b2.add(changeButton);
		//b2.add(skipBox);
		//b2.add(skip11Panel);
		//b2.add(modeRadioButtonPanel);
		//b2.add(modeBox);
		//b2.add(Box.createVerticalGlue());
		b2.add(skipPanel);
		b2.add(Box.createVerticalGlue());
		//b2.add(Box.createVerticalStrut(6));
		b2.add(modeRadioButtonPanel);
		b2.add(runPanel);
		//b2.add(skipButton);
		b2.add(Box.createVerticalGlue());
		b2.add(Box.createVerticalStrut(6));
		b2.add(unalignButton);
		b2.add(Box.createVerticalStrut(6));
		b2.add(alignButton);

		b2.setOpaque(false);

		util.addInGridBag(b2);

		// for resizing purposes
		row2 = new Component[Alignment.NUM_FILES + 1];
		row2[0] = alignedListBox[0];
		row2[1] = b2;
		row2[2] = alignedListBox[1];
		row2weighty = c.weighty;

		// third row - elements under consideration for alignment

		c.gridy = WORK_ROW;
		c.weighty = WORK_ROW_WEIGHT;

        for (int t=0; t<Alignment.NUM_FILES; t++) {

			c.gridx = TEXT_COLS[t];
			c.gridwidth = 1;
			c.weightx = TEXT_COL_WEIGHT;
			c.fill = GridBagConstraints.BOTH;

			//s = new JScrollPane(toAlignListBox[t]);
			toAlignScrollPane[t] = new JScrollPane(toAlignListBox[t]);
			//s.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
			toAlignScrollPane[t].setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
			toAlignScrollPane[t].setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);   // 2006-09-15
			////s.setVisible(false);

			//util.addInGridBag(s);
			util.addInGridBag(toAlignScrollPane[t]);

		}

		// (((matchInfoScrollPane moved to fifth row)))

		//alignButton.setBackground(buttonColor);
		//alignButton.setForeground(buttonTextColor);

		c.gridx = DO_COL;
		c.gridwidth = 1;
		c.weightx = DO_COL_WEIGHT;
		c.fill = GridBagConstraints.BOTH;

		//Box b3 = new Box(BoxLayout.Y_AXIS);
		Box b3 = new Box(BoxLayout.X_AXIS);
		////&&//b3.add(correspButton);
		////b3.add(linkButton);
		////b3.add(alignArrow);
		//b3.add(anchorWordMatches);
		//b3.add(alignButton);
		//alignButton.setMaximumSize(new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE));
		compareInfoScrollPane.setMaximumSize(new Dimension(300, Integer.MAX_VALUE));
		b3.add(compareInfoScrollPane);

		b3.setOpaque(false);

		util.addInGridBag(b3);

		// for resizing purposes
		row3 = new Component[Alignment.NUM_FILES + 1];
		row3[0] = toAlignListBox[0];
		//row3[1] = anchorWordMatchesScrollPane;
		//row3[1] = matchInfoScrollPane;
		//row3[2] = toAlignListBox[1];
		row3[1] = toAlignListBox[1];

		// fourth row - less/more buttons

		c.gridy = CHANGE_ROW;
		c.weighty = CHANGE_ROW_WEIGHT;

        for (int t=0; t<Alignment.NUM_FILES; t++) {

			c.gridx = TEXT_COLS[t];
			c.gridwidth = 1;
			c.weightx = TEXT_COL_WEIGHT;
			c.fill = GridBagConstraints.HORIZONTAL;

			// color
			lessButton[t].setBackground(buttonColor);
			lessButton[t].setForeground(buttonTextColor);
			moreButton[t].setBackground(buttonColor);
			moreButton[t].setForeground(buttonTextColor);

			Box b = new Box(BoxLayout.X_AXIS);
			//b.add(moreLessArrow[t]);
			//b.add(Box.createHorizontalGlue());
			lessButton[t].setMaximumSize(new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE));
			moreButton[t].setMaximumSize(new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE));
			if (t == 0) {
				b.add(lessButton[t]);
			} else {
				b.add(moreButton[t]);
			}
			//b.add(Box.createHorizontalGlue());
			//b.add(Box.createRigidArea(new Dimension(5, 0)));
			b.add(Box.createRigidArea(new Dimension(6, 0)));   // 6 passer bedre siden insets er 3
			if (t == 0) {
				b.add(moreButton[t]);
			} else {
				b.add(lessButton[t]);
			}

			/*
			JPanel b = new JPanel();
			b.add(BorderLayout.WEST, lessButton[t]);
			//b.add(BorderLayout.CENTER, moreLessArrow[t]);
			b.add(BorderLayout.EAST, moreButton[t]);
			*/

			b.setOpaque(false);

			util.addInGridBag(b);

		}

		c.gridx = DO_COL;
		c.gridwidth = 1;
		c.weightx = DO_COL_WEIGHT;
		c.fill = GridBagConstraints.HORIZONTAL;

		// color
		suggestButton.setBackground(buttonColor);
		suggestButton.setForeground(buttonTextColor);

		Box b5 = new Box(BoxLayout.Y_AXIS);
		//b5.add(batchButton);
		b5.add(suggestButton);
		//suggestButton.setMaximumSize(new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE));
		suggestButton.setMaximumSize(new Dimension(300, Integer.MAX_VALUE));

		b5.setOpaque(false);

		util.addInGridBag(b5);

		/*
		c.gridx = DO_COL;
		c.gridwidth = 1;
		c.weightx = DO_COL_WEIGHT;
		c.fill = GridBagConstraints.BOTH;

		util.addInGridBag(new JPanel());
		*/

		// fifth row - unaligned elements

		c.gridy = UNALIGNED_ROW;
		c.weighty = UNALIGNED_ROW_WEIGHT;

        for (int t=0; t<Alignment.NUM_FILES; t++) {

			c.gridx = TEXT_COLS[t];
			c.gridwidth = 1;
			c.weightx = TEXT_COL_WEIGHT;
			c.fill = GridBagConstraints.BOTH;

			//s = new JScrollPane(unalignedListBox[t]);
			unalignedScrollPane[t] = new JScrollPane(unalignedListBox[t]);
			//s.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
			unalignedScrollPane[t].setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
			unalignedScrollPane[t].setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);   // 2006-09-15

			//util.addInGridBag(s);
			util.addInGridBag(unalignedScrollPane[t]);

	        //System.out.print("width:");
	        //System.out.println(unalignedListBox[t].getFixedCellWidth());

		}

		// (((suggest button moved to fourth row)))

		c.gridx = DO_COL;
		c.gridwidth = 1;
		//c.gridheight = 2;   // 
		c.weightx = DO_COL_WEIGHT;
		c.fill = GridBagConstraints.BOTH;

		//anchorWordMatchesScrollPane.setMinimumSize(new Dimension(MIN_DO_WIDTH, MIN_WORK_HEIGHT));
		//matchInfoScrollPane.setMinimumSize(new Dimension(MIN_DO_WIDTH, MIN_WORK_HEIGHT));
		compareInfoScrollPane.setMinimumSize(new Dimension(MIN_DO_WIDTH, MIN_WORK_HEIGHT));
		//compareInfoPanel.setMinimumSize(new Dimension(MIN_DO_WIDTH, MIN_WORK_HEIGHT));
		//matchInfoTextArea.setMinimumSize(new Dimension(MIN_DO_WIDTH, MIN_WORK_HEIGHT));

		//util.addInGridBag(anchorWordMatchesScrollPane);
		matchInfoScrollPane.setMaximumSize(new Dimension(300, Integer.MAX_VALUE));   // ### virker ikke. blir ca 382
		                                                                             // ### men det er visst noe annet sin feil!!!
		//JPanel trick = new JPanel();
		//trick.add(matchInfoScrollPane);
		//trick.setMaximumSize(new Dimension(300, Integer.MAX_VALUE)); ### helt pï¿½trynet
		util.addInGridBag(matchInfoScrollPane);
		//util.addInGridBag(trick);

		// for resizing purposes
		row5 = new Component[Alignment.NUM_FILES + 1];
		row5[0] = unalignedListBox[0];
		//row5[1] = b5;
		row5[1] = matchInfoScrollPane;
		row5[2] = unalignedListBox[1];
		row5weighty = c.weighty;

		//c.gridheight = 1;   // 

		// sixth row - status line

		c.gridy = STATUS_ROW;
		c.weighty = STATUS_ROW_WEIGHT;

		c.gridx = 0;
		c.gridwidth = GridBagConstraints.REMAINDER;
		c.weightx = 0;
		c.fill = GridBagConstraints.BOTH;

		util.addInGridBag(statusLine);

		// ...

		// test - bind keystrokes to actions.  ikke testet pï¿½nytt

		/*
		//getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("typed q"), "Open file 1");
		//getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke('q'), "Open file 1");
		//openFileButton[0].getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke('q'), "Open file 1");
		getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke('q'), "Open file 1");
		//getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("typed w"), "Save file 1");
		getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("F12"), "Save file 1");
		*/
		/*
		getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("typed o"), "openFile_2_action");
		getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("typed p"), "saveFile_2_action");
		getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("typed g"), "align_action");
		//getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("pressed z"), "less_1_action");   // pressed funker ikke
		//getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("released z"), "less_1_action_end");
		getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("typed z"), "less_1_action");
		getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("typed x"), "more_1_action");
		getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("typed n"), "less_2_action");
		getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("typed m"), "more_2_action");
		*/

		// test - add the actions to the components

		// h - dette var ikke ndvendig for ï¿½fï¿½menyene til ï¿½funke...

		/*
		System.out.println("getActionMap().size()=" + getActionMap().size());   // =0. mine actions er altsï¿½ikke i ActionMap
		getActionMap().put("Open file 1", openActions[0]);
		System.out.println("getActionMap().size()=" + getActionMap().size());   // =1
		getActionMap().put("save file 1", saveActions[0]);
		*/

		/*
		getActionMap().put("openFile_2_action", new AbstractAction("openFile_2_action") {
			public void actionPerformed(ActionEvent e) {
				Toolkit.getDefaultToolkit().beep();
			}
		});
		getActionMap().put("saveFile_2_action", new AbstractAction("saveFile_2_action") {
			public void actionPerformed(ActionEvent e) {
				Toolkit.getDefaultToolkit().beep();
			}
		});
		getActionMap().put("align_action", new AbstractAction("align_action") {
			public void actionPerformed(ActionEvent e) {
				Toolkit.getDefaultToolkit().beep();
			}
		});
		getActionMap().put("less_1_action", new AbstractAction("less_1_action") {
			public void actionPerformed(ActionEvent e) {
				arrow_1.setText("v");
				//currentThread().sleep(200); hvordan?
				//arrow_1.setText("");
			}
		});
		//-
		getActionMap().put("less_1_action_end", new AbstractAction("less_1_action_end") {
			public void actionPerformed(ActionEvent e) {
				arrow_1.setText("");
			}
		});
		-//
		getActionMap().put("more_1_action", new AbstractAction("more_1_action") {
			public void actionPerformed(ActionEvent e) {
				arrow_1.setText("^");
			}
		});
		getActionMap().put("less_2_action", new AbstractAction("less_2_action") {
			public void actionPerformed(ActionEvent e) {
				arrow_2.setText("v");
			}
		});
		getActionMap().put("more_2_action", new AbstractAction("more_2_action") {
			public void actionPerformed(ActionEvent e) {
				arrow_2.setText("^");
			}
		});
		*/

		// dialogs.
		// eller skal disse lages frst nï¿½ det er bruk for dem?
		// ja, hvordan skal de ellers fï¿½riktig owner (parent)?

		//correspDialog = new CorrespDialog(null);

		// members for remembering current open and save folders

		model.currentOpenDirectory = null;
		model.currentSaveDirectory = null;

		// TEST

		/*InputMap inputMap = anchorFilenameLabel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
		inputMap.put(KeyStroke.getKeyStroke('l'), "label");
		inputMap.put(KeyStroke.getKeyStroke('L'), "label1");
		anchorFilenameLabel.getActionMap().put("label", new TestAbstractAction("lll"));
		anchorFilenameLabel.getActionMap().put("label1", new TestAbstractAction("LLLLL"));*/

		/*
		InputMap inputMap = openFileButton[0].getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
		inputMap.put(KeyStroke.getKeyStroke('l'), "label");
		*/
		//openFileButton[0].getActionMap().put("label", new TestAbstractAction("lll"));  // denne funket. men jeg nsker jo ï¿½bruke min egen, eksisterende action
		//openFileButton[0].getActionMap().put("label", openActions[0]);  // denne funket ikke
		/*openFileButton[0].getActionMap().put(
			"label",
			new OpenAction(
				"Open file 1",
				createImageIcon("images/Read.gif", "read from disc"),
				"Open file 1",
				new Integer(0)
			)
		); funker ikke*/

		/*
		// ###fï¿½ bare 0. for tidlig
		System.out.println("alignedListBox[0].getWidth() = " + alignedListBox[0].getWidth());
		System.out.println("alignedListBox[1].getWidth() = " + alignedListBox[1].getWidth());
		System.out.println("toAlignListBox[0].getWidth() = " + toAlignListBox[0].getWidth());
		System.out.println("toAlignListBox[1].getWidth() = " + toAlignListBox[1].getWidth());
		System.out.println("unalignedListBox[0].getWidth() = " + unalignedListBox[0].getWidth());
		System.out.println("unalignedListBox[1].getWidth() = " + unalignedListBox[1].getWidth());
		System.out.println("unalignedScrollPane[0].getWidth() = " + unalignedScrollPane[0].getWidth());
		System.out.println("unalignedScrollPane[1].getWidth() = " + unalignedScrollPane[1].getWidth());
		*/



    } //end constructor


	// 
	/* flytter den til model
    private void loadFile(File f, int t) {
        if (model.loadFile(f, t)) {
            // get some datastructure with all the s-nodes
            //NodeList elements = model.getElements(t);
            AElement[] myElements = model.getMyElements(t);
            //fill the bottom list with these elements
            DefaultListModel lm = null;
			toAlignModel[t].clear();
			alignedModel[t].clear();
			unalignedModel[t].clear();
            //System.out.println(elements.getLength() + " elements");
            System.out.println(myElements.length + " elements");
            //for (int i=0; i<elements.getLength(); ++i) {
            for (int i=0; i<myElements.length; ++i) {
                //unalignedModel[t].addElement(elements.item(i));
                unalignedModel[t].addElement(myElements[i]);
            }
        }
    }
    */


} //end class AlignGui


