Finished "Colors" preference page. Need to update terminal colors when
preferences change.
diff --git a/com.google.eclipse.terminal.local/plugin.xml b/com.google.eclipse.terminal.local/plugin.xml
index 1e777ec..9cb63c4 100644
--- a/com.google.eclipse.terminal.local/plugin.xml
+++ b/com.google.eclipse.terminal.local/plugin.xml
@@ -49,5 +49,11 @@
             name="Local Terminal Colors">
       </page>
    </extension>
+   <extension
+         point="org.eclipse.core.runtime.preferences">
+      <initializer
+            class="com.google.eclipse.terminal.local.ui.preferences.PreferenceInitializer">
+      </initializer>
+   </extension>
 
 </plugin>
diff --git a/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/Activator.java b/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/Activator.java
index 562dc7d..4cbb715 100644
--- a/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/Activator.java
+++ b/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/Activator.java
@@ -11,6 +11,7 @@
 import static org.eclipse.core.runtime.IStatus.*;
 
 import org.eclipse.core.runtime.*;
+import org.eclipse.jface.preference.IPreferenceStore;
 import org.eclipse.ui.plugin.AbstractUIPlugin;
 import org.osgi.framework.BundleContext;
 
@@ -39,10 +40,14 @@
   }
 
   public static void log(IStatus status) {
-    getDefault().getLog().log(status);
+    instance().getLog().log(status);
   }
 
-  public static Activator getDefault() {
+  public static Activator instance() {
     return plugin;
   }
+
+  public static IPreferenceStore preferenceStore() {
+    return instance().getPreferenceStore();
+  }
 }
diff --git a/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/ui/preferences/AbstractColorPreferencesChangeListener.java b/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/ui/preferences/AbstractColorPreferencesChangeListener.java
new file mode 100644
index 0000000..8b8724e
--- /dev/null
+++ b/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/ui/preferences/AbstractColorPreferencesChangeListener.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2012 Google Inc.
+ *
+ * All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse
+ * Public License v1.0 which accompanies this distribution, and is available at
+ *
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package com.google.eclipse.terminal.local.ui.preferences;
+
+import static com.google.eclipse.terminal.local.ui.preferences.PreferenceNames.*;
+
+import org.eclipse.jface.util.*;
+
+/**
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+public abstract class AbstractColorPreferencesChangeListener implements IPropertyChangeListener {
+  @Override public final void propertyChange(PropertyChangeEvent event) {
+    String property = event.getProperty();
+    if (BACKGROUND_COLOR.equals(property) || FOREGROUND_COLOR.equals(property)) {
+      onColorChanged();
+    }
+  }
+
+  protected abstract void onColorChanged();
+}
diff --git a/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/ui/preferences/ColorPreferences.java b/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/ui/preferences/ColorPreferences.java
new file mode 100644
index 0000000..fc7b6c4
--- /dev/null
+++ b/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/ui/preferences/ColorPreferences.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2012 Google Inc.
+ *
+ * All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse
+ * Public License v1.0 which accompanies this distribution, and is available at
+ *
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package com.google.eclipse.terminal.local.ui.preferences;
+
+import static com.google.eclipse.terminal.local.Activator.preferenceStore;
+import static com.google.eclipse.terminal.local.ui.preferences.PreferenceNames.*;
+
+import org.eclipse.jface.preference.PreferenceConverter;
+import org.eclipse.swt.graphics.RGB;
+
+/**
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+public class ColorPreferences {
+
+  public static RGB background() {
+    return PreferenceConverter.getColor(preferenceStore(), BACKGROUND_COLOR);
+  }
+
+  public static RGB foreground() {
+    return PreferenceConverter.getColor(preferenceStore(), FOREGROUND_COLOR);
+  }
+}
diff --git a/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/ui/preferences/ColorsPreferencePage.java b/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/ui/preferences/ColorsPreferencePage.java
index 1f79486..00cbf98 100644
--- a/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/ui/preferences/ColorsPreferencePage.java
+++ b/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/ui/preferences/ColorsPreferencePage.java
@@ -8,10 +8,12 @@
  */
 package com.google.eclipse.terminal.local.ui.preferences;
 
-import static com.google.eclipse.terminal.local.Activator.log;
+import static com.google.eclipse.terminal.local.Activator.*;
+import static com.google.eclipse.terminal.local.ui.preferences.PreferenceNames.*;
 import static org.eclipse.jface.preference.ColorSelector.PROP_COLORCHANGE;
 import static org.eclipse.swt.SWT.*;
 
+import java.io.InputStream;
 import java.util.Scanner;
 
 import org.eclipse.jface.preference.*;
@@ -37,6 +39,7 @@
   }
 
   @Override public void init(IWorkbench workbench) {
+    setPreferenceStore(preferenceStore());
   }
 
   @Override protected Control createContents(Composite parent) {
@@ -63,17 +66,25 @@
     previewerText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
     Cursor arrowCursor = previewerText.getDisplay().getSystemCursor(CURSOR_ARROW);
     previewerText.setCursor(arrowCursor);
-    Display display = getShell().getDisplay();
-    backgroundColorSelector.addListener(new ColorChangeListener(display) {
-      @Override void updateColor(Color color) {
-        previewer.getTextWidget().setBackground(color);
+    backgroundColorSelector.addListener(new ColorChangeListener() {
+      @Override void updateColor(RGB color) {
+        validateInput();
+        if (isValid()) {
+          previewer.getTextWidget().setBackground(newColor(color));
+        }
       }
     });
-    foregroundColorSelector.addListener(new ColorChangeListener(display) {
-      @Override void updateColor(Color color) {
-        previewer.setTextColor(color);
+    foregroundColorSelector.addListener(new ColorChangeListener() {
+      @Override void updateColor(RGB color) {
+        validateInput();
+        if (isValid()) {
+          previewer.setTextColor(newColor(color));
+        }
       }
     });
+    displayValue(BACKGROUND_COLOR, backgroundColorSelector);
+    displayValue(FOREGROUND_COLOR, foregroundColorSelector);
+    updatePreview();
     return contents;
   }
 
@@ -82,7 +93,8 @@
     StringBuilder buffer = new StringBuilder();
     Scanner scanner = null;
     try {
-      scanner = new Scanner(getClass().getResourceAsStream(fileName));
+      InputStream inputStream = getClass().getResourceAsStream(fileName);
+      scanner = new Scanner(inputStream);
       while (scanner.hasNextLine()) {
         String line = scanner.nextLine();
         buffer.append(line).append(lineSeparator);
@@ -97,20 +109,67 @@
     return buffer.toString();
   }
 
-  private static abstract class ColorChangeListener implements IPropertyChangeListener {
-    private final Device device;
-
-    private ColorChangeListener(Device device) {
-      this.device = device;
+  private void validateInput() {
+    if (backgroundColorSelector.getColorValue().equals(foregroundColorSelector.getColorValue())) {
+      setErrorMessage("Background and foreground colors cannot be the same");
+      setValid(false);
+      return;
     }
+    pageIsValid();
+  }
 
+  private void pageIsValid() {
+    setErrorMessage(null);
+    setValid(true);
+  }
+
+  private void displayValue(String preferenceName, ColorSelector colorSelector) {
+    RGB color = PreferenceConverter.getColor(getPreferenceStore(), preferenceName);
+    colorSelector.setColorValue(color);
+  }
+
+  private Color newColor(RGB rgb) {
+    return new Color(display(), rgb);
+  }
+
+  private Display display() {
+    return getShell().getDisplay();
+  }
+
+  @Override public boolean performOk() {
+    storeValue(BACKGROUND_COLOR, backgroundColorSelector);
+    storeValue(FOREGROUND_COLOR, foregroundColorSelector);
+    return true;
+  }
+
+  private void storeValue(String preferenceName, ColorSelector colorSelector) {
+    PreferenceConverter.setValue(getPreferenceStore(), preferenceName, colorSelector.getColorValue());
+  }
+
+  @Override protected void performDefaults() {
+    displayDefaultValue(BACKGROUND_COLOR, backgroundColorSelector);
+    displayDefaultValue(FOREGROUND_COLOR, foregroundColorSelector);
+    updatePreview();
+  }
+
+  private void displayDefaultValue(String preferenceName, ColorSelector colorSelector) {
+    RGB color = PreferenceConverter.getDefaultColor(getPreferenceStore(), preferenceName);
+    colorSelector.setColorValue(color);
+  }
+
+  private void updatePreview() {
+    previewer.getTextWidget().setBackground(newColor(backgroundColorSelector.getColorValue()));
+    previewer.setTextColor(newColor(foregroundColorSelector.getColorValue()));
+  }
+
+  private static abstract class ColorChangeListener implements IPropertyChangeListener {
     @Override public final void propertyChange(PropertyChangeEvent event) {
       if (PROP_COLORCHANGE.equals(event.getProperty())) {
         RGB rgb = (RGB) event.getNewValue();
-        updateColor(new Color(device, rgb));
+        updateColor(rgb);
       }
     }
 
-    abstract void updateColor(Color color);
+    abstract void updateColor(RGB rgb);
   }
 }
diff --git a/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/ui/preferences/PreferenceInitializer.java b/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/ui/preferences/PreferenceInitializer.java
new file mode 100644
index 0000000..6c72331
--- /dev/null
+++ b/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/ui/preferences/PreferenceInitializer.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2012 Google Inc.
+ *
+ * All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse
+ * Public License v1.0 which accompanies this distribution, and is available at
+ *
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package com.google.eclipse.terminal.local.ui.preferences;
+
+import static com.google.eclipse.terminal.local.ui.preferences.PreferenceNames.*;
+
+import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer;
+import org.eclipse.jface.preference.PreferenceConverter;
+import org.eclipse.swt.graphics.RGB;
+
+import com.google.eclipse.terminal.local.Activator;
+
+/**
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+public class PreferenceInitializer extends AbstractPreferenceInitializer {
+  @Override public void initializeDefaultPreferences() {
+    setDefault(BACKGROUND_COLOR, new RGB(0, 0, 0));
+    setDefault(FOREGROUND_COLOR, new RGB(229, 229, 229));
+  }
+
+  private void setDefault(String name, RGB value) {
+    PreferenceConverter.setDefault(Activator.preferenceStore(), name, value);
+  }
+}
diff --git a/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/ui/preferences/PreferenceNames.java b/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/ui/preferences/PreferenceNames.java
new file mode 100644
index 0000000..929dac3
--- /dev/null
+++ b/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/ui/preferences/PreferenceNames.java
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2012 Google Inc.
+ *
+ * All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse
+ * Public License v1.0 which accompanies this distribution, and is available at
+ *
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package com.google.eclipse.terminal.local.ui.preferences;
+
+/**
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+final class PreferenceNames {
+  static final String BACKGROUND_COLOR = "background.color";
+  static final String FOREGROUND_COLOR = "foreground.color";
+
+  private PreferenceNames() {}
+}
diff --git a/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/ui/view/TerminalView.java b/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/ui/view/TerminalView.java
index 5d6b52b..80c1d85 100644
--- a/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/ui/view/TerminalView.java
+++ b/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/ui/view/TerminalView.java
@@ -8,27 +8,25 @@
  */
 package com.google.eclipse.terminal.local.ui.view;
 
-import static com.google.eclipse.terminal.local.Activator.log;
+import static com.google.eclipse.terminal.local.Activator.*;
+import static com.google.eclipse.terminal.local.ui.preferences.ColorPreferences.*;
 import static com.google.eclipse.terminal.local.ui.util.Displays.runInDisplayThread;
 import static com.google.eclipse.terminal.local.ui.view.Messages.defaultViewTitle;
 import static com.google.eclipse.terminal.local.util.Platform.userHomeDirectory;
 import static org.eclipse.core.runtime.Path.fromOSString;
 import static org.eclipse.ui.IWorkbenchPage.VIEW_ACTIVATE;
 
-import com.google.eclipse.terminal.local.core.connector.LifeCycleListener;
-
 import org.eclipse.core.runtime.IPath;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.tm.internal.terminal.control.ITerminalListener;
 import org.eclipse.tm.internal.terminal.provisional.api.TerminalState;
-import org.eclipse.ui.IMemento;
-import org.eclipse.ui.IViewSite;
-import org.eclipse.ui.IWorkbenchPage;
-import org.eclipse.ui.PartInitException;
-import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.*;
 import org.eclipse.ui.part.ViewPart;
 
+import com.google.eclipse.terminal.local.core.connector.LifeCycleListener;
+import com.google.eclipse.terminal.local.ui.preferences.AbstractColorPreferencesChangeListener;
+
 /**
  * @author alruiz@google.com (Alex Ruiz)
  */
@@ -38,6 +36,7 @@
 
   private static final String VIEW_ID = "com.google.eclipse.terminal.local.localTerminalView";
 
+  private ColorPreferencesChangeListener colorPreferencesChangeListener;
   private IMemento savedState;
   private TerminalWidget terminalWidget;
   private IPath workingDirectory;
@@ -85,10 +84,13 @@
         });
       }
 
-  @Override public void setState(TerminalState state) {}
+      @Override public void setState(TerminalState state) {
+      }
     });
     IViewSite viewSite = getViewSite();
     terminalWidget.setUpGlobalEditActionHandlers(viewSite.getActionBars());
+    colorPreferencesChangeListener = new ColorPreferencesChangeListener(terminalWidget);
+    preferenceStore().addPropertyChangeListener(colorPreferencesChangeListener);
     if (savedState != null) {
       connectUsingSavedState();
       return;
@@ -125,4 +127,23 @@
   @Override public void setFocus() {
     terminalWidget.setFocus();
   }
+
+  @Override public void dispose() {
+    if (colorPreferencesChangeListener != null) {
+      preferenceStore().removePropertyChangeListener(colorPreferencesChangeListener);
+    }
+    super.dispose();
+  }
+
+  private static class ColorPreferencesChangeListener extends AbstractColorPreferencesChangeListener {
+    private final TerminalWidget terminalWidget;
+
+    ColorPreferencesChangeListener(TerminalWidget terminalWidget) {
+      this.terminalWidget = terminalWidget;
+    }
+
+    @Override protected void onColorChanged() {
+      terminalWidget.resetTerminalColors(background(), foreground());
+    }
+  }
 }
diff --git a/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/ui/view/TerminalWidget.java b/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/ui/view/TerminalWidget.java
index aed4126..9157b9f 100644
--- a/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/ui/view/TerminalWidget.java
+++ b/com.google.eclipse.terminal.local/src/com/google/eclipse/terminal/local/ui/view/TerminalWidget.java
@@ -15,6 +15,7 @@
 import org.eclipse.jface.action.*;
 import org.eclipse.jface.layout.*;
 import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.RGB;
 import org.eclipse.swt.widgets.*;
 import org.eclipse.tm.internal.terminal.control.ITerminalListener;
 import org.eclipse.tm.internal.terminal.emulator.VT100TerminalControl;
@@ -127,6 +128,10 @@
     return (LocalTerminalConnector) terminalControl.getTerminalConnector().getAdapter(LocalTerminalConnector.class);
   }
 
+  void resetTerminalColors(RGB background, RGB foreground) {
+    terminalControl.resetColors(background, foreground);
+  }
+
   @Override public boolean setFocus() {
     return terminalControl.setFocus();
   }
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/emulator/VT100TerminalControl.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/emulator/VT100TerminalControl.java
index 9cbf1b7..817561c 100644
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/emulator/VT100TerminalControl.java
+++ b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/emulator/VT100TerminalControl.java
@@ -43,7 +43,7 @@
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.dnd.*;
 import org.eclipse.swt.events.*;
-import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.*;
 import org.eclipse.swt.layout.*;
 import org.eclipse.swt.widgets.*;
 import org.eclipse.tm.internal.terminal.control.*;
@@ -1046,4 +1046,8 @@
 	public void setInvertedColors(boolean invert) {
 		fCtlText.setInvertedColors(invert);
 	}
+
+  public void resetColors(RGB background, RGB foreground) {
+    fCtlText.resetColors(background, foreground);
+  }
 }
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/textcanvas/ILinelRenderer.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/textcanvas/ILinelRenderer.java
index 8595b0a..5c28769 100644
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/textcanvas/ILinelRenderer.java
+++ b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/textcanvas/ILinelRenderer.java
@@ -11,8 +11,7 @@
  *******************************************************************************/
 package org.eclipse.tm.internal.terminal.textcanvas;
 
-import org.eclipse.swt.graphics.Color;
-import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.*;
 
 /**
  *
@@ -24,4 +23,5 @@
 	void onFontChange();
 	void setInvertedColors(boolean invert);
 	Color getDefaultBackgroundColor();
+  void resetColors(RGB background, RGB foreground);
 }
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/textcanvas/TextCanvas.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/textcanvas/TextCanvas.java
index ab53f79..787b1f6 100644
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/textcanvas/TextCanvas.java
+++ b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/textcanvas/TextCanvas.java
@@ -28,10 +28,7 @@
 import org.eclipse.swt.events.MouseEvent;
 import org.eclipse.swt.events.MouseListener;
 import org.eclipse.swt.events.MouseMoveListener;
-import org.eclipse.swt.graphics.Color;
-import org.eclipse.swt.graphics.GC;
-import org.eclipse.swt.graphics.Point;
-import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.graphics.*;
 import org.eclipse.swt.widgets.Composite;
 
 /**
@@ -402,5 +399,9 @@
 		}
 
 	}
+
+  public void resetColors(RGB background, RGB foreground) {
+    fCellRenderer.resetColors(background, foreground);
+  }
 }
 
diff --git a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/textcanvas/TextLineRenderer.java b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/textcanvas/TextLineRenderer.java
index e36be51..f098168 100644
--- a/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/textcanvas/TextLineRenderer.java
+++ b/com.google.eclipse.tm.terminal/src/org/eclipse/tm/internal/terminal/textcanvas/TextLineRenderer.java
@@ -14,10 +14,7 @@
 package org.eclipse.tm.internal.terminal.textcanvas;
 
 import org.eclipse.swt.SWT;
-import org.eclipse.swt.graphics.Color;
-import org.eclipse.swt.graphics.Font;
-import org.eclipse.swt.graphics.GC;
-import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.*;
 import org.eclipse.swt.widgets.Display;
 import org.eclipse.tm.terminal.model.ITerminalTextDataReadOnly;
 import org.eclipse.tm.terminal.model.LineSegment;
@@ -161,4 +158,7 @@
 		fStyleMap.setInvertedColors(invert);
 
 	}
+
+	@Override public void resetColors(RGB background, RGB foreground) {
+  }
 }