///
/// Copyright © 2003-2008 JetBrains s.r.o.
/// You may distribute under the terms of the GNU General Public License, as published by the Free Software Foundation, version 2 (see License.txt in the repository root folder).
///
using System;
using System.Collections;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Reflection;
using System.Resources;
using System.Text;
using System.Web;
using System.Windows.Forms;
using GUIControls.Controls;
using JetBrains.DataStructures;
using JetBrains.Omea.Base;
using JetBrains.Omea.Charsets;
using JetBrains.Omea.GUIControls;
using JetBrains.Omea.MIME;
using JetBrains.Omea.Net;
using JetBrains.Omea.OpenAPI;
using JetBrains.UI.Components.Separator;
namespace JetBrains.Omea.Nntp
{
public class EditMessageForm: DialogBase, IContextProvider, ICommandProcessor
{
private const string _DefaultCharset = "utf-8";
private const string _CommonMessage = "This message cannot be encoded with the charset you have selected, “{0}”. Some of the characters will be lost.\n";
private JetTextBox _subjectBox;
private IContainer components;
private Label _subjectLabel;
private StatusBar _statusBar;
private OpenFileDialog _openAttachDialog;
private ToolTip _fullNameToolTip;
private Panel _headerPanel;
private Label _fromlabel;
private Splitter _bodyListSplitter;
private Panel _bodyPanel;
private ContextMenu _attachListMenu;
private MenuItem _removeAttachMenuItem;
private ToolStrip _toolbar;
private ResourceListLinkLabel _groupsLabel;
private JetTextBox _fromTextLabel;
private ComboBox _fromComboBox;
private Label _serverLabel;
private ResourceComboBox _serverComboBox;
private ResourceListView2 _attachList;
private ResourceListView2Column nameCol, sizeCol;
private static IResourceList _attaches = Core.ResourceStore.EmptyResourceList;
private AbstractWebBrowser _browser;
#region Menu
private MenuStrip mainMenu1;
private ToolStripMenuItem _fileMenuItem;
private ToolStripMenuItem _newMenuItem;
private ToolStripSeparator _menuSeparator1;
private ToolStripMenuItem _closeMenuItem;
private ToolStripMenuItem _formatMenuItem;
private ToolStripMenuItem _saveMenuItem;
private ToolStripSeparator _menuSeparator4;
private ToolStripMenuItem _encodingMenuItem;
private ToolStripMenuItem _postMenuItem;
private ToolStripMenuItem _undoMenuItem;
private ToolStripMenuItem _redoMenuItem;
private ToolStripSeparator _menuSeparator5;
private ToolStripMenuItem _cutMenuItem;
private ToolStripMenuItem _copyMenuItem;
private ToolStripMenuItem _pasteMenuItem;
private ToolStripMenuItem _editMenuItem;
private ToolStripMenuItem _saveAndCloseMenuItem;
private ToolStripMenuItem _menuitemReply2Sender;
private ToolStripMenuItem _menuitemReply2Herd;
private ToolStripMenuItem _menuitemForward;
private ToolStripMenuItem _menuitemDeleteArticle;
private ToolStripMenuItem _menuitemNewsgroups;
private ToolStripMenuItem _menuitemAttachFile;
private ToolStripMenuItem _menuitemNext;
private ToolStripMenuItem _menuitemPrevious;
private ToolStripMenuItem _menuActions;
#endregion Menu
private JetLinkLabel _newsgroupsLabel;
private IResourceList _groups;
private string _references;
private bool _articleChanged;
private Separator _toolbarSeparator;
private IResource _draftArticle;
private IResourceList _liveArticle;
private readonly MethodInvoker _saveArticleDelegate;
private static readonly IntHashTable _openArticles = new IntHashTable();
///
/// True while the form is busy (eg sending the article) and cannot execute most of the actions.
///
protected bool _isBusy = false;
///
/// Binds toolbar controls to particular actions; also populates toolbar with buttons.
///
protected ToolbarActionManager _toolbarActionManager;
///
/// Security Context in which the HTML bodies are displayed, derived from the , forces links to be opened in a new window.
///
protected WebSecurityContext _browserContext;
///
/// A map of keyboard shortcuts to the corresponding actions.
///
protected IntHashTable _hashKeyboardActions;
///
/// Identifier of the HTML TEXTAREA that servers as a text editor control.
///
protected readonly static string _sPlainTextEditorId = "PlainTextEditor";
///
/// Identifies the role in which the current EditMessageForm performs.
///
private enum FormStateVerb
{
///
/// The form is editing a news article.
///
Edit,
///
/// The form is viewing a news article in read-only mode.
///
View
}
private FormStateVerb _whatWeAreDoing;
///
/// Actions manager for the menu items.
///
protected MenuActionsManager _menuactionsmanager;
///
/// The charset that is currently selected for the article.
/// Initialized by the default charset of the news server, or Omea's default charset if not overridden.
///
protected CharsetsEnum.Charset _charset = CharsetsEnum.GetDefaultBodyCharset();
///
/// If True, warnings are not displayed in case the selected charset cannot handle all the characters in the message correctly.
/// Used to suppress repetitive messages for the same article on every save, if the user choses to ignore the problem.
///
protected bool _bSuppressUnfitEncodingWarning = false;
private EditMessageForm()
{
InitializeComponent();
Icon = Core.UIManager.ApplicationIcon;
_attaches = Core.ResourceStore.EmptyResourceList;
_fromTextLabel.Width = _fromComboBox.Width - SystemInformation.VerticalScrollBarWidth - 1;
_newsgroupsLabel.Text = "Newsgroups:";
_saveArticleDelegate = SaveArticle;
Core.UIManager.MainWindowClosing += EditMessageForm_Closing;
IResourceList servers = Core.ResourceStore.GetAllResources( NntpPlugin._newsServer );
FillFromCombo( servers );
FillServersCombo( servers );
FillEncodingMenu();
_attachList.ShowContextMenu = false;
// Create and initialize the browser object
_bodyPanel.Controls.Remove( _bodyListSplitter );
_bodyPanel.Controls.Remove( _attachList );
InitializeBrowserControl();
_bodyPanel.Controls.Add( _browser );
_bodyPanel.Controls.Add( _bodyListSplitter );
_bodyPanel.Controls.Add( _attachList );
InitializeColumns();
InitializeMenuToolBarManagers();
InitializeFormSize();
}
private void FillFromCombo( IResourceList servers )
{
_fromComboBox.BeginUpdate();
try
{
foreach( IResource server in servers.ValidResources )
{
string displayName = server.GetPropText( NntpPlugin._propUserDisplayName );
string email = server.GetPropText( NntpPlugin._propEmailAddress );
if( email.Length > 0 )
{
if( displayName.Length > 0 )
{
email = displayName + " <" + email + '>';
}
if( _fromComboBox.Items.IndexOf( email ) < 0 )
{
_fromComboBox.Items.Add( email );
}
}
}
}
finally
{
_fromComboBox.EndUpdate();
}
}
private void FillServersCombo( IResourceList servers )
{
_serverComboBox.BeginUpdate();
try
{
ComboBox.ObjectCollection items = _serverComboBox.Items;
items.Clear();
foreach( IResource server in servers.ValidResources )
{
items.Add( server );
}
if( items.Count > 0 )
{
_serverComboBox.SelectedItem = servers[ 0 ];
}
}
finally
{
_serverComboBox.EndUpdate();
}
}
private void InitializeBrowserControl()
{
_browser = Core.WebBrowser.NewInstance();
_browser.Dock = DockStyle.Fill;
_browser.Name = "_browser";
_browser.TabIndex = 1;
_browser.Visible = true;
_browser.KeyDown += _browser_KeyDown;
_browser.AllowDrop = false;
_browser.DragOver += EditMessageForm_DragOver;
_browser.DragDrop += EditMessageForm_DragDrop;
_browser.ContextProvider = this; // Selected resource information and so on
_browser.BeforeNavigate += OnBeforeBrowserNavigate;
_browserContext = WebSecurityContext.Restricted;
_browserContext.AllowInPlaceNavigation = false;
}
private void FillEncodingMenu()
{
//////////////////
// Encoding Menu
// Get the list of available charsets
ArrayList charsets = new ArrayList();
foreach( CharsetsEnum.Charset charset in new CharsetsEnum( CharsetFlags.NntpCharset ) )
charsets.Add( charset );
// Sort by family, then by description
charsets.Sort();
// Find out where to put the separators
// (between two families, at least one of whom has more than one member)
int nFamilyStart = 0;
int nCurrentFamily = -1;
IntHashSet hashSeparators = new IntHashSet(); // Indexes of charsets in the array BEFORE which separators should be inserted
for( int a = 0; a < charsets.Count; a++ )
{
CharsetsEnum.Charset charset = (CharsetsEnum.Charset)charsets[ a ];
// Family ends here?
if( charset.FamilyCodepage != nCurrentFamily )
{
// If it was a large enough family, surround it with separators
if( a - nFamilyStart > 1 ) // Number of charsets in the family
{
if( nFamilyStart > 0 )
hashSeparators.Add( nFamilyStart );
hashSeparators.Add( a );
}
// Seed the new family
nCurrentFamily = charset.FamilyCodepage;
nFamilyStart = a;
}
}
// Add to the menu
for( int a = 0; a < charsets.Count; a++ )
{
// Add an optional separator
if( hashSeparators.Contains( a ) )
_encodingMenuItem.DropDownItems.Add( new ToolStripSeparator() );
// Add the charset menu item
CharsetsEnum.Charset charset = (CharsetsEnum.Charset)charsets[ a ];
ToolStripMenuItem mi = new EncodingMenuItem( charset );
mi.Click += OnEncodingMenuItemClicked;
_encodingMenuItem.DropDownItems.Add( mi );
}
}
private void InitializeMenuToolBarManagers()
{
/////////////////////////////////////////
// Create some actions for later use
IAction actionSave = new MethodInvokerAction( OnSaveArticle, OnUpdateSaveArticle );
IAction actionSaveAndClose = new MethodInvokerAction( OnSaveAndClose, OnUpdateSaveArticle );
IAction actionSend = new MethodInvokerAction( DoPost, OnUpdateDoPost );
IAction actionClose = new MethodInvokerAction( AsyncClose, null );
IAction actionNewsgroups = new MethodInvokerAction( SelectNewsgroups, OnUpdateSelectNewsgroups );
IAction actionAttachFile = new MethodInvokerAction( InsertAttachment, OnUpdateInsertAttachment );
IAction actionUndo = new CommandProcessorAction( "Undo" );
IAction actionRedo = new CommandProcessorAction( "Redo" );
IAction actionCut = new CommandProcessorAction( DisplayPaneCommands.Cut );
IAction actionCopy = new CommandProcessorAction( DisplayPaneCommands.Copy );
IAction actionPaste = new CommandProcessorAction( DisplayPaneCommands.Paste );
IAction actionReply2Sender = new Reply2Sender(this);
IAction actionReplyToHerd = new ReplyAction(this);
IAction actionForward = new ForwardArticle( this );
IAction actionDeleteArticle = new MethodInvokerAction(DeleteArticle, OnUpdateDelete);
IAction actionNextArticle = new MethodInvokerAction(DisplayNextArticle, OnUpdateDisplayNextArticle);
IAction actionPreviousArticle = new MethodInvokerAction(DisplayPreviousArticle, OnUpdateDisplayPreviousArticle);
///////////////////////////////
// Initialize the toolbar and populate it with buttons
_toolbarActionManager = new ToolbarActionManager(_toolbar);
_toolbarActionManager.ContextProvider = this;
string sGroup;
///////////////////
sGroup = "File";
_toolbarActionManager.RegisterActionGroup( sGroup, ListAnchor.Last );
_toolbarActionManager.RegisterAction(actionSend, sGroup, ListAnchor.Last, LoadIcon("Send"), "&Send", "Send Article", null, null );
_toolbarActionManager.RegisterAction(actionSave, sGroup, ListAnchor.Last, LoadIcon("Save"), "Save", "Save Article in Drafts", null, null );
///////////////////
sGroup = "Edit";
_toolbarActionManager.RegisterActionGroup( sGroup, ListAnchor.Last );
_toolbarActionManager.RegisterAction(actionCut,sGroup, ListAnchor.Last, LoadIcon("Cut"), "Cut", null, null, null );
_toolbarActionManager.RegisterAction(actionCopy,sGroup, ListAnchor.Last, LoadIcon("Copy"), "Copy", null, null, null );
_toolbarActionManager.RegisterAction(actionPaste,sGroup, ListAnchor.Last, LoadIcon("Paste"), "Paste", null, null, null );
///////////////////
sGroup = "Actions";
_toolbarActionManager.RegisterActionGroup( sGroup, ListAnchor.Last );
_toolbarActionManager.RegisterAction( actionReplyToHerd, sGroup, ListAnchor.Last, LoadIcon("ReplyToHerd"), "Reply", null, null, null );
_toolbarActionManager.RegisterAction( actionReply2Sender, sGroup, ListAnchor.Last, LoadIcon("Reply"), "Reply to Sender", null, null, null );
_toolbarActionManager.RegisterAction( actionForward, sGroup, ListAnchor.Last, LoadIcon("MailForward"), "Forward", "Forward Article", null, null );
_toolbarActionManager.RegisterAction( actionDeleteArticle, sGroup, ListAnchor.Last, LoadIcon("Delete"), null, "Delete", "Delete Article", null );
_toolbarActionManager.RegisterAction(actionAttachFile, sGroup, ListAnchor.Last, LoadIcon("Attach"), "&Insert Attachment…", "Insert Attachment", null, null );
_toolbarActionManager.RegisterAction(actionNewsgroups, sGroup, ListAnchor.Last, LoadIcon("EditMessageForm.PickNewsgroups"), "Newsgroups…", "Select Newsgroups", null, null );
///////////////////
sGroup = "View";
_toolbarActionManager.RegisterActionGroup( sGroup, ListAnchor.Last );
_toolbarActionManager.RegisterAction( actionNextArticle, sGroup, ListAnchor.Last, LoadIcon("Next"), null, "Next Article", null, null );
_toolbarActionManager.RegisterAction(actionPreviousArticle, sGroup, ListAnchor.Last, LoadIcon("Previous"), null, "Previous Article", null, null );
/////////
////////////////////////////////////
// Register the Menu Items actions
_menuactionsmanager = new MenuActionsManager( this, mainMenu1 );
// File
_menuactionsmanager.Add( _postMenuItem, actionSend );
_menuactionsmanager.Add( _saveMenuItem, actionSave );
_menuactionsmanager.Add( _saveAndCloseMenuItem, actionSaveAndClose );
// Edit
_menuactionsmanager.Add( _undoMenuItem, actionUndo );
_menuactionsmanager.Add( _redoMenuItem, actionRedo );
_menuactionsmanager.Add( _cutMenuItem, actionCut );
_menuactionsmanager.Add( _copyMenuItem, actionCopy );
_menuactionsmanager.Add( _pasteMenuItem, actionPaste );
_menuactionsmanager.Add( _menuitemNewsgroups, actionNewsgroups );
_menuactionsmanager.Add( _menuitemAttachFile, actionAttachFile );
// Actions
_menuactionsmanager.Add( _menuitemReply2Sender, actionReply2Sender );
_menuactionsmanager.Add( _menuitemReply2Herd, actionReplyToHerd );
_menuactionsmanager.Add( _menuitemForward, actionForward );
_menuactionsmanager.Add( _menuitemDeleteArticle, actionDeleteArticle );
_menuactionsmanager.Add( _menuitemNext, actionNextArticle );
_menuactionsmanager.Add( _menuitemPrevious, actionPreviousArticle );
////////////////////////////////////////
// Initialize the keyboard actions
_hashKeyboardActions = new IntHashTable();
_hashKeyboardActions[(int) (Keys.Control | Keys.Enter)] = actionSend;
_hashKeyboardActions[(int) (Keys.Alt | Keys.S)] = actionSend;
_hashKeyboardActions[(int) Keys.Escape] = actionClose;
_hashKeyboardActions[(int) (Keys.Control | Keys.S)] = actionSave;
_hashKeyboardActions[(int) (Keys.Alt | Keys.I)] = actionAttachFile;
}
private void InitializeColumns()
{
_attachList.AllowColumnReorder = false;
_attachList.Columns.Add( new ResourceIconColumn() );
nameCol = _attachList.AddColumn( Core.Props.Name );
sizeCol = _attachList.AddColumn( Core.Props.Size );
nameCol.ShowHeader = true;
// nameCol.FixedSize = false;
nameCol.AutoSize = true;
nameCol.Width = 100;
nameCol.Text = "Name";
sizeCol.ShowHeader = sizeCol.FixedSize = true;
sizeCol.Width = 56;
sizeCol.Text = "Size";
}
private void InitializeFormSize()
{
Rectangle bounds = Screen.PrimaryScreen.Bounds;
Width = ( bounds.Width * 3 ) >> 2;
Height = ( bounds.Height * 3 ) >> 2;
Left = bounds.Width >> 3;
Top = bounds.Height >> 3;
}
private static void OnBeforeBrowserNavigate(object sender, BeforeNavigateEventArgs args)
{
args.Cancel = true; // Prevent from the unwanted navigation
}
protected override void Dispose( bool disposing )
{
if( disposing )
{
Core.UIManager.MainWindowClosing -= EditMessageForm_Closing;
_toolbarActionManager.Dispose();
_encodingMenuItem.Dispose();
/*
foreach(MenuItem mi in _encodingMenuItem.MenuItems) // TODO: I think this can freely be removed as it is not needed after the wire-up scheme has been changed
mi.Click -= OnEncodingMenuItemClicked;
*/
if(components != null)
{
components.Dispose();
}
if(_menuactionsmanager != null)
{
_menuactionsmanager.Dispose();
_menuactionsmanager = null;
}
}
base.Dispose( disposing );
}
#region Windows Form Designer generated code
private void InitializeComponent()
{
this.components = new Container();
ResourceManager resources = new ResourceManager( typeof(EditMessageForm) );
_subjectBox = new JetTextBox();
_groupsLabel = new ResourceListLinkLabel();
_fromlabel = new Label();
_subjectLabel = new Label();
_statusBar = new StatusBar();
_openAttachDialog = new OpenFileDialog();
_attachList = new ResourceListView2();
_attachListMenu = new ContextMenu();
_removeAttachMenuItem = new MenuItem();
_fullNameToolTip = new ToolTip( this.components );
_headerPanel = new Panel();
_newsgroupsLabel = new JetLinkLabel();
_serverComboBox = new ResourceComboBox();
_serverLabel = new Label();
_toolbarSeparator = new Separator();
_fromTextLabel = new JetTextBox();
_fromComboBox = new ComboBox();
_bodyListSplitter = new Splitter();
_bodyPanel = new Panel();
_toolbar = new ToolStrip();
mainMenu1 = new MenuStrip();
_fileMenuItem = new ToolStripMenuItem();
_newMenuItem = new ToolStripMenuItem();
_postMenuItem = new ToolStripMenuItem();
_menuSeparator1 = new ToolStripSeparator();
_saveMenuItem = new ToolStripMenuItem();
_saveAndCloseMenuItem = new ToolStripMenuItem();
_menuSeparator4 = new ToolStripSeparator();
_closeMenuItem = new ToolStripMenuItem();
_editMenuItem = new ToolStripMenuItem();
_undoMenuItem = new ToolStripMenuItem();
_redoMenuItem = new ToolStripMenuItem();
_menuSeparator5 = new ToolStripSeparator();
_cutMenuItem = new ToolStripMenuItem();
_copyMenuItem = new ToolStripMenuItem();
_pasteMenuItem = new ToolStripMenuItem();
_formatMenuItem = new ToolStripMenuItem();
_encodingMenuItem = new ToolStripMenuItem();
_menuitemReply2Sender = new ToolStripMenuItem();
_menuitemReply2Herd = new ToolStripMenuItem();
_menuitemForward = new ToolStripMenuItem();
_menuitemDeleteArticle = new ToolStripMenuItem();
_menuitemNewsgroups = new ToolStripMenuItem();
_menuitemAttachFile = new ToolStripMenuItem();
_menuitemNext = new ToolStripMenuItem();
_menuitemPrevious = new ToolStripMenuItem();
_menuActions = new ToolStripMenuItem();
_headerPanel.SuspendLayout();
_bodyPanel.SuspendLayout();
this.SuspendLayout();
//
// _subjectBox
//
this._subjectBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this._subjectBox.ContextProvider = null;
this._subjectBox.EmptyText = null;
this._subjectBox.Location = new System.Drawing.Point(100, 92);
this._subjectBox.Name = "_subjectBox";
this._subjectBox.Size = new System.Drawing.Size(688, 21);
this._subjectBox.TabIndex = 4;
this._subjectBox.Text = "";
this._subjectBox.TextChanged += new System.EventHandler(this._subjectBox_TextChanged);
//
// _groupsLabel
//
this._groupsLabel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this._groupsLabel.AutoScroll = true;
this._groupsLabel.Location = new System.Drawing.Point(100, 66);
this._groupsLabel.Name = "_groupsLabel";
this._groupsLabel.ResourceList = null;
this._groupsLabel.Size = new System.Drawing.Size(684, 20);
this._groupsLabel.TabIndex = 3;
//
// _fromlabel
//
this._fromlabel.FlatStyle = System.Windows.Forms.FlatStyle.System;
this._fromlabel.Location = new System.Drawing.Point(8, 10);
this._fromlabel.Name = "_fromlabel";
this._fromlabel.Size = new System.Drawing.Size(90, 17);
this._fromlabel.TabIndex = 6;
this._fromlabel.Text = "From:";
this._fromlabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
//
// _subjectLabel
//
this._subjectLabel.FlatStyle = System.Windows.Forms.FlatStyle.System;
this._subjectLabel.Location = new System.Drawing.Point(8, 94);
this._subjectLabel.Name = "_subjectLabel";
this._subjectLabel.Size = new System.Drawing.Size(90, 17);
this._subjectLabel.TabIndex = 10;
this._subjectLabel.Text = "Subject:";
this._subjectLabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
//
// _statusBar
//
this._statusBar.AllowDrop = true;
this._statusBar.Location = new System.Drawing.Point(0, 544);
this._statusBar.Name = "_statusBar";
this._statusBar.Size = new System.Drawing.Size(792, 22);
this._statusBar.TabIndex = 11;
this._statusBar.DragDrop += new System.Windows.Forms.DragEventHandler(this.EditMessageForm_DragDrop);
this._statusBar.DragOver += new System.Windows.Forms.DragEventHandler(this.EditMessageForm_DragOver);
//
// _openAttachDialog
//
this._openAttachDialog.Multiselect = true;
//
// _attachList
//
this._attachList.AllowDrop = true;
this._attachList.BorderStyle = System.Windows.Forms.BorderStyle.None;
this._attachList.ContextMenu = this._attachListMenu;
this._attachList.Dock = System.Windows.Forms.DockStyle.Right;
this._attachList.FullRowSelect = true;
this._attachList.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable;
this._attachList.HideSelection = false;
this._attachList.Location = new System.Drawing.Point(628, 0);
this._attachList.Name = "_attachList";
this._attachList.Size = new System.Drawing.Size(160, 394);
this._attachList.TabIndex = 3;
this._attachList.SelectionChanged += new System.EventHandler(this._attachListView_SelectedIndexChanged);
this._attachList.Resize += new System.EventHandler(this._attachListView_Resize);
this._attachList.DragOver += new System.Windows.Forms.DragEventHandler(this.EditMessageForm_DragOver);
this._attachList.DragDrop += new System.Windows.Forms.DragEventHandler(this.EditMessageForm_DragDrop);
this._attachList.KeyDown += new System.Windows.Forms.KeyEventHandler(this._attachListView_KeyDown);
//
// _attachListMenu
//
this._attachListMenu.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
this._removeAttachMenuItem});
//
// _removeAttachMenuItem
//
this._removeAttachMenuItem.Index = 0;
this._removeAttachMenuItem.Text = "Remove";
this._removeAttachMenuItem.Click += new System.EventHandler(this._removeAttachMenuItem_Click);
//
// _headerPanel
//
this._headerPanel.AllowDrop = true;
this._headerPanel.Controls.Add(this._newsgroupsLabel);
this._headerPanel.Controls.Add(this._serverComboBox);
this._headerPanel.Controls.Add(this._serverLabel);
this._headerPanel.Controls.Add(this._toolbarSeparator);
this._headerPanel.Controls.Add(this._fromTextLabel);
this._headerPanel.Controls.Add(this._fromComboBox);
this._headerPanel.Controls.Add(this._subjectLabel);
this._headerPanel.Controls.Add(this._subjectBox);
this._headerPanel.Controls.Add(this._fromlabel);
this._headerPanel.Controls.Add(this._groupsLabel);
this._headerPanel.Dock = System.Windows.Forms.DockStyle.Top;
this._headerPanel.Location = new System.Drawing.Point(0, 26);
this._headerPanel.Name = "_headerPanel";
this._headerPanel.Size = new System.Drawing.Size(792, 120);
this._headerPanel.TabIndex = 0;
this._headerPanel.DragDrop += new System.Windows.Forms.DragEventHandler(this.EditMessageForm_DragDrop);
this._headerPanel.DragOver += new System.Windows.Forms.DragEventHandler(this.EditMessageForm_DragOver);
//
// _newsgroupsLabel
//
this._newsgroupsLabel.AutoSize = false;
this._newsgroupsLabel.Cursor = System.Windows.Forms.Cursors.Hand;
this._newsgroupsLabel.ForeColor = System.Drawing.Color.FromArgb(((System.Byte)(70)), ((System.Byte)(70)), ((System.Byte)(211)));
this._newsgroupsLabel.Location = new System.Drawing.Point(8, 66);
this._newsgroupsLabel.Name = "_newsgroupsLabel";
this._newsgroupsLabel.Size = new System.Drawing.Size(90, 17);
this._newsgroupsLabel.TabIndex = 0;
this._newsgroupsLabel.TabStop = false;
this._newsgroupsLabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
this._newsgroupsLabel.Click += new System.EventHandler(this._newsgroupsLabel_Click);
//
// _serverComboBox
//
this._serverComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this._serverComboBox.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawFixed;
this._serverComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this._serverComboBox.Location = new System.Drawing.Point(100, 38);
this._serverComboBox.Name = "_serverComboBox";
this._serverComboBox.Size = new System.Drawing.Size(688, 22);
this._serverComboBox.TabIndex = 2;
this._serverComboBox.SelectedIndexChanged += new System.EventHandler(this._serverComboBox_SelectedIndexChanged);
//
// _serverLabel
//
this._serverLabel.FlatStyle = System.Windows.Forms.FlatStyle.System;
this._serverLabel.Location = new System.Drawing.Point(8, 38);
this._serverLabel.Name = "_serverLabel";
this._serverLabel.Size = new System.Drawing.Size(90, 17);
this._serverLabel.TabIndex = 13;
this._serverLabel.Text = "News Server:";
this._serverLabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
//
// _toolbarSeparator
//
this._toolbarSeparator.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this._toolbarSeparator.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
this._toolbarSeparator.Location = new System.Drawing.Point(0, 0);
this._toolbarSeparator.Name = "_toolbarSeparator";
this._toolbarSeparator.Size = new System.Drawing.Size(792, 2);
this._toolbarSeparator.TabIndex = 12;
//
// _fromTextLabel
//
this._fromTextLabel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this._fromTextLabel.Location = new System.Drawing.Point(100, 8);
this._fromTextLabel.Name = "_fromTextLabel";
this._fromTextLabel.ReadOnly = true;
this._fromTextLabel.Size = new System.Drawing.Size(671, 21);
this._fromTextLabel.TabIndex = 0;
this._fromTextLabel.Text = "";
this._fromTextLabel.Enter += new System.EventHandler(this._fromTextLabel_Enter);
//
// _fromComboBox
//
this._fromComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this._fromComboBox.Location = new System.Drawing.Point(100, 8);
this._fromComboBox.Name = "_fromComboBox";
this._fromComboBox.Size = new System.Drawing.Size(688, 21);
this._fromComboBox.TabIndex = 1;
this._fromComboBox.KeyDown += new System.Windows.Forms.KeyEventHandler(this._fromBox_KeyDown);
this._fromComboBox.DropDown += new System.EventHandler(this._fromBox_DropDown);
this._fromComboBox.Leave += new System.EventHandler(this._fromBox_Leave);
this._fromComboBox.Enter += new System.EventHandler(this._fromBox_DropDown);
//
// _bodyListSplitter
//
this._bodyListSplitter.Dock = System.Windows.Forms.DockStyle.Right;
this._bodyListSplitter.Location = new System.Drawing.Point(624, 0);
this._bodyListSplitter.Name = "_bodyListSplitter";
this._bodyListSplitter.Size = new System.Drawing.Size(4, 394);
this._bodyListSplitter.TabIndex = 13;
this._bodyListSplitter.TabStop = false;
//
// _bodyPanel
//
this._bodyPanel.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
this._bodyPanel.Controls.Add(this._bodyListSplitter);
this._bodyPanel.Controls.Add(this._attachList);
this._bodyPanel.Dock = System.Windows.Forms.DockStyle.Fill;
this._bodyPanel.Location = new System.Drawing.Point(0, 146);
this._bodyPanel.Name = "_bodyPanel";
this._bodyPanel.Size = new System.Drawing.Size(792, 398);
this._bodyPanel.TabIndex = 1;
this._bodyPanel.DragDrop += new System.Windows.Forms.DragEventHandler(this.EditMessageForm_DragDrop);
this._bodyPanel.DragOver += new System.Windows.Forms.DragEventHandler(this.EditMessageForm_DragOver);
//
// _toolbar
//
this._toolbar.AllowDrop = true;
this._toolbar.Location = new System.Drawing.Point(0, 0);
this._toolbar.Name = "_toolbar";
this._toolbar.Renderer = new GradientRenderer( SystemColors.ControlLightLight, SystemColors.Control );
this._toolbar.Size = new System.Drawing.Size(792, 26);
this._toolbar.TabIndex = 11;
this._toolbar.DragDrop += new System.Windows.Forms.DragEventHandler(this.EditMessageForm_DragDrop);
this._toolbar.DragOver += new System.Windows.Forms.DragEventHandler(this.EditMessageForm_DragOver);
//
// mainMenu1
//
mainMenu1.Items.AddRange( new ToolStripItem[]{ _fileMenuItem, _editMenuItem, _menuActions, _formatMenuItem});
//
// _fileMenuItem
//
_fileMenuItem.DropDownItems.AddRange( new ToolStripItem[] { _newMenuItem, _postMenuItem, _menuSeparator1,
_saveMenuItem, _saveAndCloseMenuItem,
_menuSeparator4, _closeMenuItem});
this._fileMenuItem.Text = "&File";
//
// _newMenuItem
//
this._newMenuItem.ShortcutKeys = Keys.Control | Keys.N;
this._newMenuItem.Text = "&New";
this._newMenuItem.Click += new System.EventHandler(this._newMenuItem_Click);
//
// _postMenuItem
//
this._postMenuItem.Text = "&Send Article";
this._postMenuItem.ShortcutKeys = Keys.Control | Keys.Enter;
//
// _saveMenuItem
//
this._saveMenuItem.ShortcutKeys = Keys.Control | Keys.S;
this._saveMenuItem.Text = "Sa&ve";
//
// _saveAndCloseMenuItem
//
this._saveAndCloseMenuItem.ShortcutKeys = Keys.Control | Keys.Shift | Keys.S;
this._saveAndCloseMenuItem.Text = "Save and C&lose";
//
// _closeMenuItem
//
this._closeMenuItem.Text = "&Close";
this._closeMenuItem.Click += new System.EventHandler(this._closeMenuItem_Click);
//
// _editMenuItem
//
this._editMenuItem.DropDownItems.AddRange(new ToolStripItem[] { _undoMenuItem, _redoMenuItem,
_menuSeparator5,
_cutMenuItem, _copyMenuItem, _pasteMenuItem,
_menuitemAttachFile, _menuitemNewsgroups});
this._editMenuItem.Text = "&Edit";
this._editMenuItem.DropDownItemClicked += new ToolStripItemClickedEventHandler(_editMenuItem_DropDownItemClicked);
//
// _undoMenuItem
//
this._undoMenuItem.ShortcutKeys = Keys.Control | Keys.Z;
this._undoMenuItem.Text = "&Undo";
//
// _redoMenuItem
//
this._redoMenuItem.ShortcutKeys = Keys.Control | Keys.Y;
this._redoMenuItem.Text = "&Redo";
//
// _cutMenuItem
//
this._cutMenuItem.ShortcutKeys = Keys.Control | Keys.X;
this._cutMenuItem.Text = "Cu&t";
//
// _copyMenuItem
//
this._copyMenuItem.ShortcutKeys = Keys.Control | Keys.C;
this._copyMenuItem.Text = "&Copy";
//
// _pasteMenuItem
//
this._pasteMenuItem.ShortcutKeys = Keys.Control | Keys.V;
this._pasteMenuItem.Text = "&Paste";
//
// _formatMenuItem
//
this._formatMenuItem.DropDownItems.AddRange( new ToolStripItem[] { _encodingMenuItem } );
this._formatMenuItem.Text = "F&ormat";
//
// _encodingMenuItem
//
this._encodingMenuItem.Text = "&Encoding";
_menuitemReply2Sender.Text = "Reply to &Sender";
_menuitemReply2Herd.Text = "&Reply";
_menuitemForward.Text = "&Forward";
_menuitemDeleteArticle.Text = "&Delete";
_menuitemNewsgroups.Text = "&Newsgroups …";
_menuitemAttachFile.Text = "&Insert Attachment…";
_menuitemNext.Text = "&Next Article";
_menuitemPrevious.Text = "&Previous Article";
_menuActions.Text = "&Actions";
_menuActions.DropDownItems.AddRange( new ToolStripItem[]{ _menuitemReply2Herd, _menuitemReply2Sender, _menuitemForward,
_menuitemDeleteArticle, _menuitemNext, _menuitemPrevious} );
//
// EditMessageForm
//
this.AllowDrop = true;
this.AutoScaleBaseSize = new System.Drawing.Size(5, 14);
this.ClientSize = new System.Drawing.Size(792, 566);
this.Controls.Add(this._bodyPanel);
this.Controls.Add(this._headerPanel);
this.Controls.Add(this._statusBar);
this.Controls.Add(this._toolbar);
this.Controls.Add( this.mainMenu1 );
this.MaximizeBox = true;
this.MinimizeBox = true;
this.MinimumSize = new System.Drawing.Size(200, 136);
this.Name = "EditMessageForm";
this.ShowInTaskbar = true;
this.Text = "New Article";
this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.EditMessageForm_KeyDown);
this.Closing += new System.ComponentModel.CancelEventHandler(this.EditMessageForm_Closing);
this.DragOver += new System.Windows.Forms.DragEventHandler(this.EditMessageForm_DragOver);
this.DragDrop += new System.Windows.Forms.DragEventHandler(this.EditMessageForm_DragDrop);
this._headerPanel.ResumeLayout(false);
this._bodyPanel.ResumeLayout(false);
this.ResumeLayout(false);
}
void _editMenuItem_DropDownItemClicked(object sender, ToolStripItemClickedEventArgs e)
{
_undoMenuItem.Enabled = _cutMenuItem.Enabled = _copyMenuItem.Enabled = _pasteMenuItem.Enabled =
_whatWeAreDoing == FormStateVerb.Edit && (ActiveControl is TextBox); // Checking for a TextBox is valid, as JetTextBox extends it
}
#endregion
public static void EditAndPostMessage( IResourceList groups,
string subject, string message, string references,
bool newArticle )
{
EditMessageForm theForm = new EditMessageForm();
theForm.RestoreSettings();
theForm._whatWeAreDoing = FormStateVerb.Edit;
ServerResource server = null;
IContact myself = Core.ContactManager.MySelf;
string myselfDisplayName = Core.ContactManager.GetFullName( myself.Resource );
string from = myselfDisplayName;
string email = myself.DefaultEmailAddress;
if( email != null && email.Length > 0 )
{
from += " <" + email + '>';
}
if( groups == null || groups.Count == 0 )
{
theForm._groups = Core.ResourceStore.EmptyResourceList;
theForm.UpdateStatusBarText();
}
else
{
IResource serverRes = new NewsgroupResource( groups[ 0 ] ).Server;
if( serverRes != null )
{
server = new ServerResource( serverRes );
theForm._serverComboBox.SelectedItem = serverRes;
string userDisplayName = server.UserDisplayName;
if( userDisplayName.Length == 0 )
{
userDisplayName = myselfDisplayName;
}
string userEmailAddress = server.UserEmailAddress;
if( userEmailAddress.Length > 0 )
{
from = userDisplayName + " <" + userEmailAddress + ">";
}
else
{
from = userDisplayName;
}
}
theForm._groups = groups;
}
if( server == null )
{
server = new ServerResource( (IResource) theForm._serverComboBox.SelectedItem );
}
theForm._fromComboBox.Text = theForm._fromTextLabel.Text = from;
theForm._subjectBox.Text = subject;
if( newArticle && server.UseSignature )
{
message += "\r\n";
message += server.MailSignature;
}
// Upload text to the edit control
theForm._browser.SecurityContext = WebSecurityContext.Internet; // No malicious content expected, but some small helper scripts are
theForm._browser.Html = FormatBodyForTextarea( message );
//theForm._bodyBox.Select( 0, 0 ); // TODO: drop or reimplement for the textarea (no problem, but is it needed?)
theForm._references = references;
theForm.ArticleChanged = false;
// Grant input focus either to the subject (for the newly-created article) or to the body edit (for replies)
if( newArticle )
{
theForm._subjectBox.Select();
}
else
{
theForm._browser.Select();
}
theForm.SetCharset( server.Charset );
theForm.UpdateToolbarButtons();
theForm.UpdateAttachListVisibility();
theForm.Show();
theForm.SetNewsgroups();
}
///
/// Formats text of the message body into an HTML page so that it could be loaded into a text area.
///
/// Original message text.
/// The HTML page for editing the text.
public static string FormatBodyForTextarea( string message )
{
StringWriter content = new StringWriter();
content.WriteLine( "" );
content.WriteLine( "
", _sPlainTextEditorId );
// The Textarea Element
content.Write( "");
return content.ToString();
}
public static void EditAndPostMessage( IResource draftArticle )
{
EditMessageForm theForm = (EditMessageForm) _openArticles[ draftArticle.Id ];
if( theForm != null )
{
theForm.Activate();
}
else
{
theForm = new EditMessageForm();
_openArticles[ draftArticle.Id ] = theForm;
theForm.RestoreSettings();
theForm._whatWeAreDoing = FormStateVerb.Edit;
theForm._draftArticle = draftArticle;
IResourceList groups = draftArticle.GetLinksFrom( NntpPlugin._newsGroup, NntpPlugin._propTo );
if( groups == null || groups.Count == 0 )
{
theForm._groups = Core.ResourceStore.EmptyResourceList;
}
else
{
IResource serverRes = new NewsgroupResource( groups[ 0 ] ).Server;
if( serverRes != null )
{
theForm._serverComboBox.SelectedItem = serverRes;
}
theForm._groups = groups;
}
theForm._fromComboBox.Text =
theForm._fromTextLabel.Text = NewsContactHelper.RestoreFromField( draftArticle );
theForm._subjectBox.Text = draftArticle.GetPropText( Core.Props.Subject );
theForm._browser.SecurityContext = WebSecurityContext.Internet; // No malicious content expected, but some small helper scripts are
theForm._browser.Html = FormatBodyForTextarea(draftArticle.GetPropText( Core.Props.LongBody ));
// theForm._bodyBox.Select( 0, 0 ); // TODO: drop or impl
theForm._references = draftArticle.GetPropText( NntpPlugin._propReferenceId );
theForm.ArticleChanged = false;
AddAttachmentResources( theForm, draftArticle );
// Select either subject (if empty) or the body (if we've already composed the subject and now're doing the body)
if( theForm._subjectBox.Text.Length > 0 )
{
theForm._browser.Select();
}
else
{
theForm._subjectBox.Select();
}
theForm.SetCharset( draftArticle.GetPropText( Core.FileResourceManager.PropCharset ) );
theForm.UpdateToolbarButtons();
theForm.UpdateAttachListVisibility();
theForm.SetListenerForArticle( draftArticle );
theForm.Show();
theForm.SetNewsgroups();
theForm.ArticleChanged = true;
}
}
private static void AddAttachmentResources( EditMessageForm form, IResource article )
{
_attaches = article.GetLinksOfTypeLive( null, NntpPlugin._propAttachment );
foreach( IResource res in _attaches )
form._attachList.JetListView.Nodes.Add( res );
}
public static void OpenMessageInSeparateWindow( IResource article )
{
EditMessageForm theForm = (EditMessageForm) _openArticles[ article.Id ];
if( theForm != null )
{
theForm.Activate();
}
else
{
theForm = new EditMessageForm();
theForm.RestoreSettings();
theForm._whatWeAreDoing = FormStateVerb.View;
// Do not trace the event since the article is RO.
theForm._subjectBox.TextChanged -= theForm._subjectBox_TextChanged;
theForm.OpenArticle(article);
theForm.Show();
if( article.HasProp( NntpPlugin._propIsUnread ) )
{
new ResourceProxy( article ).SetProp( NntpPlugin._propIsUnread, false );
}
}
}
private void OpenArticle( IResource article )
{
#region Preconditions
if( article == null )
throw new ArgumentNullException( "article", "EditMessageForm.OpenArticle -- Input resource can not be NULL." );
#endregion Preconditions
_openArticles[ article.Id ] = this;
_groups = article.GetLinksFrom( NntpPlugin._newsGroup, NntpPlugin._propTo );
if( _groups.Count > 0 )
{
IResource serverRes = new NewsgroupResource( _groups[ 0 ] ).Server;
if( serverRes != null )
{
_serverComboBox.Enabled = true;
_serverComboBox.SelectedItem = serverRes;
}
}
SetArticleReadonly( true );
_browser.Visible = true;
_toolbar.Visible = true;
_fromComboBox.Visible = false;
_fromTextLabel.Width = _fromComboBox.Width;
_subjectBox.BackColor = SystemColors.Window;
IResourceBrowser rBrowser = Core.ResourceBrowser;
if( rBrowser.VisibleResources.IndexOf( article ) >=0 )
{
rBrowser.SelectResource( article );
}
_fromTextLabel.Text = NewsContactHelper.RestoreFromField( article );
SetNewsgroups();
_subjectBox.Text = article.GetPropText( Core.Props.Subject );
_browser.SecurityContext = _browserContext;
WordPtr[] words = new WordPtr[0];
try
{
_browser.Html = ArticlePreviewPane.ArticleBody2Html( article, ref words );
}
catch( Exception e )
{
_browser.Html = e.Message;
}
_browser.Show();
_browser.Select();
AddAttachmentResources( this, article );
_attachList.ContextMenu = null;
_attachList.ShowContextMenu = true;
SetCharset( article.GetPropText( Core.FileResourceManager.PropCharset ) );
UpdateToolbarButtons();
UpdateAttachListVisibility();
/**
* closing window if article is deleted
*/
SetListenerForArticle( article );
if( article.HasProp( NntpPlugin._propHasNoBody ) )
{
RefreshArticleAction.RefreshArticleImpl( article.ToResourceList() );
}
}
private void SetListenerForArticle( IResource article )
{
if( _liveArticle != null )
{
IResource oldArticle = GetListenedArticle();
if ( oldArticle != null )
{
if( oldArticle == article )
{
return;
}
_openArticles.Remove( oldArticle.Id );
}
_liveArticle.Dispose();
}
_liveArticle = article.ToResourceListLive();
_liveArticle = _liveArticle.Minus( Core.ResourceStore.FindResourcesWithProp( null, Core.Props.IsDeleted ) );
_liveArticle.ResourceDeleting += EditMessageForm_ResourceDeleting;
_liveArticle.ResourceChanged += _liveArticle_ResourceChanged;
}
private IResource GetListenedArticle()
{
IResource result = null;
if( _liveArticle != null )
{
try
{
lock( _liveArticle )
{
if( _liveArticle.Count > 0 )
{
result = _liveArticle[ 0 ];
}
}
}
catch( InvalidResourceIdException )
{
result = null;
}
}
return result;
}
private static IResource GetNextArticle( IResource article )
{
IResource result = article;
while( result != null )
{
result = Core.ResourceBrowser.GetResourceBelow( result );
if( result == null || result.Type == NntpPlugin._newsArticle )
{
break;
}
}
return result;
}
private static IResource GetPrevArticle( IResource article )
{
IResource result = article;
while( result != null )
{
result = Core.ResourceBrowser.GetResourceAbove( result );
if( result == null || result.Type == NntpPlugin._newsArticle )
{
break;
}
}
return result;
}
private void _liveArticle_ResourceChanged( object sender, ResourcePropIndexEventArgs e )
{
IPropertyChangeSet changeSet = e.ChangeSet;
IResource article = e.Resource;
if( article != _draftArticle )
{
if( changeSet.IsPropertyChanged( Core.Props.LongBody ) ||
changeSet.IsPropertyChanged( NntpPlugin._propHtmlContent ) ||
changeSet.IsPropertyChanged( Core.Props.Subject ) ||
changeSet.IsPropertyChanged( Core.ContactManager.Props.LinkFrom ) ||
changeSet.IsPropertyChanged( Core.ResourceStore.PropTypes[ "NoFormat" ].Id ) )
{
Core.UIManager.QueueUIJob( new ResourceDelegate( OpenArticle ), e.Resource );
}
}
else
{
if( changeSet.IsPropertyChanged( Core.Props.Parent ) &&
NewsFolders.IsInFolder( article, NewsFolders.SentItems ) )
{
AsyncClose( null );
}
}
}
private void _subjectBox_TextChanged(object sender, EventArgs e)
{
string subject = _subjectBox.Text;
Text = ( subject.Length == 0 ) ? "New Article" : subject;
ArticleChanged = true;
_statusBar.Text = string.Empty;
UpdateToolbarButtons();
}
private void EditMessageForm_KeyDown(object sender, KeyEventArgs e)
{
KeyboardHandler( e );
}
private void EditMessageForm_Closing(object sender, CancelEventArgs e)
{
if( ArticleChanged )
{
DialogResult result = MessageBox.Show( this,
"Article has been modified. Save it in Drafts folder?",
"Save Article", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question );
if ( result == DialogResult.Cancel )
{
e.Cancel = true;
return;
}
else if ( result == DialogResult.Yes )
{
SaveArticle();
}
else if( result == DialogResult.No )
{
if( _draftArticle != null )
{
new ResourceProxy( _draftArticle ).Delete();
_draftArticle = null;
}
}
}
Core.UIManager.MainWindowClosing -= EditMessageForm_Closing;
ArticleChanged = false;
if( _liveArticle != null )
{
IResource article = GetListenedArticle();
if( article != null && !article.IsDeleting )
{
_openArticles.Remove( article.Id );
}
_liveArticle.Dispose();
_liveArticle = null;
}
if( _draftArticle != null )
{
_openArticles.Remove( _draftArticle.Id );
}
}
private void _attachListView_SelectedIndexChanged(object sender, EventArgs e)
{
IResourceList selectedList = _attachList.GetSelectedResources();
if( selectedList.Count > 0 )
{
IResource selected = selectedList[ 0 ];
_fullNameToolTip.SetToolTip( _attachList,
Path.Combine( selected.GetPropText( NntpPlugin._propDirectory ),
selected.GetPropText( Core.Props.Name ) ) );
}
}
private void _attachListView_Resize(object sender, EventArgs e)
{
if( _attachList.Width > 4 )
{
sizeCol.Width = _attachList.Width / 3 + 1;
nameCol.Width = _attachList.Width - sizeCol.Width - 4;
}
}
private void _removeAttachMenuItem_Click(object sender, EventArgs e)
{
RemoveSelectedAttachments();
}
private void _fromTextLabel_Enter(object sender, EventArgs e)
{
if( _fromComboBox.Visible )
{
Core.UIManager.QueueUIJob( new MethodInvoker( MakeFromTextInvisible ) );
}
}
private void _fromBox_DropDown(object sender, EventArgs e)
{
_fromTextLabel.Visible = false;
}
private void _fromBox_Leave(object sender, EventArgs e)
{
Core.UIManager.QueueUIJob( new MethodInvoker( UpdateFromText ) );
}
private void _fromBox_KeyDown(object sender, KeyEventArgs e)
{
KeyboardHandler( e );
}
private void _attachListView_KeyDown(object sender, KeyEventArgs e)
{
if( e.KeyCode == Keys.Delete && !e.Alt && !e.Control && !e.Shift )
{
RemoveSelectedAttachments();
}
else
{
KeyboardHandler( e );
}
}
private void _browser_KeyDown( object sender, KeyEventArgs e )
{
// Check if this key could be processed by keyboard handler or it should always be processed by the browser itself
if( !JetTextBox.IsEditorKey( e.KeyData ) )
KeyboardHandler( e );
}
private void _serverComboBox_SelectedIndexChanged( object sender, EventArgs e )
{
if( _groups != null )
{
IResource server = (IResource) _serverComboBox.SelectedItem;
if( server == null )
{
_groupsLabel.ResourceList = _groups = Core.ResourceStore.EmptyResourceList;
}
else
{
_groupsLabel.ResourceList = _groups = _groups.Intersect(
new ServerResource( server ).Groups, true );
}
UpdateToolbarButtons();
}
}
private void _newsgroupsLabel_Click(object sender, EventArgs e)
{
if( !_isBusy )
{
SelectNewsgroups(GetContext( ActionContextKind.Toolbar ));
}
}
private void _newMenuItem_Click(object sender, EventArgs e)
{
EditAndPostMessage( _groups, string.Empty, string.Empty, string.Empty, true );
}
private void OnSaveAndClose(IActionContext context )
{
SaveArticle();
AsyncClose( null );
}
private void _closeMenuItem_Click(object sender, EventArgs e)
{
AsyncClose( null );
}
private void OnEncodingMenuItemClicked(object sender, EventArgs e)
{
// Get the menu item that has been clicked (selected)
EncodingMenuItem miClicked = sender as EncodingMenuItem;
if(miClicked == null)
throw new InvalidOperationException("An encoding menu item event has come from a wrong object.");
// Switch the charset
_charset = miClicked.Charset;
// Check the clicked item, uncheck all the others
OnUpdateSelectedCharset();
// Update the article encoding according to the new selection
IResource article = GetListenedArticle();
if( article != null )
{
Core.ResourceAP.QueueJob( JobPriority.Immediate,
new ReencodeArticleDelegate( ReencodeArticle ), article );
}
}
private void EditMessageForm_DragOver( object sender, DragEventArgs e )
{
e.Effect = DragDropEffects.None;
IResourceList resources = e.Data.GetData( typeof( IResourceList ) ) as IResourceList;
if( resources != null )
{
foreach( IResource res in resources )
{
if( File.Exists( IOTools.Combine( res.GetPropText( NntpPlugin._propDirectory ),
res.GetPropText( Core.Props.Name ) ) ) )
{
e.Effect = DragDropEffects.Link;
}
}
}
else if( e.Data.GetDataPresent( DataFormats.FileDrop, false ) )
{
e.Effect = DragDropEffects.Link;
}
}
private void EditMessageForm_DragDrop(object sender, DragEventArgs e)
{
IResourceList resources = e.Data.GetData( typeof( IResourceList ) ) as IResourceList;
if( resources != null )
{
foreach( IResource res in resources )
{
if( File.Exists( IOTools.Combine( res.GetPropText( NntpPlugin._propDirectory ),
res.GetPropText( Core.Props.Name ) ) ) )
{
AddAttachment( res );
}
}
UpdateAttachListVisibility();
}
else
{
string[] filenames = (string[]) e.Data.GetData( DataFormats.FileDrop );
AddAttachments( filenames );
}
}
private void AddAttachments( string[] filenames )
{
foreach( string filename in filenames )
{
FileInfo fi = IOTools.GetFileInfo( filename );
if( fi != null )
{
IResource attachment = Core.ResourceStore.NewResourceTransient( NntpPlugin._unknownFileResourceType );
attachment.SetProp( Core.Props.Name, fi.Name );
attachment.SetProp( Core.Props.Size, (int) fi.Length );
attachment.SetProp( NntpPlugin._propDirectory, fi.DirectoryName );
AddAttachment( attachment );
}
}
UpdateAttachListVisibility();
}
private void AddAttachment( IResource res )
{
_attaches = _attaches.Union( res.ToResourceListLive() );
_attachList.JetListView.Nodes.Add( res );
if( _draftArticle != null )
{
ResourceProxy proxy = new ResourceProxy( res );
proxy.AsyncPriority = JobPriority.Immediate;
proxy.AddLink( NntpPlugin._propAttachment, _draftArticle );
}
ArticleChanged = true;
}
private delegate void ReencodeArticleDelegate( IResource article );
private void ReencodeArticle( IResource article )
{
string oldCharset = article.GetPropText( Core.FileResourceManager.PropCharset );
if( oldCharset.Length > 0 )
{
Encoding newEncoding = MIMEParser.GetEncodingExceptionSafe( _charset.Name );
Encoding oldEncoding = MIMEParser.GetEncodingExceptionSafe( oldCharset );
article.SetProp( Core.Props.LongBody,
newEncoding.GetString( oldEncoding.GetBytes( article.GetPropText( Core.Props.LongBody ) ) ) );
if( article.HasProp( NntpPlugin._propHtmlContent ) )
{
article.SetProp( NntpPlugin._propHtmlContent,
newEncoding.GetString( oldEncoding.GetBytes( article.GetPropText( NntpPlugin._propHtmlContent ) ) ) );
}
}
else
{
article.SetProp( Core.Props.LongBody,
MIMEParser.TranslateRawStringInCharset( _charset.Name, article.GetPropText( Core.Props.LongBody ) ) );
if( article.HasProp( NntpPlugin._propHtmlContent ) )
{
article.SetProp( NntpPlugin._propHtmlContent,
MIMEParser.TranslateRawStringInCharset( _charset.Name, article.GetPropText( NntpPlugin._propHtmlContent ) ) );
}
}
article.SetProp( Core.FileResourceManager.PropCharset, _charset.Name );
// correct from for a specific charset
string from = article.GetPropText( NntpPlugin._propRawFrom );
IContact sender;
NewsArticleParser.ParseFrom( article, NewsArticleParser.TranslateHeader( _charset.Name, from ), out sender );
// correct subject for a specific charset
string subject = article.GetPropText( NntpPlugin._propRawSubject );
if( subject.Length > 0 )
{
article.SetProp( Core.Props.Subject, NewsArticleParser.TranslateHeader( _charset.Name, subject ) );
}
}
private void DisplayNextArticle( IActionContext context )
{
IResource article = GetListenedArticle();
if( article != null )
{
// Fix OM-13062:
// When user opens prelast article in the list and clicks on the
// "Next" toolbar button too fast then next resource is null;
IResource next = GetNextArticle( article );
if( next != null )
OpenArticle( next );
}
}
private void DisplayPreviousArticle( IActionContext context )
{
IResource article = GetListenedArticle();
if( article != null )
{
IResource prev = GetPrevArticle( article );
if( prev != null )
OpenArticle( prev );
}
}
private void DeleteArticle( IActionContext context )
{
IResource article = GetListenedArticle();
if( article != null )
{
IResourceDeleter deleter = Core.PluginLoader.GetResourceDeleter( article.Type );
if( deleter != null )
{
Core.ResourceAP.QueueJob(
JobPriority.AboveNormal, new ResourceDelegate( deleter.DeleteResource ), article );
}
}
}
private void DoPost( IActionContext context )
{
if( _toolbar.Enabled && !_isBusy )
{
if( _subjectBox.Text.Length == 0 )
{
string newSubject = Core.UIManager.InputString( "Send Message",
"You did not specify a subject for this message. If you would like to provide one," +
" please type it now.",
"(no subject)",
null,
this,
InputStringFlags.AllowEmpty );
if ( newSubject == null )
{
SetArticleReadonly( false );
return;
}
_subjectBox.Text = newSubject;
}
_toolbar.Enabled = false;
SetArticleReadonly( true );
_isBusy = true;
_attachList.Enabled = false;
ArticleChanged = true;
SaveArticle();
if( _draftArticle == null )
{
SetArticleReadonly( false );
_toolbar.Enabled = true;
_attachList.Enabled = true;
_isBusy = false;
}
else
{
_statusBar.Text = "Posting article...";
IResource server = (IResource) _serverComboBox.SelectedItem;
if( server != null && server.HasProp( NntpPlugin._propPutInOutbox ) )
{
NewsFolders.PlaceResourceToFolder( _draftArticle, NewsFolders.Outbox );
AsyncClose( null );
}
else
{
NntpClientHelper.PostArticle( _draftArticle, PostingFinished, true );
}
}
}
}
private void PostingFinished( AsciiProtocolUnit unit )
{
NntpPostArticleUnit postUnit = (NntpPostArticleUnit) unit;
if( unit != null )
{
string error = postUnit.Error;
if( error == null )
{
ArticleChanged = false;
AsyncClose( null );
}
else
{
string errorMessage = "Posting failed. ";
if( error.Length > 0 )
{
errorMessage += error;
}
_statusBar.Text = errorMessage;
SetArticleReadonly( false );
_toolbar.Enabled = true;
_isBusy = false;
_attachList.Enabled = true;
}
}
}
private void InsertAttachment( IActionContext context )
{
if( _openAttachDialog.InitialDirectory.Length == 0 )
{
_openAttachDialog.InitialDirectory = Environment.GetFolderPath( Environment.SpecialFolder.Personal );
}
if( _openAttachDialog.ShowDialog( this ) == DialogResult.OK )
{
string[] filenames = _openAttachDialog.FileNames;
AddAttachments( filenames );
}
}
private void RemoveSelectedAttachments()
{
IResourceList selected = _attachList.GetSelectedResources();
if( selected.Count > 0 )
{
foreach( IResource res in selected )
{
_attachList.JetListView.Nodes.Remove( res );
}
_attaches = _attaches.Minus( selected );
ArticleChanged = true;
UpdateAttachListVisibility();
}
}
private void SelectNewsgroups( IActionContext context )
{
IResource server = (IResource) _serverComboBox.SelectedItem;
if( server != null )
{
IResourceList selectedGroups = server.ToResourceList();
selectedGroups = Core.UIManager.SelectResourcesFromList( this,
selectedGroups.Union( new ServerResource( server ).AllSubNodes ), "Select Newsgroups", _groups );
if( selectedGroups != null && selectedGroups.Count > 0 )
{
if( selectedGroups.Count == _groups.Count &&
selectedGroups.Union( _groups ).Count == _groups.Count )
{
return;
}
_groups = selectedGroups;
SetNewsgroups();
UpdateToolbarButtons();
UpdateStatusBarText();
}
}
}
private void SetNewsgroups()
{
_groupsLabel.ResourceList = _groups;
}
///
/// Sets the message's charset to a new value.
/// Does not change the current charset if the charset name is invalid.
/// The default is system's default body charset.
///
private void SetCharset( string charset )
{
Guard.NullArgument( charset, "charset" );
CharsetsEnum.Charset charsetNew = CharsetsEnum.TryGetCharset( charset );
Debug.Assert(charsetNew != null, "The charset name passed into the EMF.SetCharset does not resolve to a valid charset.");
if(charsetNew != null)
{
_charset = charsetNew;
OnUpdateSelectedCharset();
}
}
private void UpdateToolbarButtons()
{
// Toolbar buttons
_toolbarActionManager.UpdateToolbarActions();
// Miscellanous
if( _whatWeAreDoing == FormStateVerb.View )
_newsgroupsLabel.ClickableLink = false;
}
private void UpdateStatusBarText()
{
if( _groups.Count == 0 )
{
_statusBar.Text = "Please select newsgroup(s)...";
_statusBar.ForeColor = Color.Red;
}
else
{
_statusBar.Text = string.Empty;
_statusBar.ForeColor = Color.Black;
}
}
private void UpdateAttachListVisibility()
{
SuspendLayout();
_bodyListSplitter.Visible = _attachList.Visible = _attaches.Count > 0;
int splitterIndex = _bodyPanel.Controls.GetChildIndex( _bodyListSplitter );
int attachIndex = _bodyPanel.Controls.GetChildIndex( _attachList );
if( attachIndex < splitterIndex )
{
_bodyPanel.Controls.SetChildIndex( _attachList, splitterIndex );
_bodyPanel.Controls.SetChildIndex( _bodyListSplitter, attachIndex );
}
ResumeLayout();
}
private void EditMessageForm_ResourceDeleting( object sender, ResourceIndexEventArgs e )
{
AsyncClose( null );
}
private void UpdateFromText()
{
if( _fromTextLabel.Text != _fromComboBox.Text )
{
_fromTextLabel.Text = _fromComboBox.Text;
ArticleChanged = true;
}
_fromTextLabel.Visible = true;
}
private void MakeFromTextInvisible()
{
_fromTextLabel.Visible = false;
}
private void KeyboardHandler( KeyEventArgs e )
{
IntHashTable.Entry entry = _hashKeyboardActions.GetEntry( (int) e.KeyData );
if( entry != null )
{
IAction action = (IAction) entry.Value;
IActionContext context = GetContext( ActionContextKind.Keyboard );
ActionPresentation presentation = new ActionPresentation();
presentation.Reset();
action.Update( context, ref presentation );
if(presentation.Enabled)
{
action.Execute( context );
e.Handled = true;
return;
}
}
if( (!JetTextBox.IsEditorKey(e.KeyData)) && (Core.ActionManager.ExecuteKeyboardAction(GetContext( ActionContextKind.Keyboard ), e.KeyData)))
e.Handled = true;
return;
}
private void AsyncClose( IActionContext context )
{
Core.UIManager.QueueUIJob( new MethodInvoker( Close ) );
}
private string CreateNntpBody( ServerResource server )
{
CheckUnfitEncoding();
StringBuilder articleBuilder = StringBuilderPool.Alloc();
try
{
string from = _fromTextLabel.Text;
string subject = _subjectBox.Text;
/**
* encode headers if necessary
*/
if( MIMEParser.Has8BitCharacters( from ) )
{
int i = from.IndexOf( "@" );
while( i > 0 && from[ --i ] != ' ' );
if( i <= 0 )
{
from = MIMEParser.CreateQuotedPrintableMIMEString( _charset.Name, from );
}
else
{
from = MIMEParser.CreateQuotedPrintableMIMEString( _charset.Name, from.Substring( 0, i ) ) +
from.Substring( i );
}
}
if( MIMEParser.Has8BitCharacters( subject ) )
{
subject = MIMEParser.CreateBase64MIMEString( _charset.Name, subject );
}
articleBuilder.Append( "From: " );
articleBuilder.Append( from );
articleBuilder.Append( "\r\nSubject: " );
articleBuilder.Append( subject );
articleBuilder.Append( "\r\nNewsgroups: " );
bool first = true;
foreach( IResource group in _groups.ValidResources )
{
if( !first )
{
articleBuilder.Append( ',' );
}
articleBuilder.Append( new NewsgroupResource( group ).Name );
first = false;
}
if( _references.Length > 0 )
{
articleBuilder.Append( "\r\nReferences: " );
articleBuilder.Append( ParseTools.UnescapeCaseSensitiveString( _references ) );
}
string body = RetrieveFromTextarea();
string content_type = "text/plain";
if( _charset.Name.Length > 0 )
{
content_type += "; charset=";
content_type += _charset.Name;
}
string lowerMsgFormat = server.MailFormat.ToLower();
IResourceList attachList = _attaches;
lock( attachList )
{
if( attachList.Count == 0 )
{
if( lowerMsgFormat == "mime" )
{
articleBuilder.Append( "\r\nMIME-Version: 1.0\r\nContent-Transfer-Encoding: 8bit" );
}
content_type += "; format=flowed";
body = MultiPartBodyBuilder.BuildPlainTextFlowedBody( body, _charset.Name );
}
else
{
ArrayList attachments = new ArrayList( attachList.Count );
foreach( IResource attachment in attachList.ValidResources )
{
attachments.Add(
Path.Combine( attachment.GetPropText( NntpPlugin._propDirectory ),
attachment.GetPropText( Core.Props.Name ) ) );
}
string[] attachmentsArray = (string[]) attachments.ToArray( typeof( string ) );
string bodyEncoding = server.MIMETextEncoding;
if( lowerMsgFormat != "mime" )
{
body = MultiPartBodyBuilder.BuildBodyWithUUEncodedInsertions( body, _charset.Name, attachmentsArray );
content_type = string.Empty;
}
else
{
string boundary;
body = MultiPartBodyBuilder.BuildMIMEBody(
body, _charset.Name, bodyEncoding, out boundary, attachmentsArray );
content_type = "multipart/mixed; boundary=\"" + boundary + "\"";
articleBuilder.Append( "\r\nMIME-Version: 1.0\r\nContent-Transfer-Encoding: " );
if( bodyEncoding.ToLower() == "quoted-printable" || bodyEncoding.ToLower() == "base64" )
{
articleBuilder.Append( bodyEncoding );
}
else
{
articleBuilder.Append( "8bit" );
}
}
}
}
if( content_type.Length > 0 )
{
articleBuilder.Append( "\r\nContent-Type: " );
articleBuilder.Append( content_type );
}
articleBuilder.Append( "\r\nX-Newsreader: " );
articleBuilder.Append( "JetBrains " );
articleBuilder.Append( Core.ProductFullName );
articleBuilder.Append( ' ' );
articleBuilder.Append( Core.ProductVersion );
articleBuilder.Append( "\r\n\r\n" );
articleBuilder.Append( body );
if( Settings.ExtraFooterLF )
{
articleBuilder.Append( "\r\n" );
}
articleBuilder.Append( "\r\n." );
return articleBuilder.ToString();
}
finally
{
StringBuilderPool.Dispose( articleBuilder );
}
}
///
/// Checks whether the encoding currently selected in the news message editor fits to the text being edited,
/// ie whether all the symbols can be represented by that encoding.
/// If not, displays a message box that suggests switching to another encoding.
/// TODO: check not only the body, but also the From, Subject and any other encoded field.
///
private void CheckUnfitEncoding()
{
// Check whether the body can be encoded using the specified charset
if(!_bSuppressUnfitEncodingWarning)
{
string body = RetrieveFromTextarea();
string sSourceChar = null, sDestChar = null;
Encoding encoding = MIMEParser.GetEncodingExceptionSafe(_charset.Name);
// Encode forth and back, and see if the result is different
string bodyAfterEncoding = encoding.GetString( encoding.GetBytes( body ));
if(bodyAfterEncoding != body)
{
// If the body length has not changed, check what symbols are failing
if(bodyAfterEncoding.Length == body.Length)
{
for(int a = 0; a < body.Length; a++)
{
if(body[a] != bodyAfterEncoding[a])
{
sSourceChar = body[a].ToString( );
sDestChar = bodyAfterEncoding[a].ToString( );
break;
}
}
}
CharsetsEnum.Charset charsetUtf8 = CharsetsEnum.TryGetCharset( _DefaultCharset );
DialogResult choice;
string title = Core.ProductName + " – Save News Article";
if((sSourceChar == null) || (sDestChar == null))
choice = MessageBox.Show(String.Format(_CommonMessage + "\nWould you like to use the “{1}” charset instead, which will save all the characters?", _charset.Description, charsetUtf8.Description), title, MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation);
else
choice = MessageBox.Show(String.Format(_CommonMessage + "For example, “{2}” will become “{3}”.\n\nWould you like to use the “{1}” charset instead, which will save all the characters?", _charset.Description, charsetUtf8.Description, sSourceChar, sDestChar), title, MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation);
if(choice == DialogResult.Yes)
{
_charset = charsetUtf8;
OnUpdateSelectedCharset();
}
else
_bSuppressUnfitEncodingWarning = true;
}
}
}
///
/// Retrieves the edited body text as plain text from the editing text area and returns it.
///
/// Plain text of the message body.
/// If the browser has not been initialized yet, a Null value is returned.
protected string RetrieveFromTextarea()
{
IHtmlDomDocument doc = _browser.HtmlDocument;
if(doc == null)
return "";
IHtmlDomElement textarea = doc.GetElementById( _sPlainTextEditorId );
if(textarea == null)
return "";
return textarea.InnerText;
}
private void SaveArticle()
{
IResource serverRes = (IResource) _serverComboBox.SelectedItem;
if( ArticleChanged && serverRes != null )
{
ArticleChanged = false;
ServerResource server = new ServerResource( serverRes );
string nntpBody = CreateNntpBody( server );
_draftArticle = NewsFolders.PlaceArticle( _draftArticle, NewsFolders.Drafts, _groups,
_fromTextLabel.Text, _subjectBox.Text, RetrieveFromTextarea(),
_charset.Name, _references, nntpBody, _attaches );
_openArticles[ _draftArticle.Id ] = this;
SetListenerForArticle( _draftArticle );
}
}
private bool ArticleChanged
{
get
{
if( !Visible ) // Form not visible => do not check the article body
return false;
if( _articleChanged )
return true;
if( _whatWeAreDoing == FormStateVerb.View )
return _articleChanged;
string text = RetrieveFromTextarea();
if( text == null ) // The text is not ready yet, which means that it's probably not dirty )
return false;
return ( _draftArticle != null ) && ( _draftArticle.GetPropText( Core.Props.LongBody ) != text );
}
set
{
// this property can be set from non-UI thread, so methods accessing the UI
// (like the ArticleChanged getter) should not be used here
_articleChanged = value;
IAsyncProcessor ap = Core.UserInterfaceAP;
if( !value )
{
ap.CancelTimedJobs( _saveArticleDelegate );
}
else
{
ap.QueueJobAt( DateTime.Now.AddSeconds( 30 ), _saveArticleDelegate );
}
Core.UIManager.QueueUIJob( new SetSaveButtonEnabledDelegate( SetSaveButtonEnabled ), value );
}
}
private delegate void SetSaveButtonEnabledDelegate( bool enabled );
private void SetSaveButtonEnabled( bool enabled )
{
_saveAndCloseMenuItem.Enabled = _saveMenuItem.Enabled = enabled;
}
private void SetArticleReadonly( bool readOnly )
{
//_bodyBox.ReadOnly = readOnly; // TODO: implement
_subjectBox.ReadOnly = readOnly;
_serverComboBox.Enabled = !readOnly;
}
///
/// Returns the action context for the current state of the control.
///
/// The kind of action which is invoked (keyboard, menu and so on).
/// The action context for the specified kind and the current state.
public IActionContext GetContext( ActionContextKind kind )
{
ActionContext context = new ActionContext( kind, this, _liveArticle );
context.SetCommandProcessor( this );
context.SetOwnerForm( this );
return context;
}
///
/// Checks if the command with the specified ID can be executed in the current state
/// of the control.
///
/// The ID of the command.
/// true if the ID of the command is known to the control and can be
/// executed; false otherwise.
public bool CanExecuteCommand( string command )
{
// Check if the focused control can process the action
Control active = ActiveControl;
if((active == null) || (!(active.Focused)))
active = _browser; // Currently, we do not mark browser as being active if it gets activated by a click (as opposed to tab sequence activation), so we do a little hack to avoid directing actions to the subject box if actually the browser is active
if((active is ICommandProcessor) && ((active as ICommandProcessor).CanExecuteCommand(command)))
return true;
return false; // Cannot process myself
}
///
/// Executes the command with the specified ID.
///
/// ID of the command to execute.
public void ExecuteCommand( string command )
{
// Check if the focused control can process the action
Control active = ActiveControl;
if((active == null) || (!(active.Focused)))
active = _browser; // Currently, we do not mark browser as being active if it gets activated by a click (as opposed to tab sequence activation), so we do a little hack to avoid directing actions to the subject box if actually the browser is active
if((active is ICommandProcessor) && ((active as ICommandProcessor).CanExecuteCommand(command)))
{
(active as ICommandProcessor).ExecuteCommand( command );
return;
}
return; // Cannot process myself
}
///
/// Loads an icon from the resources stream.
///
/// Short name of the icon (without namespace prefixs and the extension).
/// Icon object.
private static Icon LoadIcon( string name )
{
Stream stream;
return (((stream = Assembly.GetExecutingAssembly().GetManifestResourceStream( "NntpPlugin.Icons." + name + ".ico" )) != null) ? new Icon( stream ) : null);
}
private void OnUpdateDelete( IActionContext context, ref ActionPresentation presentation )
{
presentation.Visible = (_whatWeAreDoing == FormStateVerb.View);
presentation.Enabled = !_isBusy; // Disable if busy
}
private void OnUpdateDisplayNextArticle( IActionContext context, ref ActionPresentation presentation )
{
presentation.Visible = (_whatWeAreDoing == FormStateVerb.View);
presentation.Enabled = presentation.Visible && !_isBusy && (GetNextArticle( GetListenedArticle() ) != null);
}
private void OnUpdateDisplayPreviousArticle( IActionContext context, ref ActionPresentation presentation )
{
presentation.Visible = (_whatWeAreDoing == FormStateVerb.View);
presentation.Enabled = presentation.Visible && !_isBusy && (GetPrevArticle( GetListenedArticle() ) != null);
}
private void OnSaveArticle( IActionContext context )
{
SaveArticle();
}
private void OnUpdateSaveArticle( IActionContext context, ref ActionPresentation presentation )
{
presentation.Visible = (_whatWeAreDoing == FormStateVerb.Edit);
presentation.Enabled = !_isBusy; // Disable if busy
}
private void OnUpdateDoPost( IActionContext context, ref ActionPresentation presentation )
{
try
{
presentation.Visible = (_whatWeAreDoing == FormStateVerb.Edit);
presentation.Enabled = presentation.Visible && (_groups != null) && (_groups.Count > 0) && !_isBusy;
// Do not enable the Send button until the control is finally created
IHtmlDomDocument htmlDocument; // Foolproof variable to avoid async modification
if((_browser == null) || ((htmlDocument = _browser.HtmlDocument) == null) || (htmlDocument.GetElementById( _sPlainTextEditorId ) == null))
presentation.Enabled = false;
}
catch( NullReferenceException e )
{
Core.ReportBackgroundException( new NullReferenceException( "NRE in OnUpdateDoPost", e ));
presentation.Enabled = false;
}
}
private void OnUpdateInsertAttachment( IActionContext context, ref ActionPresentation presentation )
{
presentation.Visible = _whatWeAreDoing == FormStateVerb.Edit;
presentation.Enabled = !_isBusy; // Disable if busy
}
private void OnUpdateSelectNewsgroups( IActionContext context, ref ActionPresentation presentation )
{
try
{
presentation.Visible = (_whatWeAreDoing == FormStateVerb.Edit);
if( presentation.Visible )
{
IResource server = (IResource) _serverComboBox.SelectedItem;
presentation.Enabled = (server != null) && (new ServerResource( server ).Groups.Count > 0) && !_isBusy; // Disable if busy
}
}
catch( NullReferenceException e )
{
throw new ApplicationException( "NRE in OnUpdateSelectNewsgroups", e );
}
}
///
/// Updates the radio-check on the Encoding submenu items so that only the currently-selected charset was checked.
///
protected void OnUpdateSelectedCharset()
{
foreach( ToolStripItem mi in _encodingMenuItem.DropDownItems )
{
EncodingMenuItem emi;
if((emi = mi as EncodingMenuItem) == null)
continue;
emi.Checked = emi.Charset == _charset;
}
}
#region MenuActionsManager Class — Binds Omea actions to the menu items, and performs presentation state updates
///
/// Updates presentation for the subscribed menu items.
///
public class MenuActionsManager : IDisposable
{
///
/// Maps menu items to the corresponding actions.
///
protected Hashtable _hashMenuActions;
///
/// The context provider.
///
protected IContextProvider _contextprovider;
///
/// The top level menu items listened for the event.
///
protected ToolStripMenuItem[] _miTopLevel;
public MenuActionsManager( IContextProvider contextprovider, ToolStrip menu )
{
//Core.UIManager.EnterIdle += new EventHandler( OnEnterIdle );
_contextprovider = contextprovider;
_hashMenuActions = new Hashtable();
// Attach to the top-level menu-item popups
_miTopLevel = new ToolStripMenuItem[ menu.Items.Count ];
menu.Items.CopyTo( _miTopLevel, 0 );
foreach( ToolStripMenuItem mi in _miTopLevel )
mi.Click += OnTopLevelMenuItemPopup;
}
public void Add( ToolStripMenuItem mi, IAction action )
{
_hashMenuActions.Add( mi, action );
mi.Click += OnMenuItemClicked;
}
#region IDisposable Members
public void Dispose()
{
//if( ICore.Instance != null )
// Core.UIManager.EnterIdle -= new EventHandler( OnEnterIdle );
// Unsubscribe
if( _hashMenuActions != null )
{
foreach( ToolStripMenuItem mi in _hashMenuActions.Keys )
mi.Click -= OnMenuItemClicked;
}
// Unsubscribe from the top-level items
if(_miTopLevel != null)
{
foreach( ToolStripMenuItem mi in _miTopLevel )
mi.Click -= OnTopLevelMenuItemPopup;
_miTopLevel = null;
}
// Detach
_hashMenuActions = null;
}
#endregion
protected void OnEnterIdle( object sender, EventArgs e )
{
if( Core.ResourceStore != null )
{
try { UpdateActions(); }
catch( Exception ex )
{
Core.ReportBackgroundException( ex );
}
}
}
///
/// Update all actions that represent the menu. Executes when a menu opens.
///
protected void UpdateActions()
{
ActionPresentation presentation = new ActionPresentation();
IActionContext context = _contextprovider.GetContext( ActionContextKind.MainMenu );
// Update the actions
foreach( ToolStripMenuItem mi in _hashMenuActions.Keys )
{
presentation.Reset();
IAction action = (IAction)_hashMenuActions[ mi ];
action.Update( context, ref presentation );
mi.Visible = presentation.Visible;
mi.Enabled = presentation.Enabled;
if( presentation.Text != null )
mi.Text = presentation.Text;
}
// Now for each of the top-level menus hide the double-separators
foreach( ToolStripMenuItem miTopLevel in _miTopLevel )
{
bool bPrevSep = true; // Allows to hide to conscequent separators that might appear if all the items between them get hidden; setting it initially to True avoids showing a separator at the first position in the menu
ToolStripItem miLastVisible = null; // The last item that is visible (check for a sep)
foreach( ToolStripItem mi in miTopLevel.DropDownItems )
{
if( mi is ToolStripSeparator )
{
if( bPrevSep ) // Two or more separators in a row, suppress the second one
mi.Visible = false;
else
{ // This is a first separator after a normal item, show it (if it's not the first visible item in the menu)
mi.Visible = bPrevSep = true;
miLastVisible = mi;
}
}
else
{ // A normal item
if( mi.Visible )
{
bPrevSep = false;
miLastVisible = mi;
}
}
}
// Don't allow a separator to be the last visible item in the menu
if( ( miLastVisible != null ) && ( miLastVisible is ToolStripSeparator ) )
miLastVisible.Visible = false;
}
}
private void OnMenuItemClicked( object sender, EventArgs e )
{
ToolStripMenuItem miSender = (ToolStripMenuItem)sender;
((IAction)_hashMenuActions[ miSender ]).Execute( _contextprovider.GetContext( ActionContextKind.MainMenu ) );
}
private void OnTopLevelMenuItemPopup(object sender, EventArgs e)
{
UpdateActions();
}
}
#endregion
#region EncodingMenuItem Class — MenuItems that have a charset associated to them.
internal class EncodingMenuItem : ToolStripMenuItem
{
///
/// The charset this item serves.
///
protected CharsetsEnum.Charset _charset;
internal EncodingMenuItem( CharsetsEnum.Charset charset )
: base( charset.Description ) // Send UI text to the menu item base
{
Guard.NullArgument( charset, "charset" );
_charset = charset;
// RadioCheck = true;
CheckOnClick = true;
}
///
/// Gets the charset this item serves.
///
internal CharsetsEnum.Charset Charset
{
get { return _charset; }
}
}
#endregion
}
}