Remove ThemeData.primarySwatch

In the dark theme, there isn't really a primary swatch, so this API was
a sandtrap. Instead, be explicit about the colors we need for various
widgets in the theme.

Fixes #1277
diff --git a/examples/widgets/card_collection.dart b/examples/widgets/card_collection.dart
index c2683d0..512619d 100644
--- a/examples/widgets/card_collection.dart
+++ b/examples/widgets/card_collection.dart
@@ -300,7 +300,7 @@
       onResized: () { _invalidator(<int>[index]); },
       onDismissed: () { dismissCard(cardModel); },
       child: new Card(
-        color: Theme.of(context).primarySwatch[cardModel.color],
+        color: _primaryColor[cardModel.color],
         child: new Container(
           height: cardModel.height,
           padding: const EdgeDims.all(kCardMargins),
@@ -428,7 +428,7 @@
 
     Widget body = new Container(
       padding: const EdgeDims.symmetric(vertical: 12.0, horizontal: 8.0),
-      decoration: new BoxDecoration(backgroundColor: Theme.of(context).primarySwatch[50]),
+      decoration: new BoxDecoration(backgroundColor: _primaryColor[50]),
       child: cardCollection
     );
 
diff --git a/packages/flutter/lib/src/material/date_picker.dart b/packages/flutter/lib/src/material/date_picker.dart
index 21d9aab..7b74a93 100644
--- a/packages/flutter/lib/src/material/date_picker.dart
+++ b/packages/flutter/lib/src/material/date_picker.dart
@@ -181,8 +181,8 @@
   final DateTime displayedMonth;
 
   Widget build(BuildContext context) {
-    ThemeData theme = Theme.of(context);
-    TextStyle headerStyle = theme.text.caption.copyWith(fontWeight: FontWeight.w700);
+    ThemeData themeData = Theme.of(context);
+    TextStyle headerStyle = themeData.text.caption.copyWith(fontWeight: FontWeight.w700);
     TextStyle monthStyle = headerStyle.copyWith(fontSize: 14.0, height: 24.0 / 14.0);
     TextStyle dayStyle = headerStyle.copyWith(fontWeight: FontWeight.w500);
     DateFormat dateFormat = new DateFormat();
@@ -230,7 +230,7 @@
             selectedDate.month == month &&
             selectedDate.day == day)
           decoration = new BoxDecoration(
-            backgroundColor: theme.primarySwatch[100],
+            backgroundColor: themeData.backgroundColor,
             shape: BoxShape.circle
           );
 
@@ -239,7 +239,7 @@
         if (currentDate.year == year &&
             currentDate.month == month &&
             currentDate.day == day)
-          itemStyle = itemStyle.copyWith(color: theme.primaryColor);
+          itemStyle = itemStyle.copyWith(color: themeData.primaryColor);
 
         item = new GestureDetector(
           onTap: () {
@@ -389,7 +389,7 @@
         child: new Container(
           height: _itemExtent,
           decoration: year == config.selectedDate.year ? new BoxDecoration(
-            backgroundColor: Theme.of(context).primarySwatch[100],
+            backgroundColor: Theme.of(context).backgroundColor,
             shape: BoxShape.circle
           ) : null,
           child: new Center(
diff --git a/packages/flutter/lib/src/material/input.dart b/packages/flutter/lib/src/material/input.dart
index 7f6621b..20b5521 100644
--- a/packages/flutter/lib/src/material/input.dart
+++ b/packages/flutter/lib/src/material/input.dart
@@ -84,9 +84,17 @@
     bool focused = focusContext != null && Focus.at(focusContext, autofocus: config.autofocus);
 
     TextStyle textStyle = config.style ?? themeData.text.subhead;
-    Color focusHighlightColor = themeData.accentColor;
-    if (themeData.primarySwatch != null)
-      focusHighlightColor = focused ? themeData.primarySwatch[400] : themeData.hintColor;
+    Color activeColor = themeData.hintColor;
+    if (focused) {
+      switch (themeData.brightness) {
+        case ThemeBrightness.dark:
+          activeColor = themeData.accentColor;
+          break;
+        case ThemeBrightness.light:
+          activeColor = themeData.primaryColor;
+          break;
+      }
+    }
     double topPadding = config.isDense ? 12.0 : 16.0;
 
     List<Widget> stackChildren = <Widget>[];
@@ -96,7 +104,7 @@
     if (config.labelText != null) {
       TextStyle labelStyle = hasInlineLabel ?
         themeData.text.subhead.copyWith(color: themeData.hintColor) :
-        themeData.text.caption.copyWith(color: focused ? focusHighlightColor : themeData.hintColor);
+        themeData.text.caption.copyWith(color: activeColor);
 
       double topPaddingIncrement = themeData.text.caption.fontSize + (config.isDense ? 4.0 : 8.0);
       double top = topPadding;
@@ -123,13 +131,9 @@
       ));
     }
 
-    Color cursorColor = themeData.primarySwatch == null ?
-      themeData.accentColor :
-      themeData.primarySwatch[200];
-
     EdgeDims margin = new EdgeDims.only(bottom: config.isDense ? 4.0 : 8.0);
     EdgeDims padding = new EdgeDims.only(top: topPadding, bottom: 8.0);
-    Color borderColor = focusHighlightColor;
+    Color borderColor = activeColor;
     double borderWidth = focused ? 2.0 : 1.0;
 
     if (config.errorText != null) {
@@ -160,8 +164,8 @@
         focusKey: focusKey,
         style: textStyle,
         hideText: config.hideText,
-        cursorColor: cursorColor,
-        selectionColor: cursorColor,
+        cursorColor: themeData.selectionColor,
+        selectionColor: themeData.selectionColor,
         keyboardType: config.keyboardType,
         onChanged: config.onChanged,
         onSubmitted: config.onSubmitted
@@ -190,7 +194,7 @@
             width: config.isDense ? 40.0 : 48.0,
             child: new Icon(
               icon: config.icon,
-              color: focused ? focusHighlightColor : Colors.black45,
+              color: focused ? activeColor : Colors.black45,
               size: config.isDense ? IconSize.s18 : IconSize.s24
             )
           ),
diff --git a/packages/flutter/lib/src/material/progress_indicator.dart b/packages/flutter/lib/src/material/progress_indicator.dart
index 866c1ac..7668c68 100644
--- a/packages/flutter/lib/src/material/progress_indicator.dart
+++ b/packages/flutter/lib/src/material/progress_indicator.dart
@@ -22,7 +22,7 @@
 
   final double value; // Null for non-determinate progress indicator.
 
-  Color _getBackgroundColor(BuildContext context) => Theme.of(context).primarySwatch[200];
+  Color _getBackgroundColor(BuildContext context) => Theme.of(context).backgroundColor;
   Color _getValueColor(BuildContext context) => Theme.of(context).primaryColor;
 
   void debugFillDescription(List<String> description) {
diff --git a/packages/flutter/lib/src/material/raised_button.dart b/packages/flutter/lib/src/material/raised_button.dart
index 11a9dcc..3c3decb 100644
--- a/packages/flutter/lib/src/material/raised_button.dart
+++ b/packages/flutter/lib/src/material/raised_button.dart
@@ -74,15 +74,7 @@
 
   Color getColor(BuildContext context) {
     if (config.enabled) {
-      if (config.color != null)
-        return config.color;
-      switch (Theme.of(context).brightness) {
-        case ThemeBrightness.light:
-          return Colors.grey[300];
-        case ThemeBrightness.dark:
-          Map<int, Color> swatch = Theme.of(context).primarySwatch ?? Colors.blue;
-          return swatch[600];
-      }
+      return config.color ?? Theme.of(context).buttonColor;
     } else {
       if (config.disabledColor != null)
         return config.disabledColor;
diff --git a/packages/flutter/lib/src/material/theme_data.dart b/packages/flutter/lib/src/material/theme_data.dart
index f6a80bb..01bfafc 100644
--- a/packages/flutter/lib/src/material/theme_data.dart
+++ b/packages/flutter/lib/src/material/theme_data.dart
@@ -31,9 +31,10 @@
 
   ThemeData.raw({
     this.brightness,
-    this.primarySwatch,
     this.primaryColor,
     this.primaryColorBrightness,
+    this.accentColor,
+    this.accentColorBrightness,
     this.canvasColor,
     this.cardColor,
     this.dividerColor,
@@ -41,8 +42,9 @@
     this.splashColor,
     this.unselectedColor,
     this.disabledColor,
-    this.accentColor,
-    this.accentColorBrightness,
+    this.buttonColor,
+    this.selectionColor,
+    this.backgroundColor,
     this.indicatorColor,
     this.hintColor,
     this.hintOpacity,
@@ -52,9 +54,10 @@
     this.primaryIconTheme
   }) {
     assert(brightness != null);
-    // primarySwatch can be null; TODO(ianh): see https://github.com/flutter/flutter/issues/1277
     assert(primaryColor != null);
     assert(primaryColorBrightness != null);
+    assert(accentColor != null);
+    assert(accentColorBrightness != null);
     assert(canvasColor != null);
     assert(cardColor != null);
     assert(dividerColor != null);
@@ -62,8 +65,9 @@
     assert(splashColor != null);
     assert(unselectedColor != null);
     assert(disabledColor != null);
-    assert(accentColor != null);
-    assert(accentColorBrightness != null);
+    assert(buttonColor != null);
+    assert(selectionColor != null);
+    assert(disabledColor != null);
     assert(indicatorColor != null);
     assert(hintColor != null);
     assert(hintOpacity != null);
@@ -74,10 +78,12 @@
   }
 
   factory ThemeData({
-    ThemeBrightness brightness: ThemeBrightness.light,
+    ThemeBrightness brightness,
     Map<int, Color> primarySwatch,
     Color primaryColor,
     ThemeBrightness primaryColorBrightness,
+    Color accentColor,
+    ThemeBrightness accentColorBrightness,
     Color canvasColor,
     Color cardColor,
     Color dividerColor,
@@ -85,8 +91,9 @@
     Color splashColor,
     Color unselectedColor,
     Color disabledColor,
-    Color accentColor,
-    ThemeBrightness accentColorBrightness: ThemeBrightness.dark,
+    Color buttonColor,
+    Color selectionColor,
+    Color backgroundColor,
     Color indicatorColor,
     Color hintColor,
     double hintOpacity,
@@ -95,10 +102,13 @@
     TextTheme primaryTextTheme,
     IconThemeData primaryIconTheme
   }) {
-    // brightness default is in the arguments list
-    bool isDark = brightness == ThemeBrightness.dark;
-    primaryColor ??= primarySwatch == null ? isDark ? Colors.grey[900] : Colors.grey[100] : primarySwatch[500];
-    primaryColorBrightness ??= primarySwatch == null ? brightness : ThemeBrightness.dark /* swatch[500] is always dark */;
+    brightness ??= ThemeBrightness.light;
+    final bool isDark = brightness == ThemeBrightness.dark;
+    primarySwatch ??= Colors.blue;
+    primaryColor ??= isDark ? Colors.grey[900] : primarySwatch[500];
+    primaryColorBrightness ??= ThemeBrightness.dark;
+    accentColor ??= primarySwatch[500];
+    accentColorBrightness ??= ThemeBrightness.dark;
     canvasColor ??= isDark ? Colors.grey[850] : Colors.grey[50];
     cardColor ??= isDark ? Colors.grey[800] : Colors.white;
     dividerColor ??= isDark ? const Color(0x1FFFFFFF) : const Color(0x1F000000);
@@ -106,8 +116,9 @@
     splashColor ??= isDark ? _kDarkThemeSplashColor : _kLightThemeSplashColor;
     unselectedColor ??= isDark ? Colors.white70 : Colors.black54;
     disabledColor ??= isDark ? Colors.white30 : Colors.black26;
-    accentColor ??= primarySwatch == null ? Colors.blue[500] : primarySwatch[500];
-    // accentColorBrightness default is in the arguments list
+    buttonColor ??= isDark ? primarySwatch[600] : Colors.grey[300];
+    selectionColor ??= isDark ? accentColor : primarySwatch[200];
+    backgroundColor ??= isDark ? Colors.grey[700] : primarySwatch[200];
     indicatorColor ??= accentColor == primaryColor ? Colors.white : accentColor;
     hintColor ??= isDark ? const Color(0x42FFFFFF) : const Color(0x4C000000);
     hintOpacity ??= hintColor != null ? hintColor.alpha / 0xFF : isDark ? 0.26 : 0.30;
@@ -117,9 +128,10 @@
     primaryIconTheme ??= primaryColorBrightness == ThemeBrightness.dark ? const IconThemeData(color: IconThemeColor.white) : const IconThemeData(color: IconThemeColor.black);
     return new ThemeData.raw(
       brightness: brightness,
-      primarySwatch: primarySwatch,
       primaryColor: primaryColor,
       primaryColorBrightness: primaryColorBrightness,
+      accentColor: accentColor,
+      accentColorBrightness: accentColorBrightness,
       canvasColor: canvasColor,
       cardColor: cardColor,
       dividerColor: dividerColor,
@@ -127,8 +139,9 @@
       splashColor: splashColor,
       unselectedColor: unselectedColor,
       disabledColor: disabledColor,
-      accentColor: accentColor,
-      accentColorBrightness: accentColorBrightness,
+      buttonColor: buttonColor,
+      selectionColor: selectionColor,
+      backgroundColor: backgroundColor,
       indicatorColor: indicatorColor,
       hintColor: hintColor,
       hintOpacity: hintOpacity,
@@ -139,7 +152,7 @@
     );
   }
 
-  factory ThemeData.light() => new ThemeData(primarySwatch: Colors.blue, brightness: ThemeBrightness.light);
+  factory ThemeData.light() => new ThemeData(brightness: ThemeBrightness.light);
   factory ThemeData.dark() => new ThemeData(brightness: ThemeBrightness.dark);
   factory ThemeData.fallback() => new ThemeData.light();
 
@@ -155,8 +168,6 @@
   /// dark, use Colors.white or the accentColor for a contrasting color.
   final ThemeBrightness brightness;
 
-  final Map<int, Color> primarySwatch;
-
   /// The background colour for major parts of the app (toolbars, tab bars, etc)
   final Color primaryColor;
 
@@ -164,14 +175,6 @@
   /// icons placed on top of the primary color (e.g. toolbar text).
   final ThemeBrightness primaryColorBrightness;
 
-  final Color canvasColor;
-  final Color cardColor;
-  final Color dividerColor;
-  final Color highlightColor;
-  final Color splashColor;
-  final Color unselectedColor;
-  final Color disabledColor;
-
   /// The foreground color for widgets (knobs, text, etc)
   final Color accentColor;
 
@@ -180,6 +183,17 @@
   /// action button).
   final ThemeBrightness accentColorBrightness;
 
+  final Color canvasColor;
+  final Color cardColor;
+  final Color dividerColor;
+  final Color highlightColor;
+  final Color splashColor;
+  final Color unselectedColor;
+  final Color disabledColor;
+  final Color buttonColor;
+  final Color selectionColor;
+  final Color backgroundColor;
+
   /// The color of the selected tab indicator in a tab strip.
   final Color indicatorColor;
 
@@ -199,18 +213,8 @@
   final IconThemeData primaryIconTheme;
 
   static ThemeData lerp(ThemeData begin, ThemeData end, double t) {
-    Map<int, Color> primarySwatch;
-    if (begin.primarySwatch != null && end.primarySwatch != null) {
-      primarySwatch = <int, Color>{};
-      for (int index in begin.primarySwatch.keys) {
-        if (!end.primarySwatch.containsKey(index))
-          continue;
-        primarySwatch[index] = Color.lerp(begin.primarySwatch[index], end.primarySwatch[index], t);
-      }
-    }
     return new ThemeData.raw(
       brightness: t < 0.5 ? begin.brightness : end.brightness,
-      primarySwatch: primarySwatch,
       primaryColor: Color.lerp(begin.primaryColor, end.primaryColor, t),
       primaryColorBrightness: t < 0.5 ? begin.primaryColorBrightness : end.primaryColorBrightness,
       canvasColor: Color.lerp(begin.canvasColor, end.canvasColor, t),
@@ -220,6 +224,9 @@
       splashColor: Color.lerp(begin.splashColor, end.splashColor, t),
       unselectedColor: Color.lerp(begin.unselectedColor, end.unselectedColor, t),
       disabledColor: Color.lerp(begin.disabledColor, end.disabledColor, t),
+      buttonColor: Color.lerp(begin.buttonColor, end.buttonColor, t),
+      selectionColor: Color.lerp(begin.selectionColor, end.selectionColor, t),
+      backgroundColor: Color.lerp(begin.backgroundColor, end.backgroundColor, t),
       accentColor: Color.lerp(begin.accentColor, end.accentColor, t),
       accentColorBrightness: t < 0.5 ? begin.accentColorBrightness : end.accentColorBrightness,
       indicatorColor: Color.lerp(begin.indicatorColor, end.indicatorColor, t),
@@ -237,7 +244,6 @@
       return false;
     ThemeData otherData = other;
     return (otherData.brightness == brightness) &&
-           (otherData.primarySwatch == primarySwatch) &&
            (otherData.primaryColor == primaryColor) &&
            (otherData.primaryColorBrightness == primaryColorBrightness) &&
            (otherData.canvasColor == canvasColor) &&
@@ -247,6 +253,9 @@
            (otherData.splashColor == splashColor) &&
            (otherData.unselectedColor == unselectedColor) &&
            (otherData.disabledColor == disabledColor) &&
+           (otherData.buttonColor == buttonColor) &&
+           (otherData.selectionColor == selectionColor) &&
+           (otherData.backgroundColor == backgroundColor) &&
            (otherData.accentColor == accentColor) &&
            (otherData.accentColorBrightness == accentColorBrightness) &&
            (otherData.indicatorColor == indicatorColor) &&
@@ -260,8 +269,6 @@
   int get hashCode {
     return hashValues(
       brightness,
-      hashList(primarySwatch.keys),
-      hashList(primarySwatch.values),
       primaryColor,
       primaryColorBrightness,
       canvasColor,
@@ -271,6 +278,9 @@
       splashColor,
       unselectedColor,
       disabledColor,
+      buttonColor,
+      selectionColor,
+      backgroundColor,
       accentColor,
       accentColorBrightness,
       hashValues( // Too many values.