PageRenderTime 22ms CodeModel.GetById 10ms app.highlight 9ms RepoModel.GetById 1ms app.codeStats 0ms

/BlogEngine/BlogEngine.NET/App_Code/Controls/TagCloud.cs

#
C# | 218 lines | 140 code | 34 blank | 44 comment | 15 complexity | a789b29cfee85c3e39f4510900b98f14 MD5 | raw file
  1// --------------------------------------------------------------------------------------------------------------------
  2// <summary>
  3//   The tag cloud.
  4// </summary>
  5// --------------------------------------------------------------------------------------------------------------------
  6
  7namespace App_Code.Controls
  8{
  9    using System;
 10    using System.Collections.Generic;
 11    using System.Linq;
 12    using System.Web;
 13    using System.Web.UI;
 14
 15    using BlogEngine.Core;
 16
 17    using Resources;
 18
 19    /// <summary>
 20    /// The tag cloud.
 21    /// </summary>
 22    public class TagCloud : Control
 23    {
 24        #region Constants and Fields
 25
 26        /// <summary>
 27        /// The link format.
 28        /// </summary>
 29        private const string Link = "<a href=\"{0}\" class=\"{1}\" title=\"{2}\">{3}</a> ";
 30
 31        /// <summary>
 32        ///     The sync root.
 33        /// </summary>
 34        private static readonly object SyncRoot = new object();
 35
 36        /// <summary>
 37        /// The weighted list.
 38        /// </summary>
 39        private static Dictionary<Guid, Dictionary<string, string>> weightedList = new Dictionary<Guid, Dictionary<string, string>>();
 40
 41        /// <summary>
 42        /// The minimum posts.
 43        /// </summary>
 44        private int minimumPosts = 1;
 45
 46        /// <summary>
 47        /// The tag cloud size.
 48        /// </summary>
 49        private int tagCloudSize = -1;
 50
 51        #endregion
 52
 53        #region Properties
 54
 55        /// <summary>
 56        /// Gets or sets MinimumPosts.
 57        /// </summary>
 58        public int MinimumPosts
 59        {
 60            get
 61            {
 62                return this.minimumPosts;
 63            }
 64
 65            set
 66            {
 67                this.minimumPosts = value;
 68            }
 69        }
 70
 71        /// <summary>
 72        /// Gets or sets TagCloudSize.
 73        /// </summary>
 74        public int TagCloudSize
 75        {
 76            get
 77            {
 78                return this.tagCloudSize;
 79            }
 80
 81            set
 82            {
 83                this.tagCloudSize = value;
 84            }
 85        }
 86
 87        /// <summary>
 88        ///     Gets WeightedList.
 89        /// </summary>
 90        private Dictionary<string, string> WeightedList
 91        {
 92            get
 93            {
 94                Dictionary<string, string> list = null;
 95                Guid blogId = Blog.CurrentInstance.Id;
 96
 97                if (!weightedList.TryGetValue(blogId, out list))
 98                {
 99                    lock (SyncRoot)
100                    {
101                        if (!weightedList.TryGetValue(blogId, out list))
102                        {
103                            list = new Dictionary<string, string>();
104                            weightedList.Add(blogId, list);
105
106                            this.SortList();
107                        }
108                    }
109                }
110
111                return list;
112            }
113        }
114
115        #endregion
116
117        #region Public Methods
118
119        /// <summary>
120        /// Outputs server control content to a provided <see cref="T:System.Web.UI.HtmlTextWriter"/> object and stores tracing information about the control if tracing is enabled.
121        /// </summary>
122        /// <param name="writer">The <see cref="T:System.Web.UI.HtmlTextWriter"/> object that receives the control content.</param>
123        public override void RenderControl(HtmlTextWriter writer)
124        {
125            if (this.WeightedList.Keys.Count == 0)
126            {
127                writer.Write("<p>{0}</p>", labels.none);
128            }
129
130            writer.Write("<ul id=\"tagcloud\" class=\"tagcloud\">");
131
132            foreach (var key in this.WeightedList.Keys)
133            {
134                writer.Write("<li>");
135                writer.Write(
136                    string.Format(
137                        Link, 
138                        string.Format("{0}?tag=/{1}", Utils.RelativeWebRoot, HttpUtility.UrlEncode(key)), 
139                        this.WeightedList[key], 
140                        string.Format("Tag: {0}", key), 
141                        key));
142                writer.Write("</li>");
143            }
144
145            writer.Write("</ul>");
146            writer.Write(Environment.NewLine);
147        }
148
149        #endregion
150
151        #region Methods
152
153        /// <summary>
154        /// Builds a raw list of all tags and the number of times
155        /// they have been added to a post.
156        /// </summary>
157        /// <returns>A sorted dictionary of int with string keys.</returns>
158        private static SortedDictionary<string, int> CreateRawList()
159        {
160            var dic = new SortedDictionary<string, int>();
161            foreach (var tag in Post.Posts.Where(post => post.IsVisibleToPublic).SelectMany(post => post.Tags))
162            {
163                if (dic.ContainsKey(tag))
164                {
165                    dic[tag]++;
166                }
167                else
168                {
169                    dic[tag] = 1;
170                }
171            }
172
173            return dic;
174        }
175
176        /// <summary>
177        /// Sorts the list of tags based on how much they are used.
178        /// </summary>
179        private void SortList()
180        {
181            var dic = CreateRawList();
182            var max = dic.Values.Max();
183
184            var currentTagCount = 0;
185
186            int count = currentTagCount;
187            foreach (var key in
188                dic.Keys.Where(key => dic[key] >= this.MinimumPosts).Where(key => this.TagCloudSize <= 0 || count <= this.TagCloudSize))
189            {
190                currentTagCount++;
191
192                var weight = ((double)dic[key] / max) * 100;
193                if (weight >= 99)
194                {
195                    WeightedList.Add(key, "biggest");
196                }
197                else if (weight >= 70)
198                {
199                    WeightedList.Add(key, "big");
200                }
201                else if (weight >= 40)
202                {
203                    WeightedList.Add(key, "medium");
204                }
205                else if (weight >= 20)
206                {
207                    WeightedList.Add(key, "small");
208                }
209                else if (weight >= 3)
210                {
211                    WeightedList.Add(key, "smallest");
212                }
213            }
214        }
215
216        #endregion
217    }
218}