/src/LayerControl.cs
C# | 582 lines | 456 code | 88 blank | 38 comment | 54 complexity | bd9ac2898aeb0490109251e0c43460f9 MD5 | raw file
- /////////////////////////////////////////////////////////////////////////////////
- // 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 System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Drawing;
- using System.Windows.Forms;
- using PaintDotNet.Base;
-
- namespace PaintDotNet
- {
- internal class LayerControl
- : UserControl
- {
- private class PanelWithLayout
- : PanelEx
- {
- private LayerControl _parentLayerControl;
- public LayerControl ParentLayerControl
- {
- get
- {
- return _parentLayerControl;
- }
-
- set
- {
- _parentLayerControl = value;
- }
- }
-
- public PanelWithLayout()
- {
- HideHScroll = true;
- }
-
- public void PositionLayers()
- {
- if (_parentLayerControl == null || _parentLayerControl._layerControls == null) return;
- int cursor = AutoScrollPosition.Y;
- int newWidth = ClientRectangle.Width;
-
- for (int i = _parentLayerControl._layerControls.Count - 1; i >= 0; --i)
- {
- LayerElement lec = _parentLayerControl._layerControls[i];
- lec.Width = newWidth;
- lec.Top = cursor;
- cursor += lec.Height;
- }
- }
-
- protected override void OnResize(EventArgs eventargs)
- {
- SystemLayer.UI.SuspendControlPainting(this);
- PositionLayers();
- AutoScrollPosition = new Point(0, -AutoScrollOffset.Y);
- base.OnResize(eventargs);
- SystemLayer.UI.ResumeControlPainting(this);
- Invalidate(true);
- }
-
- protected override void OnLayout(LayoutEventArgs levent)
- {
- PositionLayers();
- base.OnLayout(levent);
- }
- }
-
- public void PositionLayers()
- {
- _layerControlPanel.PositionLayers();
- }
-
- private readonly EventHandler _elementClickDelegate;
- private readonly EventHandler _elementDoubleClickDelegate;
- private readonly EventHandler _documentChangedDelegate;
- private readonly EventHandler<EventArgs<Document>> _documentChangingDelegate;
- private readonly EventHandler _layerChangedDelegate;
- private readonly KeyEventHandler _keyUpDelegate;
- private readonly IndexEventHandler _layerInsertedDelegate;
- private readonly IndexEventHandler _layerRemovedDelegate;
-
- private readonly int _elementHeight;
- private readonly int _thumbnailSize;
-
- private AppWorkspace _appWorkspace;
- private Document _document;
-
- private readonly List<LayerElement> _layerControls;
- private PanelWithLayout _layerControlPanel;
-
- private ThumbnailManager _thumbnailManager;
-
- [Browsable(false)]
- public LayerElement[] Layers
- {
- get {
- return _layerControls == null ? new LayerElement[0] : _layerControls.ToArray();
- }
- }
-
- public Layer ActiveLayer
- {
- get
- {
- int[] selected = SelectedLayerIndexes;
-
- return selected.Length == 1 ? Layers[selected[0]].Layer : null;
- }
- }
-
- public int ActiveLayerIndex
- {
- get
- {
- int[] selected = SelectedLayerIndexes;
-
- if (selected.Length == 1)
- {
- return selected[0];
- }
- return -1;
- }
- }
-
- private int[] SelectedLayerIndexes
- {
- get
- {
- LayerElement[] layers = Layers;
- var layerIndexes = new List<int>();
-
- for (int i = 0; i < layers.Length; ++i)
- {
- if (layers[i].IsSelected)
- {
- layerIndexes.Add(i);
- }
- }
-
- return layerIndexes.ToArray();
- }
- }
-
- public void ClearLayerSelection()
- {
- LayerElement[] layers = Layers;
-
- foreach (LayerElement t in layers)
- {
- t.IsSelected = false;
- }
- }
-
- public new BorderStyle BorderStyle
- {
- get
- {
- return _layerControlPanel.BorderStyle;
- }
-
- set
- {
- _layerControlPanel.BorderStyle = value;
- }
- }
-
- /// <summary>
- /// Required designer variable.
- /// </summary>
- private Container _components = null;
-
- public LayerControl()
- {
- _elementHeight = 6 + SystemLayer.UI.ScaleWidth(LayerElement.ThumbSizePreScaling);
-
- // This call is required by the Windows.Forms Form Designer.
- InitializeComponent();
-
- _elementClickDelegate = new EventHandler(ElementClickHandler);
- _elementDoubleClickDelegate = new EventHandler(ElementDoubleClickHandler);
- _documentChangedDelegate = new EventHandler(DocumentChangedHandler);
- _documentChangingDelegate = DocumentChangingHandler;
- _layerInsertedDelegate = new IndexEventHandler(LayerInsertedHandler);
- _layerRemovedDelegate = new IndexEventHandler(LayerRemovedHandler);
- _layerChangedDelegate = new EventHandler(LayerChangedHandler);
- _keyUpDelegate = new KeyEventHandler(KeyUpHandler);
-
- _thumbnailManager = new ThumbnailManager(this);
- _thumbnailSize = SystemLayer.UI.ScaleWidth(LayerElement.ThumbSizePreScaling);
- _layerControls = new List<LayerElement>();
- }
-
- private void SetupNewDocument(Document newDocument)
- {
- //thumbnailManager.ClearQueue();
-
- // Subscribe to the eevents
- _document = newDocument;
- _document.Layers.Inserted += _layerInsertedDelegate;
- _document.Layers.RemovedAt += _layerRemovedDelegate;
-
- SystemLayer.UI.SuspendControlPainting(_layerControlPanel);
-
- for (int i = 0; i < _document.Layers.Count; ++i)
- {
- LayerInsertedHandler(this, new IndexEventArgs(i));
- }
-
- if (_appWorkspace != null)
- {
- foreach (LayerElement lec in _layerControls)
- {
- lec.IsSelected = lec.Layer == _appWorkspace.ActiveDocumentWorkspace.ActiveLayer;
- }
- }
-
- SystemLayer.UI.ResumeControlPainting(_layerControlPanel);
- _layerControlPanel.Invalidate(true);
-
- OnActiveLayerChanged(ActiveLayer);
- }
-
- private void TearDownOldDocument()
- {
- SuspendLayout();
-
- foreach (LayerElement lec in _layerControls)
- {
- lec.Click -= _elementClickDelegate;
- lec.DoubleClick -= _elementDoubleClickDelegate;
- lec.KeyUp -= _keyUpDelegate;
- lec.Layer = null;
- _layerControlPanel.Controls.Remove(lec);
- lec.Dispose();
- }
-
- ResumeLayout(true);
-
- _layerControls.Clear();
-
- //thumbnailManager.ClearQueue();
-
- // Unsubscribe to the Events
- if (_document == null) return;
- _document.Layers.Inserted -= _layerInsertedDelegate;
- _document.Layers.RemovedAt -= _layerRemovedDelegate;
- _document = null;
- }
-
- private void DocumentChangingHandler(object sender, EventArgs<Document> e)
- {
- TearDownOldDocument();
- }
-
- private void DocumentChangedHandler(object sender, EventArgs e)
- {
- SetupNewDocument(_appWorkspace.ActiveDocumentWorkspace.Document);
- }
-
- private void LayerRemovedHandler(object sender, IndexEventArgs e)
- {
- LayerElement lec = _layerControls[e.Index];
- _thumbnailManager.RemoveFromQueue(lec.Layer);
- lec.Click -= _elementClickDelegate;
- lec.DoubleClick -= _elementDoubleClickDelegate;
- lec.KeyUp -= _keyUpDelegate;
- lec.Layer = null;
- _layerControls.Remove(lec);
- _layerControlPanel.Controls.Remove(lec);
- lec.Dispose();
- PerformLayout();
- }
-
- private void InitializeLayerElement(LayerElement lec, Layer l)
- {
- lec.Height = _elementHeight;
- lec.Layer = l;
- lec.Click += _elementClickDelegate;
- lec.DoubleClick += _elementDoubleClickDelegate;
- lec.KeyUp += _keyUpDelegate;
- lec.IsSelected = false;
- }
-
- private void SetActive(LayerElement lec)
- {
- SetActive(lec.Layer);
- }
-
- private void SetActive(Layer layer)
- {
- foreach (LayerElement lec in _layerControls)
- {
- bool active = (lec.Layer == layer);
- lec.IsSelected = active;
-
- if (!active) continue;
- OnActiveLayerChanged(lec.Layer);
- _layerControlPanel.ScrollControlIntoView(lec);
- lec.Select();
- Update();
- }
- }
-
- private void LayerInsertedHandler(object sender, IndexEventArgs e)
- {
- SuspendLayout();
- _layerControlPanel.SuspendLayout();
- var layer = (Layer)_document.Layers[e.Index];
- var lec = new LayerElement {ThumbnailManager = _thumbnailManager, ThumbnailSize = _thumbnailSize};
- InitializeLayerElement(lec, layer);
- _layerControls.Insert(e.Index, lec);
- _layerControlPanel.Controls.Add(lec);
- _layerControlPanel.ScrollControlIntoView(lec);
- lec.Select();
- SetActive(lec);
- lec.RefreshPreview();
- _layerControlPanel.ResumeLayout(false);
- ResumeLayout(false);
- _layerControlPanel.PerformLayout();
- PerformLayout();
-
- Refresh();
- }
-
- public void RefreshPreviews()
- {
- foreach (LayerElement t in _layerControls)
- {
- t.RefreshPreview();
- }
- }
-
- public event EventHandler RelinquishFocus;
- protected void OnRelinquishFocus()
- {
- if (RelinquishFocus != null)
- {
- RelinquishFocus(this, EventArgs.Empty);
- }
- }
-
- protected override void OnClick(EventArgs e)
- {
- OnRelinquishFocus();
- base.OnClick(e);
- }
-
- /// <summary>
- /// This event is raised whenever the user clicks on a layer within the
- /// LayerControl to activate it.
- /// </summary>
- public event EventHandler<EventArgs<Layer>> ClickedOnLayer;
- private void OnClickedOnLayer(Layer layer)
- {
- if (ClickedOnLayer != null)
- {
- ClickedOnLayer(this, new EventArgs<Layer>(layer));
- }
- }
-
- /// <summary>
- /// This event is raised whenever the selected layer is changed. Note that
- /// this can occur without user intervention, which distinguishes this event
- /// from ClickedOnLayer.
- /// </summary>
- public event EventHandler<EventArgs<Layer>> ActiveLayerChanged;
- private void OnActiveLayerChanged(Layer layer)
- {
- if (ActiveLayerChanged != null)
- {
- ActiveLayerChanged(this, new EventArgs<Layer>(layer));
- }
- }
-
- public event EventHandler<EventArgs<Layer>> DoubleClickedOnLayer;
- private void OnDoubleClickedOnLayer(Layer layer)
- {
- if (DoubleClickedOnLayer != null)
- {
- DoubleClickedOnLayer(this, new EventArgs<Layer>(layer));
- }
- }
-
- private void ElementClickHandler(object sender, EventArgs e)
- {
- var lec = (LayerElement)sender;
-
- if (ModifierKeys == Keys.Control)
- {
- lec.IsSelected = !lec.IsSelected;
- }
- else
- {
- ClearLayerSelection();
- lec.IsSelected = true;
- }
-
- SetActive(lec);
- OnClickedOnLayer(lec.Layer);
- }
-
- private void ElementDoubleClickHandler(object sender, EventArgs e)
- {
- OnDoubleClickedOnLayer(((LayerElement)sender).Layer);
- }
-
- private void LayerChangedHandler(object sender, EventArgs e)
- {
- SetActive(_appWorkspace.ActiveDocumentWorkspace.ActiveLayer);
- }
-
- public void SuspendLayerPreviewUpdates()
- {
- foreach (LayerElement element in _layerControls)
- {
- element.SuspendPreviewUpdates();
- }
- }
-
- public void ResumeLayerPreviewUpdates()
- {
- foreach (LayerElement element in _layerControls)
- {
- element.ResumePreviewUpdates();
- }
- }
-
- private void KeyUpHandler(object sender, KeyEventArgs e)
- {
- OnKeyUp(e);
- }
-
- [Browsable(false)]
- public AppWorkspace AppWorkspace
- {
- get
- {
- return _appWorkspace;
- }
-
- set
- {
- if (_appWorkspace == value) return;
- if (_appWorkspace != null)
- {
- TearDownOldDocument();
-
- _appWorkspace.ActiveDocumentWorkspaceChanging -= WorkspaceActiveDocumentWorkspaceChanging;
- _appWorkspace.ActiveDocumentWorkspaceChanged -= WorkspaceActiveDocumentWorkspaceChanged;
- }
-
- _appWorkspace = value;
-
- if (_appWorkspace == null) return;
- _appWorkspace.ActiveDocumentWorkspaceChanging += WorkspaceActiveDocumentWorkspaceChanging;
- _appWorkspace.ActiveDocumentWorkspaceChanged += WorkspaceActiveDocumentWorkspaceChanged;
-
- if (_appWorkspace.ActiveDocumentWorkspace != null)
- {
- SetupNewDocument(_appWorkspace.ActiveDocumentWorkspace.Document);
- }
- }
- }
-
- private void WorkspaceActiveDocumentWorkspaceChanging(object sender, EventArgs e)
- {
- TearDownOldDocument();
-
- if (_appWorkspace.ActiveDocumentWorkspace == null) return;
- _appWorkspace.ActiveDocumentWorkspace.DocumentChanging -= _documentChangingDelegate;
- _appWorkspace.ActiveDocumentWorkspace.DocumentChanged -= _documentChangedDelegate;
- _appWorkspace.ActiveDocumentWorkspace.ActiveLayerChanged -= _layerChangedDelegate;
- }
-
- private void WorkspaceActiveDocumentWorkspaceChanged(object sender, EventArgs e)
- {
- if (_appWorkspace.ActiveDocumentWorkspace == null) return;
- _appWorkspace.ActiveDocumentWorkspace.DocumentChanging += _documentChangingDelegate;
- _appWorkspace.ActiveDocumentWorkspace.DocumentChanged += _documentChangedDelegate;
- _appWorkspace.ActiveDocumentWorkspace.ActiveLayerChanged += _layerChangedDelegate;
-
- if (_appWorkspace.ActiveDocumentWorkspace.Document != null)
- {
- SetupNewDocument(_appWorkspace.ActiveDocumentWorkspace.Document);
- }
- }
-
- [Browsable(false)]
- public Document Document
- {
- get
- {
- return _document;
- }
-
- set
- {
- if (_appWorkspace != null)
- {
- throw new InvalidOperationException("Workspace property is already set");
- }
-
- if (_document != null)
- {
- TearDownOldDocument();
- }
-
- if (value != null)
- {
- SetupNewDocument(value);
- }
- }
- }
-
- /// <summary>
- /// Clean up any resources being used.
- /// </summary>
- protected override void Dispose(bool disposing)
- {
- if (disposing)
- {
- if (_components != null)
- {
- _components.Dispose();
- _components = null;
- }
-
- if (_thumbnailManager != null)
- {
- _thumbnailManager.Dispose();
- _thumbnailManager = null;
- }
- }
-
- base.Dispose(disposing);
- }
-
- private void LayerControlPanelClick(object sender, EventArgs e)
- {
- OnRelinquishFocus();
- }
-
- #region Component Designer generated code
- /// <summary>
- /// Required method for Designer support - do not modify
- /// the contents of this method with the code editor.
- /// </summary>
- private void InitializeComponent()
- {
- this._layerControlPanel = new PanelWithLayout();
- this.SuspendLayout();
- //
- // layerControlPanel
- //
- this._layerControlPanel.AutoScroll = true;
- this._layerControlPanel.Dock = System.Windows.Forms.DockStyle.Fill;
- this._layerControlPanel.Location = new System.Drawing.Point(0, 0);
- this._layerControlPanel.Name = "_layerControlPanel";
- this._layerControlPanel.ParentLayerControl = this;
- this._layerControlPanel.Size = new System.Drawing.Size(150, 150);
- this._layerControlPanel.TabIndex = 2;
- this._layerControlPanel.Click += new EventHandler(LayerControlPanelClick);
- //
- // LayerControl
- //
- this.Controls.Add(this._layerControlPanel);
- this.Name = "LayerControl";
- this.ResumeLayout(false);
-
- }
-
- #endregion
- }
- }