///
/// 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.Drawing;
using System.Diagnostics;
using System.Windows.Forms;
using JetBrains.Omea.GUIControls;
using JetBrains.Omea.OpenAPI;
namespace JetBrains.Omea
{
///
/// Summary description for AnnotationForm.
///
public class AnnotationForm : Form
{
private const double cDefaultOpacity = 0.75;
private RichTextBox richText;
private ISettingStore Settings;
private IResource _resource;
private IResourceList _ResourceChangeWatcher;
private bool IsPersistentMode = false;
private bool IsModified;
private double SavedOpacity = cDefaultOpacity;
private string SourceText;
private bool _defaultPosition;
private bool _disposing;
///
/// Required designer variable.
///
private System.ComponentModel.Container components = null;
public AnnotationForm()
{
Settings = Core.SettingStore;
InitializeComponent();
//-----------------------------------------------------------------
int xPos = Settings.ReadInt( "Annotations", "LocationX", -1 ),
yPos = Settings.ReadInt( "Annotations", "LocationY", -1 );
int width = Settings.ReadInt( "Annotations", "Width", -1 ),
height = Settings.ReadInt( "Annotations", "Height", -1 );
if( xPos != -1 && yPos != -1 )
{
Location = new Point( xPos, yPos );
_defaultPosition = false;
}
else
{
_defaultPosition = true;
}
if( width != -1 && height != -1 )
this.Size = new Size( width, height );
if( IsOutsideScreen( Location ))
this.Location = new Point( Screen.PrimaryScreen.WorkingArea.Right / 2,
Screen.PrimaryScreen.WorkingArea.Bottom / 2 );
//-----------------------------------------------------------------
int opacity = Settings.ReadInt( "Annotations", "Opacity", -1 );
if( opacity != -1 )
{
SavedOpacity = Opacity;
try
{
Opacity = ((double)opacity) / 100.0;
}
catch( Exception )
{
// ignore
}
}
string color = Settings.ReadString( "Annotations", "BackColor" );
if( !String.IsNullOrEmpty( color ) )
{
if( IsValidColor( color ) )
richText.BackColor = Color.FromName( color );
else
{
MessageBox.Show( this, "Color name for the Annotation background is illegal", "Illegal Color Name", MessageBoxButtons.OK, MessageBoxIcon.Error );
Settings.WriteString( "Annotations", "BackColor", "Info" );
}
}
color = Settings.ReadString( "Annotations", "ForeColor" );
if( !String.IsNullOrEmpty( color ) )
{
if( IsValidColor( color ) )
richText.ForeColor = Color.FromName( color );
else
{
MessageBox.Show( this, "Color name for the Annotation foreground is illegal", "Illegal Color Name", MessageBoxButtons.OK, MessageBoxIcon.Error );
Settings.WriteString( "Annotations", "ForeColor", "Black" );
}
}
Hide();
}
public void ShowAnnotation( IResource res, bool isPersistentMode )
{
ShowAnnotation( res, isPersistentMode, false );
}
public void ShowAnnotation( IResource res, bool isPersistentMode, bool focus )
{
_resource = res;
IsPersistentMode = isPersistentMode;
SourceText = res.GetPropText( Core.Props.Annotation );
// [Clear and] Set a watcher on the annotation text which
// can be changed outside the Omea.
if( _ResourceChangeWatcher != null )
{
_ResourceChangeWatcher.ResourceChanged -= _ResourceChangeWatcher_ResourceChanged;
_ResourceChangeWatcher.Dispose();
}
_ResourceChangeWatcher = _resource.ToResourceListLive();
_ResourceChangeWatcher.AddPropertyWatch( Core.Props.Annotation );
_ResourceChangeWatcher.ResourceChanged += _ResourceChangeWatcher_ResourceChanged;
WriteText( SourceText );
if ( _defaultPosition )
{
Bounds = GetDefaultPosition();
_defaultPosition = false;
}
Show();
if( !focus )
Core.ResourceBrowser.FocusResourceList();
else
Focus();
}
private static Rectangle GetDefaultPosition()
{
Rectangle rc = (Core.ResourceBrowser as ResourceBrowser).DisplayPanePosition;
return new Rectangle( rc.Right - 310, rc.Bottom - 110, 300, 100 );
}
public string AnnotationText
{
get{ return( richText.Text ); }
}
///
/// Clean up any resources being used.
///
protected override void Dispose( bool disposing )
{
_disposing = true;
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.richText = new System.Windows.Forms.RichTextBox();
this.SuspendLayout();
//
// richText
//
this.richText.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.richText.BackColor = System.Drawing.SystemColors.Info;
this.richText.Font = new System.Drawing.Font("Tahoma", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(204)));
this.richText.Location = new System.Drawing.Point(0, 0);
this.richText.Name = "richText";
this.richText.ScrollBars = System.Windows.Forms.RichTextBoxScrollBars.Vertical;
this.richText.Size = new System.Drawing.Size(440, 224);
this.richText.TabIndex = 1;
this.richText.Text = "";
this.richText.LinkClicked += new System.Windows.Forms.LinkClickedEventHandler(this.richText_LinkClicked);
//
// AnnotationForm
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(440, 224);
this.Controls.Add(this.richText);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.SizableToolWindow;
this.KeyPreview = true;
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "AnnotationForm";
this.Opacity = 0.9;
this.ShowInTaskbar = false;
this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
this.Text = "Edit Annotation";
this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.OnKeyPressed);
this.Resize += new System.EventHandler(this.AnnotationForm_Resize);
this.Closing += new System.ComponentModel.CancelEventHandler(this.OnToBeClosed);
this.Move += new System.EventHandler(this.AnnotationForm_Move);
this.ResumeLayout(false);
}
#endregion
private void OnKeyPressed(object sender, KeyEventArgs e)
{
if(( e.KeyCode == Keys.Enter && e.Control ) || ( e.KeyCode == Keys.Escape && !e.Control ))
{
e.Handled = true;
/*
if( e.KeyCode == Keys.Enter && AnnotationText.Length > 0 )
SaveAnnotation( AnnotationText, Res );
else
if(( e.KeyCode == Keys.Enter && AnnotationText.Length == 0 ) ||
( e.KeyCode == Keys.Escape && SourceText.Length == 0 ))
DeleteAnnotation( Res );
if( e.KeyCode == Keys.Escape && SourceText.Length > 0 )
WriteText( SourceText );
*/
if ( AnnotationText.Length > 0 )
{
SaveAnnotation( AnnotationText, _resource );
if( IsPersistentMode )
{
if( Core.ResourceBrowser.ResourceListVisible )
Core.ResourceBrowser.FocusResourceList();
else
this.OnDeactivate( null );
}
else
Hide();
}
else
{
DeleteAnnotation( _resource );
Hide();
}
}
else if ( !JetTextBox.IsEditorKey( e.KeyData ) )
{
Core.ActionManager.ExecuteKeyboardAction( null, e.KeyCode | e.Modifiers );
IsModified = true;
}
}
protected override void OnActivated( EventArgs e )
{
base.OnGotFocus( e );
if ( Core.State == CoreState.ShuttingDown )
{
return;
}
SavedOpacity = Opacity;
// Crazy workaround - smtimes Win32Exception is raised that 1.0 is
// not a valid argument for a Opacity setter.
try
{
Opacity = 1.0;
}
catch( Exception )
{
// ignore
}
Text = CaptionText();
}
protected override void OnDeactivate( System.EventArgs e )
{
if ( !_disposing )
{
if( AnnotationText.Length > 0 )
SaveAnnotation( AnnotationText, _resource );
else
DeleteAnnotation( _resource );
}
base.OnLostFocus( e );
try
{
Opacity = SavedOpacity;
}
catch( Exception )
{
// ignore
}
Text = CaptionText();
}
private void AnnotationForm_Move(object sender, System.EventArgs e)
{
SaveConfiguration();
}
private void AnnotationForm_Resize(object sender, System.EventArgs e)
{
SaveConfiguration();
}
private void OnToBeClosed(object sender, System.ComponentModel.CancelEventArgs e)
{
if( AnnotationText.Length > 0 )
SaveAnnotation( AnnotationText, _resource );
else
DeleteAnnotation( _resource );
}
//---------------------------------------------------------------------
// Aux methods
//---------------------------------------------------------------------
private void WriteText( string text )
{
Debug.Assert( text != null );
if( text.Length > 0 )
{
string[] lines = text.Split( '\n' );
richText.Lines = lines;
}
else
richText.Clear();
}
private delegate void SaveAnnotationDelegate( IResource res, string text );
private void SaveAnnotation( string ann, IResource res )
{
if( IsModified )
{
Core.ResourceAP.QueueJob( JobPriority.Immediate, new SaveAnnotationDelegate( DoSaveAnnotation ),
res, ann );
IsModified = false;
}
}
private static void DeleteAnnotation( IResource res )
{
Core.ResourceAP.QueueJob( JobPriority.Immediate, new SaveAnnotationDelegate( DoSaveAnnotation ), res, null );
}
private static void DoSaveAnnotation( IResource res, string annotation )
{
if ( res.IsDeleted )
return;
if ( annotation != null )
{
res.SetProp( Core.Props.Annotation, annotation );
res.SetProp( "AnnotationLastModifiedDate", DateTime.Now );
}
else
{
res.DeleteProp( Core.Props.Annotation );
}
if ( res.IsTransient )
{
res.EndUpdate();
}
// finally call environment to reindex the resource so that the
// text index reflect the changes in annotation text.
Core.TextIndexManager.QueryIndexing( res.Id );
}
private void SaveConfiguration()
{
Settings.WriteInt( "Annotations", "LocationX", Location.X );
Settings.WriteInt( "Annotations", "LocationY", Location.Y );
Settings.WriteInt( "Annotations", "Width", Size.Width );
Settings.WriteInt( "Annotations", "Height", Size.Height );
}
private string CaptionText()
{
string text = "Edit Annotation";
if( _resource != null )
{
text += ": " + _resource.DisplayName;
if( _resource.HasProp( "AnnotationLastModifiedDate" ))
text += " | Last touched at " + _resource.GetDateProp( "AnnotationLastModifiedDate" ).ToShortDateString();
}
return text;
}
private static bool IsOutsideScreen( Point location )
{
Rectangle rect = Screen.PrimaryScreen.WorkingArea;
return( location.X > rect.Right || location.Y > rect.Bottom );
}
// If name does not belong to the KnownColor enumeration,
// FromName return a structure with all ARGB components equal to 0.
private static bool IsValidColor( string name )
{
Color color = Color.FromName( name );
return (color.A != 0) || (color.R != 0) || (color.G != 0) || (color.B != 0);
}
private void richText_LinkClicked( object sender, LinkClickedEventArgs e )
{
Core.UIManager.OpenInNewBrowserWindow(e.LinkText);
}
private void _ResourceChangeWatcher_ResourceChanged( object sender, ResourcePropIndexEventArgs e )
{
Core.UIManager.QueueUIJob( new MethodInvoker( UpdateAnnotation ) );
}
private void UpdateAnnotation()
{
if ( !IsDisposed && _resource != null && !_resource.IsDeleted )
{
SourceText = _resource.GetPropText( Core.Props.Annotation );
WriteText( SourceText );
}
}
protected override void OnClosed(EventArgs e)
{
base.OnClosed (e);
if( _ResourceChangeWatcher != null )
{
_ResourceChangeWatcher.ResourceChanged -= _ResourceChangeWatcher_ResourceChanged;
_ResourceChangeWatcher.Dispose();
}
}
}
}