DocumentStrip.cs :  » GUI » Paint.net » PaintDotNet » C# / CSharp Open Source

Home
C# / CSharp Open Source
1.2.6.4 mono .net core
2.2.6.4 mono core
3.Aspect Oriented Frameworks
4.Bloggers
5.Build Systems
6.Business Application
7.Charting Reporting Tools
8.Chat Servers
9.Code Coverage Tools
10.Content Management Systems CMS
11.CRM ERP
12.Database
13.Development
14.Email
15.Forum
16.Game
17.GIS
18.GUI
19.IDEs
20.Installers Generators
21.Inversion of Control Dependency Injection
22.Issue Tracking
23.Logging Tools
24.Message
25.Mobile
26.Network Clients
27.Network Servers
28.Office
29.PDF
30.Persistence Frameworks
31.Portals
32.Profilers
33.Project Management
34.RSS RDF
35.Rule Engines
36.Script
37.Search Engines
38.Sound Audio
39.Source Control
40.SQL Clients
41.Template Engines
42.Testing
43.UML
44.Web Frameworks
45.Web Service
46.Web Testing
47.Wiki Engines
48.Windows Presentation Foundation
49.Workflows
50.XML Parsers
C# / C Sharp
C# / C Sharp by API
C# / CSharp Tutorial
C# / CSharp Open Source » GUI » Paint.net 
Paint.net » PaintDotNet » DocumentStrip.cs
/////////////////////////////////////////////////////////////////////////////////
// Paint.NET                                                                   //
// Copyright (C) dotPDN LLC, Rick Brewster, Tom Jackson, and contributors.     //
// Portions Copyright (C) Microsoft Corporation. All Rights Reserved.          //
// See src/Resources/Files/License.txt for full licensing and attribution      //
// details.                                                                    //
// .                                                                           //
/////////////////////////////////////////////////////////////////////////////////

using PaintDotNet.SystemLayer;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Windows.Forms;

namespace PaintDotNet{
    internal class DocumentStrip
        : ImageStrip,
          IDocumentList
    {
        private object thumbsLock = new object();

        private List<DocumentWorkspace> documents = new List<DocumentWorkspace>();
        private List<ImageStrip.Item> documentButtons = new List<ImageStrip.Item>();
        private Dictionary<DocumentWorkspace, ImageStrip.Item> dw2button = new Dictionary<DocumentWorkspace, ImageStrip.Item>();
        private Dictionary<DocumentWorkspace, RenderArgs> thumbs = new Dictionary<DocumentWorkspace, RenderArgs>();
        private ThumbnailManager thumbnailManager;
        private DocumentWorkspace selectedDocument = null;
        private bool ensureSelectedIsVisible = true;
        private int suspendThumbnailUpdates = 0;

        public void SuspendThumbnailUpdates()
        {
            ++this.suspendThumbnailUpdates;
        }

        public void ResumeThumbnailUpdates()
        {
            --this.suspendThumbnailUpdates;
        }

        public void SyncThumbnails()
        {
            if (!this.thumbnailManager.IsDisposed)
            {
                using (new WaitCursorChanger(this))
                {
                    this.thumbnailManager.DrainQueue();
                }

                Refresh();
            }
        }

        public int ThumbnailUpdateLatency
        {
            get
            {
                return this.thumbnailManager.UpdateLatency;
            }

            set
            {
                this.thumbnailManager.UpdateLatency = value;
            }
        }

        public bool EnsureSelectedIsVisible
        {
            get
            {
                return this.ensureSelectedIsVisible;
            }

            set
            {
                if (this.ensureSelectedIsVisible != value)
                {
                    this.ensureSelectedIsVisible = value;
                    PerformLayout();
                }
            }
        }

        public DocumentWorkspace[] DocumentList
        {
            get
            {
                return this.documents.ToArray();
            }
        }

        public Image[] DocumentThumbnails
        {
            get
            {
                SyncThumbnails();

                Image[] thumbnails = new Image[this.documents.Count];

                for (int i = 0; i < thumbnails.Length; ++i)
                {
                    DocumentWorkspace dw = this.documents[i];
                    RenderArgs ra;

                    if (!this.thumbs.TryGetValue(dw, out ra))
                    {
                        thumbnails[i] = null;
                    }
                    else
                    {
                        thumbnails[i] = ra.Bitmap;
                    }
                }

                return thumbnails;
            }
        }

        public int DocumentCount
        {
            get
            {
                return this.documents.Count;
            }
        }

        public event EventHandler DocumentListChanged;
        protected virtual void OnDocumentListChanged()
        {
            if (DocumentListChanged != null)
            {
                DocumentListChanged(this, EventArgs.Empty);
            }
        }

        public DocumentWorkspace SelectedDocument
        {
            get
            {
                return this.selectedDocument;
            }

            set
            {
                if (!this.documents.Contains(value))
                {
                    throw new ArgumentException("DocumentWorkspace isn't being tracked by this instance of DocumentStrip");
                }

                if (this.selectedDocument != value)
                {
                    SelectDocumentWorkspace(value);
                    OnDocumentClicked(value, DocumentClickAction.Select);
                    Refresh();
                }
            }
        }

        public int SelectedDocumentIndex
        {
            get
            {
                return this.documents.IndexOf(this.selectedDocument);
            }
        }

        public override Size GetPreferredSize(Size proposedSize)
        {
            Size itemSize = ItemSize;
            int preferredWidth;

            if (this.ItemCount == 0)
            {
                preferredWidth = 0;
            }
            else
            {
                preferredWidth = itemSize.Width * DocumentCount;
            }

            Size preferredSize = new Size(preferredWidth, itemSize.Height);
            return preferredSize;
        }

        private bool OnDigitHotKeyPressed(Keys keys)
        {
            // strip off the Alt and Control stuff
            keys &= ~Keys.Alt;
            keys &= ~Keys.Control;

            if (keys < Keys.D0 || keys > Keys.D9)
            {
                return false;
            }

            int digit = (int)keys - (int)Keys.D0;
            int index;

            if (digit == 0)
            {
                index = 9;
            }
            else
            {
                index = digit - 1;
            }

            if (index < this.documents.Count)
            {
                PerformItemClick(index, ItemPart.Image, MouseButtons.Left);
                return true;
            }
            else
            {
                return false;
            }
        }

        public DocumentStrip()
        {
            PdnBaseForm.RegisterFormHotKey(Keys.Control | Keys.Tab, OnNextTabHotKeyPressed);
            PdnBaseForm.RegisterFormHotKey(Keys.Control | Keys.PageDown, OnNextTabHotKeyPressed);
            PdnBaseForm.RegisterFormHotKey(Keys.Control | Keys.Shift | Keys.Tab, OnPreviousTabHotKeyPressed);
            PdnBaseForm.RegisterFormHotKey(Keys.Control | Keys.PageUp, OnPreviousTabHotKeyPressed);

            thumbnailManager = new ThumbnailManager(this); // allow for a 1px black border

            InitializeComponent();

            for (int i = 0; i <= 9; ++i)
            {
                Keys digit = Utility.LetterOrDigitCharToKeys((char)(i + '0'));
                PdnBaseForm.RegisterFormHotKey(Keys.Control | digit, OnDigitHotKeyPressed);
                PdnBaseForm.RegisterFormHotKey(Keys.Alt | digit, OnDigitHotKeyPressed);
            }

            this.ShowCloseButtons = true;
        }

        private bool OnNextTabHotKeyPressed(Keys keys)
        {
            bool processed = NextTab();
            return processed;
        }

        private bool OnPreviousTabHotKeyPressed(Keys keys)
        {
            bool processed = PreviousTab();
            return processed;
        }

        public bool NextTab()
        {
            bool changed = false;

            if (this.selectedDocument != null)
            {
                int currentIndex = this.documents.IndexOf(this.selectedDocument);
                int newIndex = (currentIndex + 1) % this.documents.Count;
                SelectedDocument = this.documents[newIndex];
                changed = true;
            }

            return changed;
        }

        public bool PreviousTab()
        {
            bool changed = false;

            if (this.selectedDocument != null)
            {
                int currentIndex = this.documents.IndexOf(this.selectedDocument);
                int newIndex = (currentIndex + (this.documents.Count - 1)) % this.documents.Count;
                SelectedDocument = this.documents[newIndex];
                changed = true;
            }

            return changed;
        }

        private void InitializeComponent()
        {
            this.Name = "DocumentStrip";
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                while (this.documents.Count > 0)
                {
                    RemoveDocumentWorkspace(this.documents[this.documents.Count - 1]);
                }

                if (this.thumbnailManager != null)
                {
                    this.thumbnailManager.Dispose();
                    this.thumbnailManager = null;
                }

                foreach (DocumentWorkspace dw in this.thumbs.Keys)
                {
                    RenderArgs ra = this.thumbs[dw];
                    ra.Dispose();
                }

                this.thumbs.Clear();
                this.thumbs = null;
            }

            base.Dispose(disposing);
        }

        protected override void OnScrollArrowClicked(ArrowDirection arrowDirection)
        {
            int sign = 0;

            switch (arrowDirection)
            {
                case ArrowDirection.Left:
                    sign = -1;
                    break;

                case ArrowDirection.Right:
                    sign = +1;
                    break;
            }

            int delta = ItemSize.Width;

            ScrollOffset += sign * delta;

            base.OnScrollArrowClicked(arrowDirection);
        }
        
        protected override void OnItemClicked(Item item, ItemPart itemPart, MouseButtons mouseButtons)
        {
            DocumentWorkspace dw = item.Tag as DocumentWorkspace;

            if (dw != null)
            {
                switch (itemPart)
                {
                    case ItemPart.None:
                        // do nothing
                        break;

                    case ItemPart.CloseButton:
                        if (mouseButtons == MouseButtons.Left)
                        {
                            OnDocumentClicked(dw, DocumentClickAction.Close);
                        }
                        break;

                    case ItemPart.Image:
                        if (mouseButtons == MouseButtons.Left)
                        {
                            SelectedDocument = dw;
                        }
                        else if (mouseButtons == MouseButtons.Right)
                        {
                            // TODO: right click menu
                        }
                        break;

                    default:
                        throw new InvalidEnumArgumentException();
                }
            }

            base.OnItemClicked(item, itemPart, mouseButtons);
        }

        public event EventHandler<EventArgs<Pair<DocumentWorkspace, DocumentClickAction>>> DocumentClicked;
        protected virtual void OnDocumentClicked(DocumentWorkspace dw, DocumentClickAction action)
        {
            if (DocumentClicked != null)
            {
                DocumentClicked(this, new EventArgs<Pair<DocumentWorkspace, DocumentClickAction>>(
                    Pair.Create(dw, action)));
            }
        }

        public void UnlockDocumentWorkspaceDirtyValue(DocumentWorkspace unlockMe)
        {
            Item docItem = this.dw2button[unlockMe];
            docItem.UnlockDirtyValue();
        }

        public void LockDocumentWorkspaceDirtyValue(DocumentWorkspace lockMe, bool forceDirtyValue)
        {
            Item docItem = this.dw2button[lockMe];
            docItem.LockDirtyValue(forceDirtyValue);
        }

        public void AddDocumentWorkspace(DocumentWorkspace addMe)
        {
            this.documents.Add(addMe);

            ImageStrip.Item docButton = new ImageStrip.Item();
            docButton.Image = null;
            docButton.Tag = addMe;

            AddItem(docButton);
            this.documentButtons.Add(docButton);

            addMe.CompositionUpdated += Workspace_CompositionUpdated;

            this.dw2button.Add(addMe, docButton);

            if (addMe.Document != null)
            {
                QueueThumbnailUpdate(addMe);
                docButton.Dirty = addMe.Document.Dirty;
                addMe.Document.DirtyChanged += Document_DirtyChanged;
            }

            addMe.DocumentChanging += Workspace_DocumentChanging;
            addMe.DocumentChanged += Workspace_DocumentChanged;

            OnDocumentListChanged();
        }

        private void Workspace_DocumentChanging(object sender, EventArgs<Document> e)
        {
            if (e.Data != null)
            {
                e.Data.DirtyChanged -= Document_DirtyChanged;
            }
        }

        private void Workspace_DocumentChanged(object sender, EventArgs e)
        {
            DocumentWorkspace dw = (DocumentWorkspace)sender;
            ImageStrip.Item docButton = this.dw2button[dw];

            if (dw.Document != null)
            {
                docButton.Dirty = dw.Document.Dirty;
                dw.Document.DirtyChanged += Document_DirtyChanged;
            }
            else
            {
                docButton.Dirty = false;
            }
        }

        private void Document_DirtyChanged(object sender, EventArgs e)
        {
            for (int i = 0; i < this.documents.Count; ++i)
            {
                if (object.ReferenceEquals(sender, this.documents[i].Document))
                {
                    ImageStrip.Item docButton = this.dw2button[this.documents[i]];
                    docButton.Dirty = ((Document)sender).Dirty;
                }
            }
        }

        private void Workspace_CompositionUpdated(object sender, EventArgs e)
        {
            DocumentWorkspace dw = (DocumentWorkspace)sender;
            QueueThumbnailUpdate(dw);
        }

        public void RemoveDocumentWorkspace(DocumentWorkspace removeMe)
        {
            removeMe.CompositionUpdated -= Workspace_CompositionUpdated;

            if (this.selectedDocument == removeMe)
            {
                this.selectedDocument = null;
            }

            removeMe.DocumentChanging -= Workspace_DocumentChanging;
            removeMe.DocumentChanged -= Workspace_DocumentChanged;

            if (removeMe.Document != null)
            {
                removeMe.Document.DirtyChanged -= Document_DirtyChanged;
            }

            this.documents.Remove(removeMe);
            this.thumbnailManager.RemoveFromQueue(removeMe);

            ImageStrip.Item docButton = this.dw2button[removeMe];
            this.RemoveItem(docButton);
            this.dw2button.Remove(removeMe);
            this.documentButtons.Remove(docButton);

            if (this.thumbs.ContainsKey(removeMe))
            {
                RenderArgs thumbRA = this.thumbs[removeMe];
                Surface surface = thumbRA.Surface;
                thumbRA.Dispose();
                this.thumbs.Remove(removeMe);
                surface.Dispose();
            }

            OnDocumentListChanged();
        }

        protected override void OnLayout(LayoutEventArgs levent)
        {
            base.OnLayout(levent);

            if (this.ensureSelectedIsVisible && 
                (!Focused && !LeftScrollButton.Focused && !RightScrollButton.Focused))
            {
                int index = this.documents.IndexOf(this.selectedDocument);
                EnsureItemFullyVisible(index);
            }
        }

        public void SelectDocumentWorkspace(DocumentWorkspace selectMe)
        {
            UI.SuspendControlPainting(this);

            this.selectedDocument = selectMe;

            if (this.thumbs.ContainsKey(selectMe))
            {
                RenderArgs thumb = this.thumbs[selectMe];
                Bitmap bitmap = thumb.Bitmap;
            }
            else
            {
                QueueThumbnailUpdate(selectMe);
            }

            foreach (ImageStrip.Item docItem in this.documentButtons)
            {
                if ((docItem.Tag as DocumentWorkspace) == selectMe)
                {
                    EnsureItemFullyVisible(docItem);
                    docItem.Checked = true;
                }
                else
                {
                    docItem.Checked = false;
                }
            }

            UI.ResumeControlPainting(this);
            Invalidate(true);
        }

        public void RefreshThumbnail(DocumentWorkspace dw)
        {
            if (this.documents.Contains(dw))
            {
                QueueThumbnailUpdate(dw);
            }
        }

        public void RefreshAllThumbnails()
        {
            foreach (DocumentWorkspace dw in this.documents)
            {
                QueueThumbnailUpdate(dw);
            }
        }

        private void OnThumbnailUpdated(DocumentWorkspace dw)
        {
            // We must double check that the DW is still around, because there's a chance
            // that the DW was been removed while the thumbnail was being rendered.
            if (this.dw2button.ContainsKey(dw))
            {
                ImageStrip.Item docButton = this.dw2button[dw];
                RenderArgs docRA = this.thumbs[dw];
                docButton.Image = docRA.Bitmap;
                docButton.Update();
            }
        }

        public void QueueThumbnailUpdate(DocumentWorkspace dw)
        {
            if (this.suspendThumbnailUpdates <= 0)
            {
                this.thumbnailManager.QueueThumbnailUpdate(dw, PreferredImageSize.Width - 2, OnThumbnailRendered);
            }
        }

        private void OnThumbnailRendered(object sender, EventArgs<Pair<IThumbnailProvider, Surface>> e)
        {
            RenderArgs ra = null;
            DocumentWorkspace dw = (DocumentWorkspace)e.Data.First;

            Size desiredSize = new Size(e.Data.Second.Width + 2, e.Data.Second.Height + 2);

            if (this.thumbs.ContainsKey(dw))
            {
                ra = this.thumbs[dw];

                if (ra.Size != desiredSize)
                {
                    ra.Dispose();
                    ra = null;

                    this.thumbs.Remove(dw);
                }
            }
            
            if (ra == null)
            {
                Surface surface = new Surface(desiredSize);
                ra = new RenderArgs(surface);
                this.thumbs.Add(dw, ra);
            }

            ra.Surface.Clear(ColorBgra.Black);
            ra.Surface.CopySurface(e.Data.Second, new Point(1, 1));
            e.Data.Second.Dispose();

            OnThumbnailUpdated(dw);
        }
    }
}
www.java2v.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.