Click here to Skip to main content
15,891,744 members
Articles / Programming Languages / Visual Basic

RSS Feed Aggregator and Blogging Smart Client

Rate me:
Please Sign up or sign in to vote.
4.91/5 (85 votes)
16 Aug 2005CPOL52 min read 1.1M   2.4K   397  
RSS Feed aggregator and blogging Smart Client which uses Enterprise Library, Updater Application Block, lots of XML hacks and desktop tricks. A comprehensive guide to real life hurdles of Smart Client development.
using System;
using System.IO;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Reflection;
namespace RSSBlogAPI
{
	using RSSCommon.Helper;
	/// <summary>
	/// Summary description for WebLogManager.
	/// </summary>
	public class WebLogManager : System.Windows.Forms.Form
	{
		#region Designer

		private TD.SandBar.ToolBar standardToolBar;
		private TD.SandBar.ButtonItem newWebLogButton;
		private TD.SandBar.ButtonItem deleteWebLogButton;
		private TD.SandBar.ButtonItem sendAllPostsButton;
		private System.Windows.Forms.Panel middlePanel;
		private System.Windows.Forms.Panel leftPanel;
		private System.Windows.Forms.Splitter splitter1;
		private System.Windows.Forms.Panel rightPanel;
		private TD.Eyefinder.NavigationBar webLogsNavigationBar;
		private TD.SandBar.ButtonItem closeWindow;
		private RSSBlogAPI.PostEditorControl postEditorControl;
		private TD.SandBar.ButtonItem buttonItem1;
		private System.Windows.Forms.Label noWebLogLabel;
		private TD.SandBar.ButtonItem buttonItem2;
		private TD.SandBar.ButtonItem buttonItem3;
		/// <summary>
		/// Required designer variable.
		/// </summary>
		private System.ComponentModel.Container components = null;

		public WebLogManager()
		{
			//
			// Required for Windows Form Designer support
			//
			InitializeComponent();

			//
			// TODO: Add any constructor code after InitializeComponent call
			//
		}

		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if(components != null)
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}

		#region Windows Form Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
			System.Resources.ResourceManager resources = new System.Resources.ResourceManager(typeof(WebLogManager));
			this.standardToolBar = new TD.SandBar.ToolBar();
			this.buttonItem3 = new TD.SandBar.ButtonItem();
			this.newWebLogButton = new TD.SandBar.ButtonItem();
			this.sendAllPostsButton = new TD.SandBar.ButtonItem();
			this.deleteWebLogButton = new TD.SandBar.ButtonItem();
			this.buttonItem1 = new TD.SandBar.ButtonItem();
			this.buttonItem2 = new TD.SandBar.ButtonItem();
			this.closeWindow = new TD.SandBar.ButtonItem();
			this.middlePanel = new System.Windows.Forms.Panel();
			this.rightPanel = new System.Windows.Forms.Panel();
			this.postEditorControl = new RSSBlogAPI.PostEditorControl();
			this.splitter1 = new System.Windows.Forms.Splitter();
			this.leftPanel = new System.Windows.Forms.Panel();
			this.noWebLogLabel = new System.Windows.Forms.Label();
			this.webLogsNavigationBar = new TD.Eyefinder.NavigationBar();
			this.middlePanel.SuspendLayout();
			this.rightPanel.SuspendLayout();
			this.leftPanel.SuspendLayout();
			this.SuspendLayout();
			// 
			// standardToolBar
			// 
			this.standardToolBar.Buttons.AddRange(new TD.SandBar.ToolbarItemBase[] {
																					   this.buttonItem3,
																					   this.newWebLogButton,
																					   this.sendAllPostsButton,
																					   this.deleteWebLogButton,
																					   this.buttonItem1,
																					   this.buttonItem2,
																					   this.closeWindow});
			this.standardToolBar.Guid = new System.Guid("b0513a55-c604-4c15-94aa-f731393f8496");
			this.standardToolBar.Location = new System.Drawing.Point(0, 0);
			this.standardToolBar.Name = "standardToolBar";
			this.standardToolBar.Size = new System.Drawing.Size(848, 26);
			this.standardToolBar.TabIndex = 5;
			this.standardToolBar.Text = "toolBar1";
			this.standardToolBar.ButtonClick += new TD.SandBar.ToolBar.ButtonClickEventHandler(this.standardToolBar_ButtonClick);
			// 
			// buttonItem3
			// 
			this.buttonItem3.Icon = ((System.Drawing.Icon)(resources.GetObject("buttonItem3.Icon")));
			this.buttonItem3.Tag = "$NewBlog";
			this.buttonItem3.Text = "New Post";
			// 
			// newWebLogButton
			// 
			this.newWebLogButton.Icon = ((System.Drawing.Icon)(resources.GetObject("newWebLogButton.Icon")));
			this.newWebLogButton.Tag = "$NewWebLog";
			this.newWebLogButton.Text = "New Web Log";
			// 
			// sendAllPostsButton
			// 
			this.sendAllPostsButton.Icon = ((System.Drawing.Icon)(resources.GetObject("sendAllPostsButton.Icon")));
			this.sendAllPostsButton.Tag = "$SendAll";
			this.sendAllPostsButton.Text = "Send All Now";
			// 
			// deleteWebLogButton
			// 
			this.deleteWebLogButton.Icon = ((System.Drawing.Icon)(resources.GetObject("deleteWebLogButton.Icon")));
			this.deleteWebLogButton.Tag = "$DeleteWebLog";
			this.deleteWebLogButton.Text = "Delete Web Log";
			// 
			// buttonItem1
			// 
			this.buttonItem1.Icon = ((System.Drawing.Icon)(resources.GetObject("buttonItem1.Icon")));
			this.buttonItem1.Tag = "$DeletePost";
			this.buttonItem1.Text = "Delete Post";
			// 
			// buttonItem2
			// 
			this.buttonItem2.Icon = ((System.Drawing.Icon)(resources.GetObject("buttonItem2.Icon")));
			this.buttonItem2.Tag = "$TestWebLog";
			this.buttonItem2.Text = "Test Setting";
			// 
			// closeWindow
			// 
			this.closeWindow.Icon = ((System.Drawing.Icon)(resources.GetObject("closeWindow.Icon")));
			this.closeWindow.Tag = "$Close";
			this.closeWindow.Text = "Close";
			// 
			// middlePanel
			// 
			this.middlePanel.Controls.Add(this.rightPanel);
			this.middlePanel.Controls.Add(this.splitter1);
			this.middlePanel.Controls.Add(this.leftPanel);
			this.middlePanel.Dock = System.Windows.Forms.DockStyle.Fill;
			this.middlePanel.Location = new System.Drawing.Point(0, 26);
			this.middlePanel.Name = "middlePanel";
			this.middlePanel.Size = new System.Drawing.Size(848, 484);
			this.middlePanel.TabIndex = 7;
			// 
			// rightPanel
			// 
			this.rightPanel.Controls.Add(this.postEditorControl);
			this.rightPanel.Dock = System.Windows.Forms.DockStyle.Fill;
			this.rightPanel.Location = new System.Drawing.Point(153, 0);
			this.rightPanel.Name = "rightPanel";
			this.rightPanel.Size = new System.Drawing.Size(695, 484);
			this.rightPanel.TabIndex = 2;
			// 
			// postEditorControl
			// 
			this.postEditorControl.CurrentPost = ((RSSBlogAPI.Post)(resources.GetObject("postEditorControl.CurrentPost")));
			this.postEditorControl.Dock = System.Windows.Forms.DockStyle.Fill;
			this.postEditorControl.Location = new System.Drawing.Point(0, 0);
			this.postEditorControl.Name = "postEditorControl";
			this.postEditorControl.Size = new System.Drawing.Size(695, 484);
			this.postEditorControl.TabIndex = 0;
			this.postEditorControl.OnSave += new System.EventHandler(this.postEditorControl_OnSave);
			// 
			// splitter1
			// 
			this.splitter1.Location = new System.Drawing.Point(150, 0);
			this.splitter1.Name = "splitter1";
			this.splitter1.Size = new System.Drawing.Size(3, 484);
			this.splitter1.TabIndex = 1;
			this.splitter1.TabStop = false;
			// 
			// leftPanel
			// 
			this.leftPanel.Controls.Add(this.noWebLogLabel);
			this.leftPanel.Controls.Add(this.webLogsNavigationBar);
			this.leftPanel.Dock = System.Windows.Forms.DockStyle.Left;
			this.leftPanel.Location = new System.Drawing.Point(0, 0);
			this.leftPanel.Name = "leftPanel";
			this.leftPanel.Size = new System.Drawing.Size(150, 484);
			this.leftPanel.TabIndex = 0;
			// 
			// noWebLogLabel
			// 
			this.noWebLogLabel.Location = new System.Drawing.Point(16, 16);
			this.noWebLogLabel.Name = "noWebLogLabel";
			this.noWebLogLabel.Size = new System.Drawing.Size(112, 72);
			this.noWebLogLabel.TabIndex = 1;
			this.noWebLogLabel.Text = "Click on \"New Web Log\" button to add a new web log account and get started";
			// 
			// webLogsNavigationBar
			// 
			this.webLogsNavigationBar.Dock = System.Windows.Forms.DockStyle.Fill;
			this.webLogsNavigationBar.HeaderFont = new System.Drawing.Font("Tahoma", 12F, System.Drawing.FontStyle.Bold);
			this.webLogsNavigationBar.Location = new System.Drawing.Point(0, 0);
			this.webLogsNavigationBar.Name = "webLogsNavigationBar";
			this.webLogsNavigationBar.PaneFont = new System.Drawing.Font("Tahoma", 8.25F, System.Drawing.FontStyle.Bold);
			this.webLogsNavigationBar.SelectedPane = null;
			this.webLogsNavigationBar.Size = new System.Drawing.Size(150, 484);
			this.webLogsNavigationBar.TabIndex = 0;
			this.webLogsNavigationBar.Text = "Web Logs";
			this.webLogsNavigationBar.SelectedPaneChanged += new System.EventHandler(this.webLogsNavigationBar_SelectedPaneChanged);
			// 
			// WebLogManager
			// 
			this.AutoScaleBaseSize = new System.Drawing.Size(5, 14);
			this.ClientSize = new System.Drawing.Size(848, 510);
			this.Controls.Add(this.middlePanel);
			this.Controls.Add(this.standardToolBar);
			this.Font = new System.Drawing.Font("Tahoma", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
			this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
			this.Name = "WebLogManager";
			this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
			this.Text = "Web Log Center";
			this.Closing += new System.ComponentModel.CancelEventHandler(this.WebLogManager_Closing);
			this.Load += new System.EventHandler(this.WebLogManager_Load);
			this.middlePanel.ResumeLayout(false);
			this.rightPanel.ResumeLayout(false);
			this.leftPanel.ResumeLayout(false);
			this.ResumeLayout(false);

		}
		#endregion

		private void WebLogManager_Load(object sender, System.EventArgs e)
		{
			this.LoadAllWeblogs();
		}

		#endregion

		#region MyCode

		#region Private Methods

		public event EventHandler SendFeeds;

		/// <summary>
		/// Load all weblogs, create the navigation panes for each weblog, populate them
		/// </summary>
		private void LoadAllWeblogs()
		{
			WebLogProvider.LoadWebLogs();

			// If tag is null, we skip all the events raised from this control
			this.webLogsNavigationBar.Tag = null;
			this.webLogsNavigationBar.Controls.Clear();			

			// Reverse the order of web logs so that the recent weblog is shown first in the 
			// navigation
			ArrayList blogs = (ArrayList)WebLogProvider.Instance.WebLogs.Clone();
			blogs.Reverse();

			// Add all weblogs as navigation pane 
			foreach( WebLog log in blogs )
			{
				// Create one navigation pane for each web log 
				WebLogNavigationBar bar = new WebLogNavigationBar(log);				
				bar.Text = log.Title;
				bar.SmallImage = Image.FromStream( RSSCommon.Helper.SerializationHelper.GetStream( "PublicQueue.ico" ) );
				
				// Host a web log viewer control inside the pane which 
				// shows details about the web log
				WebLogViewControl webLogView = new WebLogViewControl(log);
				webLogView.Name = bar.Name;
				webLogView.Dock = DockStyle.Fill;
				bar.Controls.Add( webLogView );

				// Subscribe to post selection event so that we can show post
				// details on the post editor whenever a post is selected
				webLogView.OnPostSelect += new EventHandler(webLogView_OnPostSelect);
				webLogView.OnPostDelete += new EventHandler(webLogView_OnPostDelete);

				// This sometimes fails
				try
				{
					this.webLogsNavigationBar.Controls.Add( bar );
				}
				catch( Exception x ) 
				{
					System.Diagnostics.Debug.WriteLine( x.ToString() );
				}
			}

			// Decide how many panes to show by default, don't show more than 3 at a time
			if( WebLogProvider.Instance.WebLogs.Count > 3 )
				this.webLogsNavigationBar.ShowPanes = 3;
			else
				this.webLogsNavigationBar.ShowPanes = WebLogProvider.Instance.WebLogs.Count;

			this.ShowCurrentWebLog();

			this.UpdateUIState();

			this.webLogsNavigationBar.Tag = true;
		}

		/// <summary>
		/// Invoke a public method of this class. It is used by the toolbar where
		/// each button contains a name of method to call on this class
		/// </summary>
		/// <param name="name"></param>
		private void InvokeMethod( string name )
		{
			if( null == name || 0 == name.Length ) return;

			// if self call, call the function on self
			if( name.StartsWith("$") )
			{
				MethodInfo method = this.GetType().GetMethod( name.TrimStart('$') );
				method.Invoke( this, null );
			}			
		}

		/// <summary>
		/// Save the current post in the current weblog's post queue
		/// </summary>
		private void SaveCurrentPost()
		{
			WebLogNavigationBar bar = this.webLogsNavigationBar.SelectedPane as WebLogNavigationBar;

			if( !this.postEditorControl.IsHandleCreated ) return;

			Post post = this.postEditorControl.CurrentPost;
			// If this is a new post, add the post in the collection
			if( null == post ) return;

			if( !bar.WebLog.Posts.Contains( post ) )
				bar.WebLog.EnqueuePost( post );

			bar.RefreshList( post );

			WebLogProvider.SaveWebLogs();

			if( post.IsSend )
				MessageBox.Show( this, "Message queued for sending on next synchronization", 
					"Send", MessageBoxButtons.OK, MessageBoxIcon.Information );
		}

		/// <summary>
		/// Load the current weblog posts in the list and preselect last unfinished post
		/// </summary>
		private void ShowCurrentWebLog()
		{
			WebLogNavigationBar bar = this.webLogsNavigationBar.SelectedPane as WebLogNavigationBar;
			if( null == bar ) return;

			WebLog log = bar.WebLog;

			// Find the last not sent post
			if( log.Posts.Count > 0 )
			{
				foreach( Post lastPost in log.Posts )
				{
					if( ( null != lastPost.ErrorInPost && lastPost.ErrorInPost.Length > 0 ) // error occured
						|| !lastPost.IsSent ) // Draft
					{
						this.EditPost( bar.WebLog, lastPost );
						bar.View.ReloadPosts(lastPost);

						return;
					}
				}
			}

			bar.View.ReloadPosts(null);
			// No post found so far to edit, show a new post
			this.NewPost();
		}

		/// <summary>
		/// Shwo the post in the post editor
		/// </summary>
		/// <param name="log"></param>
		/// <param name="post"></param>
		private void EditPost( WebLog log, Post post )
		{
			this.postEditorControl.SetWebLog( log );
			this.postEditorControl.CurrentPost = post;
		}

		/// <summary>
		/// Select the navigation bar which contains the specified weblog
		/// </summary>
		/// <param name="log"></param>
		private void SelectWebLog( WebLog log )
		{
			foreach( Control c in this.webLogsNavigationBar.Controls )
			{
				if( c is WebLogNavigationBar )
					c.Show();
			}
		}

		/// <summary>
		/// Update the toolbar button states and other UI element state according
		/// to current state of weblogs and posts.
		/// </summary>
		private void UpdateUIState()
		{
			if( WebLogProvider.Instance.WebLogs.Count > 0 )
				noWebLogLabel.Visible = false;

			if( null == webLogsNavigationBar.SelectedPane )
			{
				this.standardToolBar.Buttons[0].Enabled = false;
				this.standardToolBar.Buttons[2].Enabled = false;
				this.standardToolBar.Buttons[3].Enabled = false;
				this.standardToolBar.Buttons[4].Enabled = false;
				this.standardToolBar.Buttons[5].Enabled = false;
				this.postEditorControl.Enabled = false;
			}
			else
			{
				this.standardToolBar.Buttons[0].Enabled = true;
				this.standardToolBar.Buttons[2].Enabled = true;
				this.standardToolBar.Buttons[3].Enabled = true;
				this.standardToolBar.Buttons[4].Enabled = true;
				this.standardToolBar.Buttons[5].Enabled = true;
				this.postEditorControl.Enabled = true;
			}
		}
		#endregion

		#region Public Methods

		/// <summary>
		/// Start a new post in the current weblog
		/// </summary>
		public void NewBlog()
		{
			this.NewPost();
		}

		/// <summary>
		/// Test whether current settings on the weblog is correct
		/// </summary>
		public void TestWebLog()
		{
			WebLogNavigationBar bar = this.webLogsNavigationBar.SelectedPane as WebLogNavigationBar;
			if( null == bar ) 
			{
				return;
			}
			else
			{
				try
				{
					// Perform a test
					WebLogProvider.Instance.Test( bar.WebLog );

					// If no exception, then all ok
					MessageBox.Show( this, "Weblog settings are OK.", "Weblog Test",
						MessageBoxButtons.OK, MessageBoxIcon.Information );
				}
				catch( Exception x )
				{
					// weblog setting is not accurate
					if( DialogResult.Yes == MessageBox.Show( this, x.Message 
						+ Environment.NewLine 
						+ "Do you need some suggestions?", "Weblog Test", 
						MessageBoxButtons.YesNo, MessageBoxIcon.Error )	)
					{
						string path = Path.Combine( AppDomain.CurrentDomain.BaseDirectory, "docs\\WebLogInstruction.html" );
						RSSCommon.Helper.BrowserHelper.BrowseURL( path );
					}
				}
			}
		}

		/// <summary>
		/// Add a new weblog account
		/// </summary>
		public void NewWebLog()
		{
			using( WebLogEditor editor = new WebLogEditor() )
			{
				if( DialogResult.OK == editor.ShowDialog( this ) )
				{
					WebLogProvider.Instance.WebLogs.Add( editor.NewWebLog );
					
					WebLogProvider.SaveWebLogs();

					this.LoadAllWeblogs();

					this.SelectWebLog( editor.NewWebLog );
				}
			}
		}

		/// <summary>
		/// Create a new post in the current weblog. However, the post is not added to weblog's
		/// post queue
		/// </summary>
		private void NewPost()
		{
			this.SaveCurrentPost();

			WebLogNavigationBar bar = this.webLogsNavigationBar.SelectedPane as WebLogNavigationBar;
			if( null == bar ) 
			{
				this.postEditorControl.Enabled = false;
				return;
			}
			else
			{
				this.postEditorControl.Enabled = true;

				this.postEditorControl.SetWebLog( bar.WebLog );

				Post newPost = new Post();
				newPost.Title = "New Post";
				this.postEditorControl.CurrentPost = newPost;

				//bar.WebLog.Posts.Add( newPost );
			}
		}

		/// <summary>
		/// Start synchronizer to post all the queued posts
		/// </summary>
		public void SendAll()
		{
			if( null != SendFeeds )
				SendFeeds( this, EventArgs.Empty );
		}

		/// <summary>
		/// Delete current weblog account and all of its posts
		/// </summary>
		public void DeleteWebLog()
		{
			WebLogNavigationBar bar = this.webLogsNavigationBar.SelectedPane as WebLogNavigationBar;
			if( null == bar ) return;
			
			WebLog log = bar.WebLog;
			
			if( DialogResult.Yes == MessageBox.Show( this, "Are you sure you want to delete this Web Log with all the posts?", 
				"Delete Weblog", MessageBoxButtons.YesNo, MessageBoxIcon.Question ) )
			{
				WebLogProvider.Instance.WebLogs.Remove( log );

				WebLogProvider.SaveWebLogs();

				this.LoadAllWeblogs();
			}
		}

		/// <summary>
		/// Delete the current post
		/// </summary>
		public void DeletePost()
		{
			WebLogNavigationBar bar = this.webLogsNavigationBar.SelectedPane as WebLogNavigationBar;
			if( null == bar ) return;
			
			if( DialogResult.Yes == MessageBox.Show( this, 
				"Deleting the current post, are you sure?", 
				"Delete Post", MessageBoxButtons.YesNo, MessageBoxIcon.Question ) )
			{
				bar.View.DeleteSelectedPost();
			}
		}

		#endregion

		#region Events
		
		private void webLogView_OnPostDelete(object sender, EventArgs e)
		{
			this.ShowCurrentWebLog();
		}

		private void WebLogManager_Closing(object sender, System.ComponentModel.CancelEventArgs e)
		{
			this.SaveCurrentPost();
			WebLogProvider.SaveWebLogs();
		}

		public void DownloadCompleteEventHandler( object sender, EventArgs e )
		{
			this.LoadAllWeblogs();
		}

		private void webLogView_OnPostSelect(object sender, EventArgs e)
		{
			WebLogNavigationBar bar = this.webLogsNavigationBar.SelectedPane as WebLogNavigationBar;
			if( null == bar ) return;
			
			WebLogViewControl view = sender as WebLogViewControl;
			Post post = view.SelectedPost;
			this.EditPost( bar.WebLog, post );
		}

		private void standardToolBar_ButtonClick(object sender, TD.SandBar.ToolBarItemEventArgs e)
		{
			this.InvokeMethod(e.Item.Tag as string);
		}


		private void webLogsNavigationBar_SelectedPaneChanged(object sender, System.EventArgs e)
		{
			if( null == this.webLogsNavigationBar.Tag ) return;
			this.ShowCurrentWebLog();			
		}

		private void postEditorControl_OnSave(object sender, System.EventArgs e)
		{
			this.SaveCurrentPost();
		}

		

		#endregion

		#region Inner Class

		/// <summary>
		/// Extends the NavigationPane and makes the navigation pane attached to 
		/// a weblog
		/// </summary>
		private class WebLogNavigationBar : TD.Eyefinder.NavigationPane
		{
			public WebLog WebLog;
			public WebLogNavigationBar( WebLog log )
			{
				this.WebLog = log;

				this.WebLog.PropertyChanged += new PropertyChangedEventHandler(WebLog_PropertyChanged);
			}

			public WebLogViewControl View
			{
				get
				{
					foreach( Control c in this.Controls )
					{
						if( c is WebLogViewControl )
						{
							return (c as WebLogViewControl);
						}
					}
					return null;
				}
			}
			public void RefreshList( Post selectedPost )
			{
				this.View.ReloadPosts( selectedPost );	
			}
			public void DeleteSelectedPost()
			{
				this.View.DeleteSelectedPost();
			}

			private void WebLog_PropertyChanged(object sender, PropertyChangedEventArgs e)
			{
				base.Text = this.WebLog.Title;
			}
		}

		#endregion

		#endregion
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect BT, UK (ex British Telecom)
United Kingdom United Kingdom

Comments and Discussions