Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 323 lines (272 sloc) 10.41 kB
2ba11af Initial import
Miguel de Icaza authored
1 //
2 // TweetCell.cs:
3 //
4 // This shows both how to implement a custom UITableViewCell and
5 // how to implement a custom MonoTouch.Dialog.Element.
6 //
22288da Add licenses
Miguel de Icaza authored
7 // Copyright 2010 Miguel de Icaza
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining a copy
10 // of this software and associated documentation files (the "Software"), to deal
11 // in the Software without restriction, including without limitation the rights
12 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 // copies of the Software, and to permit persons to whom the Software is
14 // furnished to do so, subject to the following conditions:
15 //
16 // The above copyright notice and this permission notice shall be included in
17 // all copies or substantial portions of the Software.
18 //
19 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 // THE SOFTWARE.
2ba11af Initial import
Miguel de Icaza authored
26 //
27 using System;
28 using System.Drawing;
8714c96 Fix the build
Geoff Norton authored
29 using System.Collections;
2ba11af Initial import
Miguel de Icaza authored
30 using MonoTouch.UIKit;
31 using MonoTouch.Foundation;
c964891 Render cells manually, instead of using controls, this:
Miguel de Icaza authored
32 using MonoTouch.CoreGraphics;
2ba11af Initial import
Miguel de Icaza authored
33 using MonoTouch.Dialog;
34
35 namespace TweetStation
36 {
37 //
38 // TweetCell used for the timelines. It is relatlively light, and
39 // does not do highlighting. This might work for the iPhone, but
40 // for the iPad we probably should just use TweetViews that do the
41 // highlighting of url-like things
42 //
911d64a Performance, tweetcells no longer use animations, they were killing s…
Miguel de Icaza authored
43 public class TweetCell : UITableViewCell {
2ba11af Initial import
Miguel de Icaza authored
44 const int userSize = 14;
45 const int textSize = 15;
c964891 Render cells manually, instead of using controls, this:
Miguel de Icaza authored
46 const int timeSize = 12;
2ba11af Initial import
Miguel de Icaza authored
47
48 const int PicSize = 48;
49 const int PicXPad = 10;
50 const int PicYPad = 5;
51
2827890 Add support for rendering our picture on the right
Miguel de Icaza authored
52 const int PicAreaWidth = 2 * PicXPad + PicSize;
2ba11af Initial import
Miguel de Icaza authored
53
54 const int TextHeightPadding = 4;
2827890 Add support for rendering our picture on the right
Miguel de Icaza authored
55 const int TextWidthPadding = 4;
2ba11af Initial import
Miguel de Icaza authored
56 const int TextYOffset = userSize + 4;
57 const int MinHeight = PicSize + 2 * PicYPad;
58 const int TimeWidth = 46;
59
60 static UIFont userFont = UIFont.BoldSystemFontOfSize (userSize);
61 static UIFont textFont = UIFont.SystemFontOfSize (textSize);
62 static UIFont timeFont = UIFont.SystemFontOfSize (timeSize);
c964891 Render cells manually, instead of using controls, this:
Miguel de Icaza authored
63 static UIColor timeColor = UIColor.FromRGB (147, 170, 204);
2ba11af Initial import
Miguel de Icaza authored
64
83fc884 Use a nested UIView to render the cell, as this ensures that the
Miguel de Icaza authored
65 TweetCellView tweetView;
2ba11af Initial import
Miguel de Icaza authored
66
c964891 Render cells manually, instead of using controls, this:
Miguel de Icaza authored
67 static CGGradient bottomGradient, topGradient;
91d18db Add shadows
Miguel de Icaza authored
68 static CGPath badgePath = Graphics.MakeRoundedPath (48);
69 static CGPath smallBadgePath = Graphics.MakeRoundedPath (23);
70
2827890 Add support for rendering our picture on the right
Miguel de Icaza authored
71 public static int CellStyle;
c964891 Render cells manually, instead of using controls, this:
Miguel de Icaza authored
72
73 static TweetCell ()
74 {
75 using (var rgb = CGColorSpace.CreateDeviceRGB()){
76 float [] colorsBottom = {
83fc884 Use a nested UIView to render the cell, as this ensures that the
Miguel de Icaza authored
77 1, 1, 1, .5f,
78 0.93f, 0.93f, 0.93f, .5f
c964891 Render cells manually, instead of using controls, this:
Miguel de Icaza authored
79 };
80 bottomGradient = new CGGradient (rgb, colorsBottom, null);
81 float [] colorsTop = {
83fc884 Use a nested UIView to render the cell, as this ensures that the
Miguel de Icaza authored
82 0.93f, 0.93f, 0.93f, .5f,
83 1, 1, 1, 0.5f
c964891 Render cells manually, instead of using controls, this:
Miguel de Icaza authored
84 };
85 topGradient = new CGGradient (rgb, colorsTop, null);
86 }
87 }
88
83fc884 Use a nested UIView to render the cell, as this ensures that the
Miguel de Icaza authored
89 // Should never happen
2ba11af Initial import
Miguel de Icaza authored
90 public TweetCell (IntPtr handle) : base (handle) {
91 Console.WriteLine (Environment.StackTrace);
92 }
93
911d64a Performance, tweetcells no longer use animations, they were killing s…
Miguel de Icaza authored
94 public class TweetCellView : UIView, IImageUpdated {
655afcc Make TweetStation Retina Display Ready:
Miguel de Icaza authored
95 static UIImage star = UIImage.FromBundle ("Images/mini-star-on.png");
83fc884 Use a nested UIView to render the cell, as this ensures that the
Miguel de Icaza authored
96 Tweet tweet;
97 string userText;
911d64a Performance, tweetcells no longer use animations, they were killing s…
Miguel de Icaza authored
98 UIImage tweetImage, retweetImage;
83fc884 Use a nested UIView to render the cell, as this ensures that the
Miguel de Icaza authored
99
100 public TweetCellView (Tweet tweet) : base ()
101 {
102 Update (tweet);
103 Opaque = true;
104 BackgroundColor = UIColor.White;
105 }
106
107 public void Update (Tweet tweet)
108 {
109 this.tweet = tweet;
110 userText = tweet.Retweeter == null ? tweet.Screename : tweet.Screename + "" + tweet.Retweeter;
77d7d99 A potential fix for a crash, not 100% sure, plus a touchup for the pi…
Miguel de Icaza authored
111
911d64a Performance, tweetcells no longer use animations, they were killing s…
Miguel de Icaza authored
112 //
113 // For fake UserIDs (returned by the search), we try looking up by screename now
114 //
115 var img = ImageStore.GetLocalProfilePicture (tweet.UserId);
116 if (img == null)
117 img = ImageStore.GetLocalProfilePicture (tweet.Screename);
118 if (img == null)
119 ImageStore.QueueRequestForPicture (tweet.UserId, tweet.PicUrl, this);
4e10b65 In search results display the tweet immediately, even if
Miguel de Icaza authored
120 else
911d64a Performance, tweetcells no longer use animations, they were killing s…
Miguel de Icaza authored
121 tweet.PicUrl = null;
122 tweetImage = img == null ? ImageStore.DefaultImage : img;
123
f656eb8 Some performance work (add begin/end transactions) which cuts
Miguel de Icaza authored
124 if (tweet.Retweeter == null)
125 retweetImage = null;
126 else {
911d64a Performance, tweetcells no longer use animations, they were killing s…
Miguel de Icaza authored
127 img = ImageStore.GetLocalProfilePicture (tweet.RetweeterId);
128 if (img == null)
129 ImageStore.QueueRequestForPicture (tweet.RetweeterId, tweet.RetweeterPicUrl, this);
130 else
131 tweet.RetweeterPicUrl = null;
132
133 retweetImage = img == null ? ImageStore.DefaultImage : img;
134 }
83fc884 Use a nested UIView to render the cell, as this ensures that the
Miguel de Icaza authored
135 SetNeedsDisplay ();
136 }
137
138 public override void Draw (RectangleF rect)
139 {
01702cd Use a stack for the imagestore instead of a queue
Miguel de Icaza authored
140 var context = UIGraphics.GetCurrentContext ();
83fc884 Use a nested UIView to render the cell, as this ensures that the
Miguel de Icaza authored
141
142 // Superview is the container, its superview the uitableviewcell
143 bool highlighted = (Superview.Superview as UITableViewCell).Highlighted;
144 UIColor textColor;
145
146 var bounds = Bounds;
147 var midx = bounds.Width/2;
148 if (highlighted){
149 textColor = UIColor.White;
150 } else {
151 UIColor.White.SetColor ();
152 context.FillRect (bounds);
153
154 context.DrawLinearGradient (bottomGradient, new PointF (midx, bounds.Height-17), new PointF (midx, bounds.Height), 0);
155 context.DrawLinearGradient (topGradient, new PointF (midx, 1), new PointF (midx, 3), 0);
156
157 textColor = UIColor.Black;
158 }
159
2827890 Add support for rendering our picture on the right
Miguel de Icaza authored
160 float xPic, xText;
161
91d18db Add shadows
Miguel de Icaza authored
162 if ((CellStyle & 1) == 0 && tweet.UserId == TwitterAccount.CurrentAccount.AccountId){
2827890 Add support for rendering our picture on the right
Miguel de Icaza authored
163 xText = TextWidthPadding;
164 xPic = bounds.Width-PicAreaWidth+PicXPad;
165 } else {
166 xText = PicAreaWidth;
167 xPic = PicXPad;
168 }
169
8f729ad More robust handling of search results, we now try to load the info b…
Miguel de Icaza authored
170 if (userText == null){
171 userText = "Unknown";
172 }
173
83fc884 Use a nested UIView to render the cell, as this ensures that the
Miguel de Icaza authored
174 textColor.SetColor ();
2827890 Add support for rendering our picture on the right
Miguel de Icaza authored
175 DrawString (userText, new RectangleF (xText, TextHeightPadding, bounds.Width-PicAreaWidth-TextWidthPadding-TimeWidth, userSize), userFont);
176 DrawString (tweet.Text, new RectangleF (xText, bounds.Y + TextYOffset, bounds.Width-PicAreaWidth-TextWidthPadding, bounds.Height-TextYOffset), textFont, UILineBreakMode.WordWrap);
83fc884 Use a nested UIView to render the cell, as this ensures that the
Miguel de Icaza authored
177
178 timeColor.SetColor ();
911d64a Performance, tweetcells no longer use animations, they were killing s…
Miguel de Icaza authored
179 string time = Util.FormatTime (new TimeSpan (DateTime.UtcNow.Ticks - tweet.CreatedAt));
180 if (tweet.Favorited){
181 using (var nss = new NSString (time)){
182 var size = nss.StringSize (timeFont);
183
046c753 Add icons
Miguel de Icaza authored
184 star.Draw (new RectangleF (bounds.Width-24-size.Width-(xPic == PicXPad ? 0 : PicAreaWidth), TextHeightPadding, size.Height, size.Height));
911d64a Performance, tweetcells no longer use animations, they were killing s…
Miguel de Icaza authored
185 }
186 }
2827890 Add support for rendering our picture on the right
Miguel de Icaza authored
187 DrawString (time, new RectangleF (xText, TextHeightPadding, bounds.Width-PicAreaWidth-TextWidthPadding, timeSize),
83fc884 Use a nested UIView to render the cell, as this ensures that the
Miguel de Icaza authored
188 timeFont, UILineBreakMode.Clip, UITextAlignment.Right);
911d64a Performance, tweetcells no longer use animations, they were killing s…
Miguel de Icaza authored
189
91d18db Add shadows
Miguel de Icaza authored
190 if ((CellStyle & 2) == 0){
191 // Cute touch
192 UIColor.Gray.SetColor ();
193 context.SaveState ();
194 context.TranslateCTM (xPic, PicYPad);
195 context.SetLineWidth (1);
d5ec3f3 Small fix
Miguel de Icaza authored
196
197 // On device, the shadow is painted in the opposite direction!
198 context.SetShadowWithColor (new SizeF (0, -1), 3, UIColor.DarkGray.CGColor);
91d18db Add shadows
Miguel de Icaza authored
199 context.AddPath (badgePath);
77d7d99 A potential fix for a crash, not 100% sure, plus a touchup for the pi…
Miguel de Icaza authored
200 context.FillPath ();
91d18db Add shadows
Miguel de Icaza authored
201
202 if (retweetImage != null){
203 context.TranslateCTM (30, 30);
204 context.AddPath (smallBadgePath);
6cf4c7b Added MartinBowling's support for viewing larger picture previews
Miguel de Icaza authored
205 context.StrokePath ();
91d18db Add shadows
Miguel de Icaza authored
206 }
207
208 context.RestoreState ();
209 }
210
2827890 Add support for rendering our picture on the right
Miguel de Icaza authored
211 tweetImage.Draw (new RectangleF (xPic, PicYPad, PicSize, PicSize));
911d64a Performance, tweetcells no longer use animations, they were killing s…
Miguel de Icaza authored
212
213 if (retweetImage != null)
2827890 Add support for rendering our picture on the right
Miguel de Icaza authored
214 retweetImage.Draw (new RectangleF (xPic+30, PicYPad+30, 23, 23));
911d64a Performance, tweetcells no longer use animations, they were killing s…
Miguel de Icaza authored
215 }
216
217 void IImageUpdated.UpdatedImage (long onId)
218 {
219 // Discard notifications that might have been queued for an old cell
220 if (tweet == null || (tweet.UserId != onId && tweet.RetweeterId != onId))
221 return;
222
223 // Discard the url string once the image is loaded, we wont be using it.
224 if (onId == tweet.UserId){
225 tweetImage = ImageStore.GetLocalProfilePicture (onId);
226 tweet.PicUrl = null;
227 } else {
228 retweetImage = ImageStore.GetLocalProfilePicture (onId);
229 tweet.RetweeterPicUrl = null;
230 }
231 SetNeedsDisplay ();
83fc884 Use a nested UIView to render the cell, as this ensures that the
Miguel de Icaza authored
232 }
233 }
234
2ba11af Initial import
Miguel de Icaza authored
235 // Create the UIViews that we will use here, layout happens in LayoutSubviews
236 public TweetCell (UITableViewCellStyle style, NSString ident, Tweet tweet) : base (style, ident)
237 {
f9a64c2 Fix searching
Miguel de Icaza authored
238 SelectionStyle = UITableViewCellSelectionStyle.Blue;
2ba11af Initial import
Miguel de Icaza authored
239
83fc884 Use a nested UIView to render the cell, as this ensures that the
Miguel de Icaza authored
240 tweetView = new TweetCellView (tweet);
2ba11af Initial import
Miguel de Icaza authored
241 UpdateCell (tweet);
83fc884 Use a nested UIView to render the cell, as this ensures that the
Miguel de Icaza authored
242 ContentView.Add (tweetView);
2ba11af Initial import
Miguel de Icaza authored
243 }
244
245 //
246 // This method is called when the cell is reused to reset
247 // all of the cell values
248 //
249 public void UpdateCell (Tweet tweet)
250 {
83fc884 Use a nested UIView to render the cell, as this ensures that the
Miguel de Icaza authored
251 tweetView.Update (tweet);
252 SetNeedsDisplay ();
2ba11af Initial import
Miguel de Icaza authored
253 }
254
255 public static float GetCellHeight (RectangleF bounds, Tweet tweet)
256 {
257 bounds.Height = 999;
258
259 // Keep the same as LayoutSubviews
2827890 Add support for rendering our picture on the right
Miguel de Icaza authored
260 bounds.X = 0;
261 bounds.Width -= PicAreaWidth+TextWidthPadding;
2ba11af Initial import
Miguel de Icaza authored
262
263 using (var nss = new NSString (tweet.Text)){
264 var dim = nss.StringSize (textFont, bounds.Size, UILineBreakMode.WordWrap);
2827890 Add support for rendering our picture on the right
Miguel de Icaza authored
265 return Math.Max (dim.Height + TextYOffset + 2*TextWidthPadding, MinHeight);
2ba11af Initial import
Miguel de Icaza authored
266 }
267 }
83fc884 Use a nested UIView to render the cell, as this ensures that the
Miguel de Icaza authored
268
269 public override void LayoutSubviews ()
2ba11af Initial import
Miguel de Icaza authored
270 {
83fc884 Use a nested UIView to render the cell, as this ensures that the
Miguel de Icaza authored
271 base.LayoutSubviews ();
2ba11af Initial import
Miguel de Icaza authored
272
83fc884 Use a nested UIView to render the cell, as this ensures that the
Miguel de Icaza authored
273 tweetView.Frame = ContentView.Bounds;
ecba61b Fix rotation
Miguel de Icaza authored
274 tweetView.SetNeedsDisplay ();
2ba11af Initial import
Miguel de Icaza authored
275 }
276 }
277
278 //
279 // A MonoTouch.Dialog.Element that renders a TweetCell
280 //
281 public class TweetElement : Element, IElementSizing {
282 static NSString key = new NSString ("tweetelement");
283 public Tweet Tweet;
4e10b65 In search results display the tweet immediately, even if
Miguel de Icaza authored
284
2ba11af Initial import
Miguel de Icaza authored
285 public TweetElement (Tweet tweet) : base (null)
286 {
287 Tweet = tweet;
288 }
289
290 // Gets a cell on demand, reusing cells
291 public override UITableViewCell GetCell (UITableView tv)
292 {
293 var cell = tv.DequeueReusableCell (key) as TweetCell;
294 if (cell == null)
295 cell = new TweetCell (UITableViewCellStyle.Default, key, Tweet);
296 else
297 cell.UpdateCell (Tweet);
298
299 return cell;
300 }
301
302 public override void Selected (DialogViewController dvc, UITableView tableView, NSIndexPath path)
303 {
4e10b65 In search results display the tweet immediately, even if
Miguel de Icaza authored
304 var profile = new DetailTweetViewController (Tweet);
2ba11af Initial import
Miguel de Icaza authored
305 dvc.ActivateController (profile);
306 }
307
308 public override bool Matches (string text)
309 {
f9a64c2 Fix searching
Miguel de Icaza authored
310 return (Tweet.Screename.IndexOf (text, StringComparison.CurrentCultureIgnoreCase) != -1) ||
311 (Tweet.Text.IndexOf (text, StringComparison.InvariantCultureIgnoreCase) != -1) ||
312 (Tweet.Retweeter != null ? Tweet.Retweeter.IndexOf (text, StringComparison.CurrentCultureIgnoreCase) != -1 : false);
2ba11af Initial import
Miguel de Icaza authored
313 }
314
315 #region IElementSizing implementation
316 public float GetHeight (UITableView tableView, NSIndexPath indexPath)
317 {
318 return TweetCell.GetCellHeight (tableView.Bounds, Tweet);
319 }
320 #endregion
321 }
322 }
Something went wrong with that request. Please try again.