#region Disclaimer / License
// Copyright (C) 2009, Kenneth Skovhede
// http://www.hexad.dk, opensource@hexad.dk
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//
#endregion
using System;
using System.Collections.Generic;
using System.Text;
namespace OSGeo.MapGuide.Maestro.ResourceEditors
{
///
/// Represents a ColorBrewer color set
///
public class ColorBrewer
{
private string m_name;
private string m_type;
private List m_colors;
///
/// Gets the name of the ColorBrewer set
///
public string Name { get { return m_name; } }
///
/// Gets the assigned type for the ColorBrewer set
///
public string Type { get { return m_type; } }
///
/// Gets the ordered list of colors to use
///
public List Colors { get { return m_colors; } }
///
/// Constructs a new ColorBrewer instance
///
/// The name of the set
/// The set type
/// The colors in the set
public ColorBrewer(string name, string type, List colors)
{
m_name = name;
m_type = type;
m_colors = colors;
}
///
/// Parses a CSV file for ColorBrewer setup, uses double quotes for text delimiter, and comma for record delimiter
///
/// The name of the file to parse
/// A list of parsed ColorBrewer sets
public static List ParseCSV(string filename)
{
return ParseCSV(filename, '"', ',');
}
///
/// Parses a CSV file for ColorBrewer setup
///
/// The name of the file to parse
/// The character used to delimit the records
/// The character used to enclose strings
/// A list of parsed ColorBrewer sets
public static List ParseCSV(string filename, char textDelimiter, char recordDelimiter)
{
using (System.IO.StreamReader sr = new System.IO.StreamReader(filename, System.Text.Encoding.UTF8, true))
{
List result = new List();
Dictionary columns = new Dictionary();
List colnames = TokenizeLine(sr.ReadLine(), recordDelimiter, textDelimiter);
for (int i = 0; i < colnames.Count; i++)
colnames[i] = colnames[i].ToLower();
columns.Add("ColorName", colnames.IndexOf("colorname"));
columns.Add("NumOfColors", colnames.IndexOf("numofcolors"));
columns.Add("Type", colnames.IndexOf("type"));
columns.Add("CritVal", colnames.IndexOf("critval"));
columns.Add("ColorNum", colnames.IndexOf("colornum"));
columns.Add("ColorLetter", colnames.IndexOf("colorletter"));
columns.Add("R", colnames.IndexOf("r"));
columns.Add("G", colnames.IndexOf("g"));
columns.Add("B", colnames.IndexOf("b"));
columns.Add("SchemeType", colnames.IndexOf("schemetype"));
if (columns["ColorName"] < 0)
throw new Exception(string.Format(Strings.ColorBrewer.MissingColumnError, "ColorName"));
if (columns["Type"] < 0)
throw new Exception(string.Format(Strings.ColorBrewer.MissingColumnError, "Type"));
if (columns["NumOfColors"] < 0)
throw new Exception(string.Format(Strings.ColorBrewer.MissingColumnError, "NumOfColors"));
if (columns["R"] < 0)
throw new Exception(string.Format(Strings.ColorBrewer.MissingColumnError, "R"));
if (columns["G"] < 0)
throw new Exception(string.Format(Strings.ColorBrewer.MissingColumnError, "G"));
if (columns["B"] < 0)
throw new Exception(string.Format(Strings.ColorBrewer.MissingColumnError, "B"));
while (!sr.EndOfStream)
{
string line = sr.ReadLine();
List values = TokenizeLine(line, recordDelimiter, textDelimiter);
if (values.Count != columns.Count)
throw new Exception(string.Format(Strings.ColorBrewer.InvalidFieldCountError, line));
string colorName = values[columns["ColorName"]];
string type = values[columns["Type"]];
if (string.IsNullOrEmpty(colorName) || string.IsNullOrEmpty(type))
continue; //Assume comment
int colorCount;
if (!int.TryParse(values[columns["NumOfColors"]], out colorCount))
continue; //Assume comment
List colors = new List();
while (!sr.EndOfStream && colorCount > 0)
{
if (!string.IsNullOrEmpty(line))
{
values = TokenizeLine(line, recordDelimiter, textDelimiter);
if (values.Count != colnames.Count)
throw new Exception(string.Format(Strings.ColorBrewer.InvalidRecordCountError, line));
byte r, g, b;
if (!byte.TryParse(values[columns["R"]], out r))
throw new Exception(string.Format(Strings.ColorBrewer.InvalidColorComponent, "R", values[columns["R"]], line));
if (!byte.TryParse(values[columns["G"]], out g))
throw new Exception(string.Format(Strings.ColorBrewer.InvalidColorComponent, "G", values[columns["G"]], line));
if (!byte.TryParse(values[columns["B"]], out b))
throw new Exception(string.Format(Strings.ColorBrewer.InvalidColorComponent, "B", values[columns["B"]], line));
colors.Add(System.Drawing.Color.FromArgb(r, g, b));
colorCount--;
}
if (colorCount > 0)
line = sr.ReadLine();
}
if (colorCount != 0)
throw new Exception(string.Format(Strings.ColorBrewer.ColorCountError, colorCount, line));
result.Add(new ColorBrewer(colorName, type, colors));
}
return result;
}
}
///
/// Splits a line into record fields, and removes text delimiters
///
/// The line to tokenize
/// The character used to delimit the records
/// The character used to enclose strings
/// A list of records
private static List TokenizeLine(string line, char recordDelimiter, char textDelimiter)
{
if (string.IsNullOrEmpty(line))
return new List();
bool inQuotes = false;
int startIndex = 0;
List records = new List();
for (int i = 0; i < line.Length; i++)
if (line[i] == textDelimiter)
inQuotes = !inQuotes;
else if (!inQuotes && line[i] == recordDelimiter)
{
string rec = line.Substring(startIndex, i - startIndex);
if (rec.StartsWith(textDelimiter.ToString()) && rec.EndsWith(textDelimiter.ToString()))
rec = rec.Substring(1, rec.Length - 2);
records.Add(rec);
startIndex = i+1;
}
if (startIndex <= line.Length)
{
string rec = line.Substring(startIndex);
if (rec.StartsWith(textDelimiter.ToString()) && rec.EndsWith(textDelimiter.ToString()))
rec = rec.Substring(1, rec.Length - 2);
records.Add(rec);
}
return records;
}
///
/// Returns the objects string representation
///
/// The string the represents the object
public override string ToString()
{
return m_name + " - " + DisplayType;
}
///
/// Gets a display friendly version of the display type
///
public string DisplayType
{
get
{
switch (m_type)
{
case "qual":
return Strings.ColorBrewer.QualitativeName;
case "seq":
return Strings.ColorBrewer.SequentialName;
case "div":
return Strings.ColorBrewer.DivergingName;
default:
return m_type;
}
}
}
///
/// Helper class to display ColorBrewer items in a list or combobox
///
public class ColorBrewerListItem
{
///
/// Indicates what type of string to use
///
public enum DisplayMode
{
///
/// Displays "Group - Name"
///
Full,
///
/// Just display the group
///
Type,
///
/// Just display the set name
///
Set
}
///
/// A reference to the set
///
private ColorBrewer m_set;
///
/// The current display mode
///
private DisplayMode m_mode;
///
/// Gets the ColorBrewer set
///
public ColorBrewer Set { get { return m_set; } }
public ColorBrewerListItem(ColorBrewer set, DisplayMode mode)
{
m_set = set;
m_mode = mode;
}
///
/// Returns a display version of the item
///
///
public override string ToString()
{
if (m_mode == DisplayMode.Type)
return m_set.DisplayType;
else if (m_mode == DisplayMode.Set)
return m_set.Name;
else
return m_set.ToString();
}
}
}
}