#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(); } } } }