/// /// 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.Diagnostics; using System.Drawing; using System.Windows.Forms; using JetBrains.Omea.Base; using JetBrains.Omea.GUIControls; using JetBrains.Omea.OpenAPI; using JetBrains.UI.Components.ImageListButton; namespace JetBrains.Omea { /** * Balloon notification form. */ internal class BalloonForm : Form { private double _safeOpacity = 0.0; private const int DefaultVisibilityInterval = 4; private Panel _contentPane; private Label _lblFrom, _lblSubject; private JetLinkLabel _lblBody; private ImageListPictureBox _resourceIconBox; private ImageListButton _btnDelete, _btnClose; private readonly ImageList _delImageList; private readonly ImageList _closeImageList; private ToolTip _toolTipReason; private Timer _fadeInTimer, _fadeOutTimer; private Timer _visibleTimer; private Timer _balloonLeaveTimer; private EventHandler _clickHandler; private System.ComponentModel.IContainer components; private IResource _lastResource; private IResourceList _lastResourceList; private int _visibilityInterval; public BalloonForm() { _delImageList = new ImageList(); _closeImageList = new ImageList(); _delImageList.ColorDepth = Core.ResourceIconManager.IconColorDepth; _delImageList.Images.Add( Utils.TryGetEmbeddedResourceIconFromAssembly( "OmniaMea", "OmniaMea.Icons.delete.ico" ) ); _delImageList.Images.Add( Utils.TryGetEmbeddedResourceIconFromAssembly( "OmniaMea", "OmniaMea.Icons.delete_hover.ico" ) ); _delImageList.Images.Add( Utils.TryGetEmbeddedResourceIconFromAssembly( "OmniaMea", "OmniaMea.Icons.delete_pressed.ico" ) ); _closeImageList.Images.Add( Utils.TryGetEmbeddedResourceIconFromAssembly( "OmniaMea", "OmniaMea.Icons.close1.ico" ) ); _closeImageList.Images.Add( Utils.TryGetEmbeddedResourceIconFromAssembly( "OmniaMea", "OmniaMea.Icons.close2.ico" ) ); _closeImageList.Images.Add( Utils.TryGetEmbeddedResourceIconFromAssembly( "OmniaMea", "OmniaMea.Icons.close3.ico" ) ); ReadVisibilityTimer(); InitializeComponent(); } /// /// Clean up any resources being used. /// protected override void Dispose( bool disposing ) { if( disposing ) { if(components != null) { components.Dispose(); } } base.Dispose( disposing ); } #region Windows Form Designer generated code /// /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// private void InitializeComponent() { this.components = new System.ComponentModel.Container(); this._contentPane = new System.Windows.Forms.Panel(); this._lblBody = new JetBrains.Omea.GUIControls.JetLinkLabel(); this._resourceIconBox = new JetBrains.Omea.GUIControls.ImageListPictureBox(); this._lblSubject = new System.Windows.Forms.Label(); this._lblFrom = new System.Windows.Forms.Label(); _btnDelete = new ImageListButton(); _btnClose = new ImageListButton(); this._fadeInTimer = new System.Windows.Forms.Timer(this.components); this._visibleTimer = new System.Windows.Forms.Timer(this.components); this._fadeOutTimer = new System.Windows.Forms.Timer(this.components); this._balloonLeaveTimer = new System.Windows.Forms.Timer(this.components); _toolTipReason = new ToolTip( components ); _toolTipReason.ShowAlways = true; this._contentPane.SuspendLayout(); this.SuspendLayout(); // // _contentPane // this._contentPane.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this._contentPane.BackColor = System.Drawing.Color.FromArgb(((System.Byte)(192)), ((System.Byte)(192)), ((System.Byte)(255))); this._contentPane.Controls.Add(_btnClose); this._contentPane.Controls.Add(this._lblBody); this._contentPane.Controls.Add(this._resourceIconBox); this._contentPane.Controls.Add(this._btnDelete); this._contentPane.Controls.Add(this._lblSubject); this._contentPane.Controls.Add(this._lblFrom); this._contentPane.Location = new System.Drawing.Point(2, 2); this._contentPane.Name = "_contentPane"; this._contentPane.Size = new System.Drawing.Size(296, 68); this._contentPane.TabIndex = 0; // // _lblBody // this._lblBody.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this._lblBody.AutoSize = false; this._lblBody.Cursor = System.Windows.Forms.Cursors.Hand; this._lblBody.Font = new System.Drawing.Font("Tahoma", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(204))); this._lblBody.ForeColor = System.Drawing.Color.Blue; this._lblBody.Location = new System.Drawing.Point(28, 36); this._lblBody.Name = "_lblBody"; this._lblBody.Size = new System.Drawing.Size(264, 28); this._lblBody.TabIndex = 3; this._lblBody.WordWrap = true; this._lblBody.Click += new System.EventHandler(this._lblBody_Click); this._lblBody.MouseEnter += new System.EventHandler(this.OnBalloonMouseEnter); this._lblBody.MouseLeave += new System.EventHandler(this.OnBalloonMouseLeave); // // _resourceIconBox // this._resourceIconBox.ImageIndex = 0; this._resourceIconBox.ImageLeftTopPoint = new System.Drawing.Point(0, 0); this._resourceIconBox.Location = new System.Drawing.Point(8, 2); this._resourceIconBox.Name = "_resourceIconBox"; this._resourceIconBox.Size = new System.Drawing.Size(16, 16); this._resourceIconBox.TabIndex = 2; this._resourceIconBox.TabStop = false; this._resourceIconBox.MouseEnter += new System.EventHandler(this.OnBalloonMouseEnter); this._resourceIconBox.MouseLeave += new System.EventHandler(this.OnBalloonMouseLeave); // // _btnDelete // this._btnDelete.Anchor = (AnchorStyles.Top | AnchorStyles.Right); this._btnDelete.Name = "_btnDelete"; this._btnDelete.Size = new System.Drawing.Size(16, 16); this._btnDelete.Location = new System.Drawing.Point(8, 20); this._btnDelete.TabIndex = 3; this._btnDelete.Click += new EventHandler(_btnDelete_Click); this._btnDelete.NormalImageIndex = 0; this._btnDelete.HotImageIndex = 1; this._btnDelete.PressedImageIndex = 2; this._btnDelete.ImageList = _delImageList; this._btnDelete.MouseEnter += new System.EventHandler(this.OnBalloonMouseEnter); this._btnDelete.MouseLeave += new System.EventHandler(this.OnBalloonMouseLeave); // // _btnClose // this._btnClose.Name = "_btnClose"; this._btnClose.Size = new System.Drawing.Size(16, 16); this._btnClose.Location = new System.Drawing.Point(280, 2); this._btnClose.TabIndex = 3; this._btnClose.NormalImageIndex = 0; this._btnClose.HotImageIndex = 1; this._btnClose.PressedImageIndex = 2; this._btnClose.ImageList = _closeImageList; this._btnClose.MouseEnter += new System.EventHandler(this.OnBalloonMouseEnter); this._btnClose.MouseLeave += new System.EventHandler(this.OnBalloonMouseLeave); this._btnClose.Click += new EventHandler(_btnClose_Click); // // _lblSubject // this._lblSubject.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this._lblSubject.FlatStyle = System.Windows.Forms.FlatStyle.System; this._lblSubject.Font = new System.Drawing.Font("Tahoma", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(204))); this._lblSubject.Location = new System.Drawing.Point(28, 20); this._lblSubject.Name = "_lblSubject"; this._lblSubject.Size = new System.Drawing.Size(264, 14); this._lblSubject.TabIndex = 1; this._lblSubject.Text = ""; this._lblSubject.UseMnemonic = false; this._lblSubject.MouseEnter += new System.EventHandler(this.OnBalloonMouseEnter); this._lblSubject.MouseLeave += new System.EventHandler(this.OnBalloonMouseLeave); // // _lblFrom // this._lblFrom.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this._lblFrom.FlatStyle = System.Windows.Forms.FlatStyle.System; this._lblFrom.Font = new System.Drawing.Font("Tahoma", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((System.Byte)(204))); this._lblFrom.Location = new System.Drawing.Point(28, 4); this._lblFrom.Name = "_lblFrom"; this._lblFrom.Size = new System.Drawing.Size(264, 16); this._lblFrom.TabIndex = 0; this._lblFrom.Text = "From:"; this._lblFrom.UseMnemonic = false; this._lblFrom.MouseEnter += new System.EventHandler(this.OnBalloonMouseEnter); this._lblFrom.MouseLeave += new System.EventHandler(this.OnBalloonMouseLeave); // // _fadeInTimer // this._fadeInTimer.Interval = 100; this._fadeInTimer.Tick += new System.EventHandler(this._fadeInTimer_Tick); // // _visibleTimer // this._visibleTimer.Interval = _visibilityInterval; this._visibleTimer.Tick += new System.EventHandler(this._visibleTimer_Tick); // // _fadeOutTimer // this._fadeOutTimer.Interval = 100; this._fadeOutTimer.Tick += new System.EventHandler(this._fadeOutTimer_Tick); // // _balloonLeaveTimer // this._balloonLeaveTimer.Interval = 150; this._balloonLeaveTimer.Tick += new System.EventHandler(this._balloonLeaveTimer_Tick); // // BalloonForm // this.AutoScaleBaseSize = new System.Drawing.Size(5, 13); this.BackColor = System.Drawing.SystemColors.ControlDarkDark; this.ClientSize = new System.Drawing.Size(300, 72); this.Controls.Add(this._contentPane); this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; this.Name = "BalloonForm"; this.Opacity = 0; this.ShowInTaskbar = false; this.StartPosition = System.Windows.Forms.FormStartPosition.Manual; this.Text = "BalloonForm"; this.TopMost = true; this._contentPane.ResumeLayout(false); this.ResumeLayout(false); } #endregion internal double SafeOpacity { get { return _safeOpacity; } set { _safeOpacity = value; try { Opacity = value; } catch( Exception ex ) { Trace.WriteLine( "Error setting BalloonForm opacity:" + ex ); } } } internal void ShowResource( IResource res ) { SetLastResource( res ); ReadBackColor(); DisplayResourceAlertData( res ); StartVisibilityTimer(); } internal void ShowAlert( ImageList imageList, int imageIndex, string from, string subject, string body, EventHandler clickHandler ) { SetLastResource( null ); ReadBackColor(); DisplayAlertData( imageList, imageIndex, from, subject, body, clickHandler ); StartVisibilityTimer(); } private void DisplayResourceAlertData( IResource res ) { string subject; string from = res.GetPropText( Core.ContactManager.Props.LinkFrom ); if ( res.HasProp( Core.Props.Subject ) ) { subject = res.GetPropText( Core.Props.Subject ); } else { if ( from.Length == 0 ) { from = res.DisplayName; } subject = ""; } DisplayAlertData( Core.ResourceIconManager.ImageList, Core.ResourceIconManager.GetIconIndex( res ), from, subject, Core.MessageFormatter.GetPreviewText( res, 2 ), HandleResourceClick ); } private void DisplayAlertData( ImageList imageList, int imageIndex, string from, string subject, string body, EventHandler clickHandler ) { _resourceIconBox.ImageList = imageList; _resourceIconBox.ImageIndex = imageIndex; _lblFrom.Text = "From: " + from; _lblSubject.Text = subject; _lblBody.Text = !String.IsNullOrEmpty( body ) ? body : ""; _clickHandler = clickHandler; _lblBody.ClickableLink = (clickHandler != null); // Show the tooltip only if the actual text does not fit // into the control. int filled, linesFilled; Graphics grph = Graphics.FromHwnd( _lblSubject.Handle ); grph.MeasureString( subject, _lblSubject.Font, new SizeF( _lblSubject.Width, 16.0f ), new StringFormat(), out filled, out linesFilled ); _toolTipReason.SetToolTip( _lblSubject, (filled < subject.Length) ? subject : null ); } private void SetLastResource( IResource res ) { if ( _lastResourceList != null ) { _lastResourceList.ResourceDeleting -= HandleResourceDeleted; _lastResourceList.ResourceChanged -= HandleResourceChanged; _lastResourceList.Dispose(); _lastResourceList = null; } _lastResource = res; if ( _lastResource != null ) { _lastResourceList = _lastResource.ToResourceListLive(); _lastResourceList.ResourceDeleting += HandleResourceDeleted; _lastResourceList.ResourceChanged += HandleResourceChanged; } } private void HandleResourceDeleted( object sender, ResourceIndexEventArgs e ) { Core.UIManager.QueueUIJob( new MethodInvoker( HideBalloon ) ); } private void HandleResourceChanged( object sender, ResourcePropIndexEventArgs e ) { Core.UIManager.QueueUIJob( new MethodInvoker( UpdateLastResource ) ); } private void UpdateLastResource() { if ( _lastResource != null ) { DisplayResourceAlertData( _lastResource ); } } internal void SetDefaultLocation() { Rectangle rect = Screen.PrimaryScreen.Bounds; rect = Screen.GetWorkingArea( rect ); Left = rect.Right - Width; Top = rect.Bottom - Height; } private void StartVisibilityTimer() { ReadVisibilityTimer(); if ( SafeOpacity < 0.1 ) { _fadeInTimer.Start(); } else if ( _visibleTimer.Enabled ) { _visibleTimer.Stop(); _visibleTimer.Start(); } } private void _fadeInTimer_Tick( object sender, EventArgs e ) { SafeOpacity = Opacity + 0.2; if ( SafeOpacity >= 0.99 ) { _fadeInTimer.Stop(); _visibleTimer.Start(); } } private void _visibleTimer_Tick( object sender, EventArgs e ) { _visibleTimer.Stop(); _fadeOutTimer.Start(); } private void _fadeOutTimer_Tick( object sender, EventArgs e ) { if ( SafeOpacity < 0.1 ) { HideBalloon(); } else { SafeOpacity = SafeOpacity - 0.2; } } private void HideBalloon() { Visible = false; SafeOpacity = 0; SetLastResource( null ); StopAllTimers(); } private void _lblBody_Click( object sender, EventArgs e ) { if ( _clickHandler != null ) { _clickHandler( sender, e ); } } private void HandleResourceClick( object sender, EventArgs e ) { if ( _lastResource != null ) { Core.UIManager.RestoreMainWindow(); Core.UIManager.DisplayResourceInContext( _lastResource, true ); } } private void OnBalloonMouseEnter( object sender, EventArgs e ) { StopAllTimers(); SafeOpacity = 1.0; } private void StopAllTimers() { _visibleTimer.Stop(); _fadeInTimer.Stop(); _fadeOutTimer.Stop(); _balloonLeaveTimer.Stop(); } private void OnBalloonMouseLeave( object sender, EventArgs e ) { _balloonLeaveTimer.Start(); } private void _balloonLeaveTimer_Tick( object sender, EventArgs e ) { _balloonLeaveTimer.Stop(); _fadeOutTimer.Start(); } private void ReadVisibilityTimer() { // parameter is set in seconds. _visibilityInterval = Core.SettingStore.ReadInt( "General", "BalloonTimeout", DefaultVisibilityInterval ); _visibilityInterval *= 1000; } private void ReadBackColor() { int r, g, b; r = Core.SettingStore.ReadInt( "General", "BalloonBackgroundR", 192 ); g = Core.SettingStore.ReadInt( "General", "BalloonBackgroundG", 192 ); b = Core.SettingStore.ReadInt( "General", "BalloonBackgroundB", 255 ); try { _contentPane.BackColor = Color.FromArgb(r, g, b); } catch( Exception ) { _contentPane.BackColor = Color.FromArgb(192, 192, 255); } } private void _btnDelete_Click(object sender, EventArgs e) { // OM-12575, releasing mouse button may be with huge (enough) // lag, during which the resource might have been deleted. if( _lastResource != null ) { IResourceDeleter deleter = Core.PluginLoader.GetResourceDeleter( _lastResource.Type ); if( deleter != null ) { Core.ResourceAP.QueueJob( new ResourceDelegate( deleter.DeleteResource ), _lastResource ); Core.UIManager.QueueUIJob( new MethodInvoker( HideBalloon ) ); } } } private void _btnClose_Click(object sender, EventArgs e) { HideBalloon(); } } public class BalloonNotificationAction: IRuleAction { private DateTime _lastNotificationTime = DateTime.MinValue; public void Exec( IResource res, IActionParameterStore actionStore ) { if ( Core.State != CoreState.ShuttingDown ) { TimeSpan ts = DateTime.Now - _lastNotificationTime; if ( ts.TotalMilliseconds > 500 ) { Core.UIManager.QueueUIJob( new ResourceDelegate( Core.UIManager.ShowDesktopAlert ), res ); _lastNotificationTime = DateTime.Now; } } } } }