/// /// 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.Windows.Forms; using JetBrains.Omea.OpenAPI; using JetBrains.Omea.GUIControls; using JetBrains.JetListViewLibrary; using JetBrains.UI.Interop; using JetBrains.UI.RichText; namespace JetBrains.Omea.Tasks { internal class TasksViewPane : AbstractViewPane { #region Attributes private TextBox _editNewTask; private DecoResourceTreeView _tasksTree; internal static ToDoGenericFilter _todoFilter = new ToDoGenericFilter(); internal delegate void AddTargetsDelegate( IResource task, IResourceList targets, int link ); #endregion Attributes public TasksViewPane() { InitializeComponent(); _tasksTree.OpenProperty = Core.Props.Open; _tasksTree.AddNodeDecorator( new TasksNodeDecorator() ); Core.WorkspaceManager.WorkspaceChanged += OnActiveWorkspaceChanged; } protected override void Dispose(bool disposing) { base.Dispose (disposing); if( disposing ) { _tasksTree = null; } } #region Initialize Components private void InitializeComponent() { _tasksTree = new DecoResourceTreeView(); _editNewTask = new TextBox(); SuspendLayout(); // // _tasksTreeView2 // _tasksTree.AllowDrop = true; _tasksTree.Anchor = (AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right); _tasksTree.BackColor = SystemColors.Window; _tasksTree.BorderStyle = BorderStyle.None; _tasksTree.ExecuteDoubleClickAction = true; _tasksTree.HideSelection = false; _tasksTree.Location = new Point(0, 20); _tasksTree.MultiSelect = true; _tasksTree.Name = "_tasksTree"; _tasksTree.SelectAddedItems = true; _tasksTree.Size = new Size(336, 163); _tasksTree.TabIndex = 0; _tasksTree.DoubleClick += _tasksTreeView2_DoubleClick; _tasksTree.KeyDown += _tasksTreeView_KeyDown; _tasksTree.AfterItemEdit += _tasksTreeView_AfterLabelEdit; _tasksTree.BeforeItemEdit += _tasksTreeView_BeforeLabelEdit; // // _newTaskEditBox // _editNewTask.AllowDrop = true; _editNewTask.Anchor = (AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right); _editNewTask.ForeColor = Color.Gray; _editNewTask.Location = new Point(0, 0); _editNewTask.Name = "_editNewTask"; _editNewTask.Size = new Size(336, 21); _editNewTask.TabIndex = 1; _editNewTask.Text = "Click here to add a new Task"; _editNewTask.KeyPress += _newTaskEditBox_KeyPress; _editNewTask.DragOver += _newTaskEditBox_DragOver; _editNewTask.DragDrop += _newTaskEditBox_DragDrop; _editNewTask.Leave += _newTaskEditBox_Leave; _editNewTask.Enter += _newTaskEditBox_Enter; // // TasksViewPane // Controls.Add(_editNewTask); Controls.Add(_tasksTree); Font = new Font("Tahoma", 8.25F, FontStyle.Regular, GraphicsUnit.Point, 204); Name = "TasksViewPane"; Size = new Size(336, 184); ResumeLayout(false); } #endregion Initialize Components public override void Populate() { _tasksTree.RootResource = TasksPlugin.RootTask; _tasksTree.ParentProperty = TasksPlugin._linkSuperTask; ShowCompletedTaks = Core.SettingStore.ReadBool( "Tasks", "ShowCompletedTasks", true ); _tasksTree.AddNodeFilter( _todoFilter ); _tasksTree.UpdateNodeFilter( true ); } public bool ShowCompletedTaks { set { _todoFilter.showCompletedTasks = value; _tasksTree.UpdateNodeFilter( true ); } } private void OnActiveWorkspaceChanged( object sender, EventArgs e ) { if( Core.UserInterfaceAP.IsOwnerThread ) { _tasksTree.UpdateNodeFilter( true ); } else { Core.UserInterfaceAP.QueueJob( new EventHandler( OnActiveWorkspaceChanged ), sender, e ); } } private void OpenAction() { IResource selected = null; IResourceList selList = _tasksTree.GetSelectedResources(); if( selList.Count == 1 ) selected = selList[ 0 ]; if( selected != null ) { if( selected.Type != "Task" ) { Core.UIManager.DisplayResourceInContext( selected ); } else { OpenTaskAction.OpenTask( selected ); } } } #region EditBox events internal delegate void StringDelegate( string name ); internal delegate void ResStringDelegate( IResource res, string name ); private void _newTaskEditBox_Enter(object sender, EventArgs e) { _editNewTask.Text = string.Empty; _editNewTask.ForeColor = Color.Black; } private void _newTaskEditBox_Leave(object sender, EventArgs e) { if( _editNewTask.Text.Length > 0 ) { Core.ResourceAP.RunUniqueJob( new StringDelegate( CreateNewTaskInline ), _editNewTask.Text ); } _editNewTask.Text = "Click here to add a new Task"; _editNewTask.ForeColor = Color.Gray; } private void _newTaskEditBox_KeyPress(object sender, KeyPressEventArgs e) { if( e.KeyChar == '\r' ) { e.Handled = true; _tasksTree.Focus(); } } private void _tasksTreeView2_DoubleClick(object sender, HandledEventArgs e) { OpenAction(); } #endregion EditBox events #region Drag'n'Drop in EditBox private static void _newTaskEditBox_DragOver(object sender, DragEventArgs e) { IResourceList targets = (IResourceList) e.Data.GetData( typeof( IResourceList ) ); if( targets != null && targets.Count > 0 ) { e.Effect = DragDropEffects.Link; } } private static void _newTaskEditBox_DragDrop(object sender, DragEventArgs e) { IResourceList targets = (IResourceList) e.Data.GetData( typeof( IResourceList ) ); if( targets != null && targets.Count > 0 ) { System.Diagnostics.Trace.WriteLine( "Task from drop on edit, targets count = " + targets.Count ); new NewTaskAction().Execute( new ActionContext( targets ) ); } } #endregion Drag'n'Drop in EditBox #region ResourceTreeView Label Editing private static void _tasksTreeView_BeforeLabelEdit( object sender, ResourceItemEditEventArgs e ) { e.CancelEdit = ( e.Resource == null || e.Resource.Type != "Task" ); } private static void _tasksTreeView_AfterLabelEdit( object sender, ResourceItemEditEventArgs e ) { IResource task = e.Resource; if( task == null || task.Type != "Task" || e.Text == null || e.Text.Length == 0 ) { e.CancelEdit = true; } else { ResourceProxy proxy = new ResourceProxy( task ); proxy.SetProp( Core.Props.Subject, e.Text ); } } #endregion ResourceTreeView Label Editing #region Keyboard processing private void _tasksTreeView_KeyDown(object sender, KeyEventArgs e) { IResourceList selection = _tasksTree.GetSelectedResources(); if( !e.Alt && !e.Control && !e.Shift ) { if( e.KeyCode == Keys.Enter && selection.Count == 1 ) { e.Handled = true; OpenAction(); } else if( e.KeyCode == Keys.Delete ) { foreach( IResource node in selection ) { if( node.Type == "Task" ) { return; } } e.Handled = true; new DeAttachResourcesFromTaskInPane().Execute( new ActionContext( ActionContextKind.Other, this, null ) ); } else if( e.KeyCode == Keys.Insert && ( selection.Count == 1 )) { Core.ResourceAP.RunUniqueJob( new StringDelegate( CreateNewTaskInline ), string.Empty ); e.Handled = true; } } else if( e.Shift && ( e.KeyCode == Keys.Insert ) && ( selection.Count == 1 )) { Core.ResourceAP.RunUniqueJob( new ResStringDelegate( CreateNewTaskInList ), selection[ 0 ], string.Empty ); e.Handled = true; } } private void CreateNewTaskInline( string name ) { CreateNewTaskInList( null, name ); } private void CreateNewTaskInList( IResource parent, string name ) { IResource task = NewTaskAction.CreateTask( null, null ); if( task != null ) { task.EndUpdate(); if( parent != null ) { task.SetProp( TasksPlugin._linkSuperTask, parent ); } if( String.IsNullOrEmpty( name )) { Core.UserInterfaceAP.QueueJob( new ResourceDelegate( _tasksTree.EditResourceLabel ), task ); } else { task.SetProp( Core.Props.Subject, name ); } } } #endregion Keyboard processing #region Decorator private class TasksNodeDecorator : IResourceNodeDecorator { public event ResourceEventHandler DecorationChanged; public bool DecorateNode( IResource res, RichText nodeText ) { if( res.Type == "Task" ) { DateTime dueDate = res.GetDateProp( Core.Props.Date ); if( res.GetIntProp( TasksPlugin._propStatus ) == 2 ) { nodeText.SetColors( Color.Gray, SystemColors.Window ); nodeText.SetStyle( FontStyle.Strikeout, 0, nodeText.Text.Length ); } else if( dueDate > DateTime.MinValue && dueDate < DateTime.Now ) { nodeText.SetColors( Color.Red, SystemColors.Window ); nodeText.SetStyle( FontStyle.Bold, 0, nodeText.Text.Length ); } else if( dueDate.Date == DateTime.Today ) { nodeText.SetColors( Color.Green, SystemColors.Window ); } return true; } return false; } public string DecorationKey { get { return "TaskDueDate"; } } } #endregion Decorator } #region Filters internal class ToDoGenericFilter : IResourceNodeFilter { internal bool showCompletedTasks; public bool AcceptNode( IResource res, int level ) { IResourceList subTasks = res.GetLinksTo( null, TasksPlugin._linkSuperTask ); if( subTasks.Count > 0 ) { // For a supertask, it is shown if at least one of its // subtasks is shown as well. bool accept = false; foreach( IResource subTask in subTasks ) accept = accept || AcceptNode( subTask, level + 1 ); return accept; } else { // Option regulates whether we show completed tasks. int taskStatus = res.GetIntProp( TasksPlugin._propStatus ); if( res.HasProp( Core.Props.IsDeleted ) || ( !showCompletedTasks && taskStatus == (int)TaskStatuses.Completed )) { return false; } // By default we do not show tasks which start date is defined // and will become later. DateTime startDate = res.GetDateProp( TasksPlugin._propStartDate ); if( startDate != DateTime.MinValue && startDate.Date > DateTime.Now.Date ) { return false; } // Accept only those tasks which are defined in the current Wsp. IResource workspace = Core.WorkspaceManager.ActiveWorkspace; return workspace == null || res.HasLink( "InWorkspace", workspace ); } } } #endregion Filters #region Columns /// /// A column in JetListView which supports drawing checkboxes. /// internal class LinkedResourcesColumn : JetListViewColumn { public LinkedResourcesColumn() { Width = 20; FixedSize = true; _showHeader = false; } protected override void DrawItem( Graphics g, Rectangle rc, object item, RowState state, string highlightText ) { IResource res = item as IResource; if ( res != null && res.GetLinksTo( null, TasksPlugin._linkTarget ).Count > 0 ) { int midPointX = rc.Left + Width / 2; int midPointY = (rc.Top + rc.Bottom) / 2; RectangleF rcClip = g.ClipBounds; rcClip.Intersect( new RectangleF( rc.Left, rc.Top, rc.Width, rc.Height ) ); IntPtr hdc = g.GetHdc(); try { IntPtr clipRgn = Win32Declarations.CreateRectRgn( 0, 0, 0, 0 ); if ( Win32Declarations.GetClipRgn( hdc, clipRgn ) != 1 ) { Win32Declarations.DeleteObject( clipRgn ); clipRgn = IntPtr.Zero; } Win32Declarations.IntersectClipRect( hdc, (int) rcClip.Left, (int) rcClip.Top, (int) rcClip.Right, (int) rcClip.Bottom ); int ildState = ( ( state & RowState.ActiveSelected ) != 0 ) ? Win32Declarations.ILD_SELECTED : Win32Declarations.ILD_NORMAL; Win32Declarations.ImageList_Draw( TasksPlugin._ImageList.Handle, 0, hdc, midPointX - 8, midPointY - 8, ildState ); Win32Declarations.SelectClipRgn( hdc, clipRgn ); Win32Declarations.DeleteObject( clipRgn ); } finally { g.ReleaseHdc( hdc ); } } } protected override string GetItemText( object item ) { return ""; } public override string GetToolTip( JetListViewNode node, Rectangle rc, ref bool needPlace ) { return null; } } #endregion Columns }