├── .nuget ├── NuGet.exe └── NuGet.targets ├── TestApp ├── Resources │ ├── ItemBig.png │ ├── ItemHigh.png │ ├── ItemSmall.png │ └── ItemWide.png ├── app.config ├── Properties │ ├── Settings.settings │ ├── Settings.Designer.cs │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ └── Resources.resx ├── Program.cs ├── TimelineFunctionGraphModel.cs ├── TestApp.csproj └── DemoForm.resx ├── WinForms ├── EmbeddedResources │ ├── add.png │ ├── cross.png │ ├── arrow_up.png │ ├── arrow_down.png │ ├── arrow_left.png │ ├── arrow_right.png │ ├── DropDownIcon.png │ ├── arrow_upleft.png │ ├── arrow_upright.png │ ├── NumberGripIcon.png │ ├── arrow_downleft.png │ ├── arrow_downright.png │ ├── ExpandNodeClosedHot.png │ ├── ExpandNodeOpenedHot.png │ ├── ExpandNodeClosedNormal.png │ ├── ExpandNodeClosedPressed.png │ ├── ExpandNodeOpenedNormal.png │ ├── ExpandNodeOpenedPressed.png │ ├── ExpandNodeClosedDisabled.png │ └── ExpandNodeOpenedDisabled.png ├── packages.config ├── ItemModels │ ├── MenuItemTypeHint.cs │ ├── IListModel.cs │ ├── IMenuModel.cs │ ├── EventArgs │ │ ├── ListModelItemsEventArgs.cs │ │ └── MenuModelItemsEventArgs.cs │ ├── IMenuModelItem.cs │ ├── ListModel.cs │ └── MenuModel.cs ├── TimelineControls │ ├── TimelineViewRulerMarkWeight.cs │ ├── Models │ │ ├── ITimelineTrackModel.cs │ │ ├── ITimelineGraphModel.cs │ │ ├── ITimelineGraphTrackModel.cs │ │ ├── ITimelineModel.cs │ │ ├── TimelineTrackModel.cs │ │ ├── TimelineGraphTrackModel.cs │ │ ├── TimelineModel.cs │ │ └── TimelineLinearGraphModel.cs │ ├── TimelineViewRulerMark.cs │ ├── EventArgs │ │ ├── TimelineViewEventArgs.cs │ │ ├── TimelineGraphEventArgs.cs │ │ ├── TimelineTrackModelEventArgs.cs │ │ ├── TimelineViewTrackEventArgs.cs │ │ ├── TimelineGraphCollectionEventArgs.cs │ │ ├── TimelineGraphModelChangedEventArgs.cs │ │ ├── TimelineTrackModelCollectionEventArgs.cs │ │ ├── TimelineTrackModelChangedEventArgs.cs │ │ ├── TimelineGraphRangeEventArgs.cs │ │ ├── TimelineViewPaintEventArgs.cs │ │ ├── TimelineViewCursorEventArgs.cs │ │ ├── TimelineViewSelectionEventArgs.cs │ │ └── TimelineViewTrackPaintEventArgs.cs │ ├── TimelineViewControlRenderer.cs │ ├── TimelineModelViewAssignmentAttribute.cs │ └── TimelineViewTrack.cs ├── Drawing │ ├── BorderState.cs │ ├── TextBoxStyle.cs │ ├── ButtonState.cs │ ├── BorderStyle.cs │ ├── QualityLevel.cs │ ├── TextBoxState.cs │ ├── ExpandNodeState.cs │ ├── ExpandBoxState.cs │ ├── CheckBoxState.cs │ └── IconImage.cs ├── Internal │ ├── ExtMethodsMessage.cs │ ├── NativeWinAPI.cs │ ├── ExtMethodsColor.cs │ └── ReflectionHelper.cs ├── ItemViews │ ├── EventArgs │ │ ├── TiledViewEventArgs.cs │ │ ├── MenuStripMenuViewEventArgs.cs │ │ ├── TiledViewItemEventArgs.cs │ │ ├── MenuStripMenuViewItemEventArgs.cs │ │ ├── TiledViewItemAppearanceEventArgs.cs │ │ ├── TiledViewItemMouseEventArgs.cs │ │ └── TiledViewItemDrawEventArgs.cs │ ├── ITiledViewItemEditor.cs │ └── TiledViewTextItemEditor.cs ├── PropertyEditing │ ├── BitmaskItem.cs │ ├── ObjectItem.cs │ ├── PropertyEditors │ │ ├── FlaggedEnumPropertyEditor.cs │ │ ├── LabelPropertyEditor.cs │ │ ├── StringPropertyEditor.cs │ │ ├── ObjectSelectorPropertyEditor.cs │ │ ├── BitmaskPropertyEditor.cs │ │ ├── EnumPropertyEditor.cs │ │ └── BoolPropertyEditor.cs │ └── EditorTemplates │ │ ├── ComboBoxDropDown.cs │ │ ├── MultiComboBoxDropDown.cs │ │ ├── EditorTemplate.cs │ │ ├── BitmaskSelectorDropDown.cs │ │ ├── MultiComboBoxEditorTemplate.cs │ │ ├── BitmaskEditorTemplate.cs │ │ └── ComboBoxEditorTemplate.cs ├── AdamsLair.WinForms.nuspec ├── Properties │ ├── AssemblyInfo.cs │ └── ResourcesCache.cs └── ColorControls │ ├── ColorShowBox.cs │ └── ColorPickerDialog.resx ├── README.md ├── Publish NuGet Package.bat ├── LICENSE ├── AdamsLair.WinForms.sln └── .gitignore /.nuget/NuGet.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdamsLair/winforms/HEAD/.nuget/NuGet.exe -------------------------------------------------------------------------------- /TestApp/Resources/ItemBig.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdamsLair/winforms/HEAD/TestApp/Resources/ItemBig.png -------------------------------------------------------------------------------- /TestApp/Resources/ItemHigh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdamsLair/winforms/HEAD/TestApp/Resources/ItemHigh.png -------------------------------------------------------------------------------- /TestApp/Resources/ItemSmall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdamsLair/winforms/HEAD/TestApp/Resources/ItemSmall.png -------------------------------------------------------------------------------- /TestApp/Resources/ItemWide.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdamsLair/winforms/HEAD/TestApp/Resources/ItemWide.png -------------------------------------------------------------------------------- /WinForms/EmbeddedResources/add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdamsLair/winforms/HEAD/WinForms/EmbeddedResources/add.png -------------------------------------------------------------------------------- /WinForms/EmbeddedResources/cross.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdamsLair/winforms/HEAD/WinForms/EmbeddedResources/cross.png -------------------------------------------------------------------------------- /WinForms/EmbeddedResources/arrow_up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdamsLair/winforms/HEAD/WinForms/EmbeddedResources/arrow_up.png -------------------------------------------------------------------------------- /WinForms/EmbeddedResources/arrow_down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdamsLair/winforms/HEAD/WinForms/EmbeddedResources/arrow_down.png -------------------------------------------------------------------------------- /WinForms/EmbeddedResources/arrow_left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdamsLair/winforms/HEAD/WinForms/EmbeddedResources/arrow_left.png -------------------------------------------------------------------------------- /WinForms/EmbeddedResources/arrow_right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdamsLair/winforms/HEAD/WinForms/EmbeddedResources/arrow_right.png -------------------------------------------------------------------------------- /WinForms/EmbeddedResources/DropDownIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdamsLair/winforms/HEAD/WinForms/EmbeddedResources/DropDownIcon.png -------------------------------------------------------------------------------- /WinForms/EmbeddedResources/arrow_upleft.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdamsLair/winforms/HEAD/WinForms/EmbeddedResources/arrow_upleft.png -------------------------------------------------------------------------------- /WinForms/EmbeddedResources/arrow_upright.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdamsLair/winforms/HEAD/WinForms/EmbeddedResources/arrow_upright.png -------------------------------------------------------------------------------- /WinForms/EmbeddedResources/NumberGripIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdamsLair/winforms/HEAD/WinForms/EmbeddedResources/NumberGripIcon.png -------------------------------------------------------------------------------- /WinForms/EmbeddedResources/arrow_downleft.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdamsLair/winforms/HEAD/WinForms/EmbeddedResources/arrow_downleft.png -------------------------------------------------------------------------------- /WinForms/EmbeddedResources/arrow_downright.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdamsLair/winforms/HEAD/WinForms/EmbeddedResources/arrow_downright.png -------------------------------------------------------------------------------- /WinForms/EmbeddedResources/ExpandNodeClosedHot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdamsLair/winforms/HEAD/WinForms/EmbeddedResources/ExpandNodeClosedHot.png -------------------------------------------------------------------------------- /WinForms/EmbeddedResources/ExpandNodeOpenedHot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdamsLair/winforms/HEAD/WinForms/EmbeddedResources/ExpandNodeOpenedHot.png -------------------------------------------------------------------------------- /WinForms/EmbeddedResources/ExpandNodeClosedNormal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdamsLair/winforms/HEAD/WinForms/EmbeddedResources/ExpandNodeClosedNormal.png -------------------------------------------------------------------------------- /WinForms/EmbeddedResources/ExpandNodeClosedPressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdamsLair/winforms/HEAD/WinForms/EmbeddedResources/ExpandNodeClosedPressed.png -------------------------------------------------------------------------------- /WinForms/EmbeddedResources/ExpandNodeOpenedNormal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdamsLair/winforms/HEAD/WinForms/EmbeddedResources/ExpandNodeOpenedNormal.png -------------------------------------------------------------------------------- /WinForms/EmbeddedResources/ExpandNodeOpenedPressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdamsLair/winforms/HEAD/WinForms/EmbeddedResources/ExpandNodeOpenedPressed.png -------------------------------------------------------------------------------- /WinForms/EmbeddedResources/ExpandNodeClosedDisabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdamsLair/winforms/HEAD/WinForms/EmbeddedResources/ExpandNodeClosedDisabled.png -------------------------------------------------------------------------------- /WinForms/EmbeddedResources/ExpandNodeOpenedDisabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdamsLair/winforms/HEAD/WinForms/EmbeddedResources/ExpandNodeOpenedDisabled.png -------------------------------------------------------------------------------- /TestApp/app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /WinForms/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /WinForms/ItemModels/MenuItemTypeHint.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace AdamsLair.WinForms.ItemModels 7 | { 8 | public enum MenuItemTypeHint 9 | { 10 | Item, 11 | Separator 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /TestApp/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /WinForms/TimelineControls/TimelineViewRulerMarkWeight.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | 6 | namespace AdamsLair.WinForms.TimelineControls 7 | { 8 | public enum TimelineViewRulerMarkWeight 9 | { 10 | Minor, 11 | Regular, 12 | Major 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /WinForms/Drawing/BorderState.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Drawing; 5 | using System.Drawing.Drawing2D; 6 | using System.Windows.Forms; 7 | 8 | using AdamsLair.WinForms.Properties; 9 | 10 | namespace AdamsLair.WinForms.Drawing 11 | { 12 | public enum BorderState 13 | { 14 | Normal, 15 | Disabled 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /WinForms/Drawing/TextBoxStyle.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Drawing; 5 | using System.Drawing.Drawing2D; 6 | using System.Windows.Forms; 7 | 8 | using AdamsLair.WinForms.Properties; 9 | 10 | namespace AdamsLair.WinForms.Drawing 11 | { 12 | public enum TextBoxStyle 13 | { 14 | Plain, 15 | Flat, 16 | Sunken 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /WinForms/Drawing/ButtonState.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Drawing; 5 | using System.Drawing.Drawing2D; 6 | using System.Windows.Forms; 7 | 8 | using AdamsLair.WinForms.Properties; 9 | 10 | namespace AdamsLair.WinForms.Drawing 11 | { 12 | public enum ButtonState 13 | { 14 | Disabled, 15 | Normal, 16 | Hot, 17 | Pressed 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /WinForms/Drawing/BorderStyle.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Drawing; 5 | using System.Drawing.Drawing2D; 6 | using System.Windows.Forms; 7 | 8 | using AdamsLair.WinForms.Properties; 9 | 10 | namespace AdamsLair.WinForms.Drawing 11 | { 12 | public enum BorderStyle 13 | { 14 | Simple, 15 | Focus, 16 | ContentBox, 17 | Sunken 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /WinForms/TimelineControls/Models/ITimelineTrackModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace AdamsLair.WinForms.TimelineControls 7 | { 8 | public interface ITimelineTrackModel 9 | { 10 | string TrackName { get; } 11 | float EndTime { get; } 12 | float BeginTime { get; } 13 | 14 | event EventHandler TrackNameChanged; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /WinForms/Drawing/QualityLevel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace AdamsLair.WinForms.Drawing 7 | { 8 | /// 9 | /// Represents the level of drawing quality. It is guaranteed that higher levels also have higher numeric values. 10 | /// 11 | public enum QualityLevel 12 | { 13 | Low = 0, 14 | Medium = 1, 15 | High = 2 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /WinForms/Internal/ExtMethodsMessage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Windows.Forms; 6 | 7 | using AdamsLair.WinForms.NativeWinAPI; 8 | 9 | namespace AdamsLair.WinForms 10 | { 11 | internal static class ExtMethodsMessage 12 | { 13 | public static WindowMessage GetWindowMessage(this Message msg) 14 | { 15 | return (WindowMessage)msg.Msg; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /WinForms/ItemModels/IListModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace AdamsLair.WinForms.ItemModels 7 | { 8 | public interface IListModel 9 | { 10 | int Count { get; } 11 | object GetItemAt(int index); 12 | int GetIndexOf(object item); 13 | 14 | event EventHandler CountChanged; 15 | event EventHandler IndicesChanged; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /WinForms/ItemViews/EventArgs/TiledViewEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace AdamsLair.WinForms.ItemViews 7 | { 8 | public class TiledViewEventArgs : EventArgs 9 | { 10 | private TiledView view; 11 | public TiledView View 12 | { 13 | get { return this.view; } 14 | } 15 | public TiledViewEventArgs(TiledView view) 16 | { 17 | this.view = view; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /WinForms/Drawing/TextBoxState.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Drawing; 5 | using System.Drawing.Drawing2D; 6 | using System.Windows.Forms; 7 | 8 | using AdamsLair.WinForms.Properties; 9 | 10 | namespace AdamsLair.WinForms.Drawing 11 | { 12 | [Flags] 13 | public enum TextBoxState 14 | { 15 | Disabled = 0x1, 16 | Normal = 0x2, 17 | Hot = 0x4, 18 | Focus = 0x8, 19 | 20 | ReadOnlyFlag = 0x100 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /WinForms/ItemModels/IMenuModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace AdamsLair.WinForms.ItemModels 7 | { 8 | public interface IMenuModel 9 | { 10 | IEnumerable Items { get; } 11 | 12 | event EventHandler ItemsAdded; 13 | event EventHandler ItemsRemoved; 14 | event EventHandler ItemsChanged; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /WinForms/Drawing/ExpandNodeState.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Drawing; 5 | using System.Drawing.Drawing2D; 6 | using System.Windows.Forms; 7 | 8 | using AdamsLair.WinForms.Properties; 9 | 10 | namespace AdamsLair.WinForms.Drawing 11 | { 12 | public enum ExpandNodeState 13 | { 14 | OpenedDisabled, 15 | OpenedNormal, 16 | OpenedHot, 17 | OpenedPressed, 18 | ClosedDisabled, 19 | ClosedNormal, 20 | ClosedHot, 21 | ClosedPressed 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /TestApp/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Windows.Forms; 5 | 6 | namespace AdamsLair.WinForms.TestApp 7 | { 8 | static class Program 9 | { 10 | /// 11 | /// Der Haupteinstiegspunkt für die Anwendung. 12 | /// 13 | [STAThread] 14 | static void Main() 15 | { 16 | Application.EnableVisualStyles(); 17 | Application.SetCompatibleTextRenderingDefault(false); 18 | Application.Run(new DemoForm()); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /WinForms/Drawing/ExpandBoxState.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Drawing; 5 | using System.Drawing.Drawing2D; 6 | using System.Windows.Forms; 7 | 8 | using AdamsLair.WinForms.Properties; 9 | 10 | namespace AdamsLair.WinForms.Drawing 11 | { 12 | public enum ExpandBoxState 13 | { 14 | ExpandDisabled, 15 | ExpandPressed, 16 | ExpandHot, 17 | ExpandNormal, 18 | 19 | CollapseDisabled, 20 | CollapsePressed, 21 | CollapseHot, 22 | CollapseNormal 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /WinForms/TimelineControls/Models/ITimelineGraphModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace AdamsLair.WinForms.TimelineControls 7 | { 8 | public interface ITimelineGraphModel 9 | { 10 | float EndTime { get; } 11 | float BeginTime { get; } 12 | 13 | float GetValueAtX(float units); 14 | float GetMaxValueInRange(float begin, float end); 15 | float GetMinValueInRange(float begin, float end); 16 | 17 | event EventHandler GraphChanged; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /WinForms/ItemViews/EventArgs/MenuStripMenuViewEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Windows.Forms; 6 | 7 | namespace AdamsLair.WinForms.ItemViews 8 | { 9 | public class MenuStripMenuViewEventArgs : EventArgs 10 | { 11 | private MenuStripMenuView view = null; 12 | 13 | public MenuStripMenuView View 14 | { 15 | get { return this.view; } 16 | } 17 | 18 | public MenuStripMenuViewEventArgs(MenuStripMenuView view) 19 | { 20 | this.view = view; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /WinForms/TimelineControls/Models/ITimelineGraphTrackModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace AdamsLair.WinForms.TimelineControls 7 | { 8 | public interface ITimelineGraphTrackModel : ITimelineTrackModel 9 | { 10 | IEnumerable Graphs { get; } 11 | 12 | event EventHandler GraphsAdded; 13 | event EventHandler GraphsRemoved; 14 | event EventHandler GraphChanged; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /WinForms/TimelineControls/TimelineViewRulerMark.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | 6 | namespace AdamsLair.WinForms.TimelineControls 7 | { 8 | public struct TimelineViewRulerMark 9 | { 10 | public float UnitValue; 11 | public float PixelValue; 12 | public TimelineViewRulerMarkWeight Weight; 13 | 14 | public TimelineViewRulerMark(float units, float pixels, TimelineViewRulerMarkWeight weight) 15 | { 16 | this.UnitValue = units; 17 | this.PixelValue = pixels; 18 | this.Weight = weight; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /WinForms/TimelineControls/EventArgs/TimelineViewEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Drawing; 6 | 7 | using AdamsLair.WinForms.Drawing; 8 | 9 | namespace AdamsLair.WinForms.TimelineControls 10 | { 11 | public class TimelineViewEventArgs : EventArgs 12 | { 13 | private TimelineView view = null; 14 | 15 | public TimelineView View 16 | { 17 | get { return this.view; } 18 | } 19 | 20 | public TimelineViewEventArgs(TimelineView view) 21 | { 22 | this.view = view; 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /WinForms/TimelineControls/EventArgs/TimelineGraphEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Drawing; 6 | 7 | using AdamsLair.WinForms.Drawing; 8 | 9 | namespace AdamsLair.WinForms.TimelineControls 10 | { 11 | public class TimelineGraphEventArgs : EventArgs 12 | { 13 | private ITimelineGraphModel graph; 14 | public ITimelineGraphModel Graph 15 | { 16 | get { return this.graph; } 17 | } 18 | public TimelineGraphEventArgs(ITimelineGraphModel graph) 19 | { 20 | this.graph = graph; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /WinForms/Drawing/CheckBoxState.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Drawing; 5 | using System.Drawing.Drawing2D; 6 | using System.Windows.Forms; 7 | 8 | using AdamsLair.WinForms.Properties; 9 | 10 | namespace AdamsLair.WinForms.Drawing 11 | { 12 | public enum CheckBoxState 13 | { 14 | CheckedDisabled, 15 | CheckedPressed, 16 | CheckedHot, 17 | CheckedNormal, 18 | 19 | UncheckedDisabled, 20 | UncheckedPressed, 21 | UncheckedHot, 22 | UncheckedNormal, 23 | 24 | MixedDisabled, 25 | MixedPressed, 26 | MixedHot, 27 | MixedNormal 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /WinForms/TimelineControls/EventArgs/TimelineTrackModelEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Drawing; 6 | 7 | using AdamsLair.WinForms.Drawing; 8 | 9 | namespace AdamsLair.WinForms.TimelineControls 10 | { 11 | public class TimelineTrackModelEventArgs : EventArgs 12 | { 13 | private ITimelineTrackModel model = null; 14 | public ITimelineTrackModel Model 15 | { 16 | get { return this.model; } 17 | } 18 | public TimelineTrackModelEventArgs(ITimelineTrackModel model) 19 | { 20 | this.model = model; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /WinForms/TimelineControls/Models/ITimelineModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace AdamsLair.WinForms.TimelineControls 7 | { 8 | public interface ITimelineModel 9 | { 10 | string UnitName { get; } 11 | string UnitDescription { get; } 12 | float UnitBaseScale { get; } 13 | IEnumerable Tracks { get; } 14 | 15 | event EventHandler UnitChanged; 16 | event EventHandler TracksAdded; 17 | event EventHandler TracksRemoved; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /WinForms/TimelineControls/EventArgs/TimelineViewTrackEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Drawing; 6 | 7 | using AdamsLair.WinForms.Drawing; 8 | 9 | namespace AdamsLair.WinForms.TimelineControls 10 | { 11 | public class TimelineViewTrackEventArgs : TimelineViewEventArgs 12 | { 13 | private TimelineViewTrack track = null; 14 | 15 | public TimelineViewTrack Track 16 | { 17 | get { return this.track; } 18 | } 19 | 20 | public TimelineViewTrackEventArgs(TimelineViewTrack track) : base(track.ParentView) 21 | { 22 | this.track = track; 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /WinForms/ItemViews/ITiledViewItemEditor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Collections; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Windows.Forms; 8 | using System.Drawing; 9 | 10 | using AdamsLair.WinForms.Drawing; 11 | using AdamsLair.WinForms.ItemModels; 12 | 13 | namespace AdamsLair.WinForms.ItemViews 14 | { 15 | public interface ITiledViewItemEditor 16 | { 17 | event EventHandler StopEditing; 18 | 19 | bool IsAcceptingValue { get; } 20 | Control MainControl { get; } 21 | 22 | void GetValueFromItem(object item); 23 | bool ApplyValueToItem(object item); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /WinForms/TimelineControls/EventArgs/TimelineGraphCollectionEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Drawing; 6 | 7 | using AdamsLair.WinForms.Drawing; 8 | 9 | namespace AdamsLair.WinForms.TimelineControls 10 | { 11 | public class TimelineGraphCollectionEventArgs : EventArgs 12 | { 13 | private ITimelineGraphModel[] graphs; 14 | public IEnumerable Graphs 15 | { 16 | get { return this.graphs; } 17 | } 18 | public TimelineGraphCollectionEventArgs(IEnumerable graphs) 19 | { 20 | this.graphs = graphs.ToArray(); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | AdamsLair.WinForms 2 | ================== 3 | 4 | A collection of custom Controls for Windows.Forms. These include: 5 | 6 | * A custom **ColorPicker** Dialog, similar to the one known from software like Photoshop, but also supporting alpha values. 7 | * A custom **PropertyGrid** Control, aimed to be highly extensible. 8 | * **TiledView**, a model / view based Control to display large amounts of items in a tiled grid. 9 | * A **model / view** separated representation of **MenuStrips** that can be used to display the same menu structure in MenuStrips, ContextMenus or submenus and react to events caused by it. Can easily be extended to include Tool- and StatusStrips as well. 10 | -------------------------------------------------------------------------------- /WinForms/PropertyEditing/BitmaskItem.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace AdamsLair.WinForms.PropertyEditing 7 | { 8 | public class BitmaskItem 9 | { 10 | private ulong value = 0; 11 | private string caption = null; 12 | 13 | public string Caption 14 | { 15 | get { return this.caption; } 16 | } 17 | public ulong Value 18 | { 19 | get { return this.value; } 20 | } 21 | 22 | public BitmaskItem(ulong v, string c) 23 | { 24 | this.value = v; 25 | this.caption = c; 26 | } 27 | 28 | public override string ToString() 29 | { 30 | return this.caption; 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /WinForms/PropertyEditing/ObjectItem.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace AdamsLair.WinForms.PropertyEditing 7 | { 8 | public class ObjectItem 9 | { 10 | private object value = null; 11 | private string caption = null; 12 | 13 | public string Caption 14 | { 15 | get { return this.caption; } 16 | } 17 | public object Value 18 | { 19 | get { return this.value; } 20 | } 21 | 22 | public ObjectItem(object v, string c) 23 | { 24 | this.value = v; 25 | this.caption = c; 26 | } 27 | 28 | public override string ToString() 29 | { 30 | return this.caption; 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /WinForms/TimelineControls/EventArgs/TimelineGraphModelChangedEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Drawing; 6 | 7 | using AdamsLair.WinForms.Drawing; 8 | 9 | namespace AdamsLair.WinForms.TimelineControls 10 | { 11 | public class TimelineGraphChangedEventArgs : TimelineGraphEventArgs 12 | { 13 | private ITimelineGraphModel oldGraph = null; 14 | public ITimelineGraphModel OldGraph 15 | { 16 | get { return this.oldGraph; } 17 | } 18 | public TimelineGraphChangedEventArgs(ITimelineGraphModel oldGraph, ITimelineGraphModel graph) : base(graph) 19 | { 20 | this.oldGraph = oldGraph; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /WinForms/TimelineControls/EventArgs/TimelineTrackModelCollectionEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Drawing; 6 | 7 | using AdamsLair.WinForms.Drawing; 8 | 9 | namespace AdamsLair.WinForms.TimelineControls 10 | { 11 | public class TimelineTrackModelCollectionEventArgs : EventArgs 12 | { 13 | private ITimelineTrackModel[] tracks = null; 14 | 15 | public IEnumerable Tracks 16 | { 17 | get { return this.tracks; } 18 | } 19 | 20 | public TimelineTrackModelCollectionEventArgs(IEnumerable tracks) 21 | { 22 | this.tracks = tracks.ToArray(); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Publish NuGet Package.bat: -------------------------------------------------------------------------------- 1 | :: search for msbuild make it available 2 | set msbuildPath=%ProgramFiles(x86)%\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\ 3 | set PATH=%PATH%;%msbuildPath% 4 | 5 | :: make sure we have a clean release build 6 | msbuild /t:Rebuild /p:Configuration=Release /p:Platform="Any CPU" AdamsLair.WinForms.sln 7 | 8 | :: remove any existing nupkg files 9 | del *.nupkg 10 | 11 | :: build the nuget packages 12 | .nuget\nuget pack WinForms\AdamsLair.WinForms.csproj -Properties Configuration=Release;Platform=AnyCPU 13 | 14 | :: upload the nuget packages 15 | .nuget\nuget push *.nupkg -Source "https://www.nuget.org" 16 | 17 | :: remove nupkg files after uploading them 18 | del *.nupkg 19 | -------------------------------------------------------------------------------- /WinForms/TimelineControls/EventArgs/TimelineTrackModelChangedEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Drawing; 6 | 7 | using AdamsLair.WinForms.Drawing; 8 | 9 | namespace AdamsLair.WinForms.TimelineControls 10 | { 11 | public class TimelineTrackModelChangedEventArgs : TimelineTrackModelEventArgs 12 | { 13 | private ITimelineTrackModel oldModel = null; 14 | public ITimelineTrackModel OldModel 15 | { 16 | get { return this.oldModel; } 17 | } 18 | public TimelineTrackModelChangedEventArgs(ITimelineTrackModel oldModel, ITimelineTrackModel model) : base(model) 19 | { 20 | this.oldModel = oldModel; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /WinForms/TimelineControls/TimelineViewControlRenderer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Drawing; 5 | using System.Drawing.Drawing2D; 6 | 7 | using AdamsLair.WinForms.Drawing; 8 | 9 | namespace AdamsLair.WinForms.TimelineControls 10 | { 11 | public class TimelineViewControlRenderer : ControlRenderer 12 | { 13 | public Color ColorRulerMarkMajor 14 | { 15 | get { return this.ColorVeryDarkBackground; } 16 | } 17 | public Color ColorRulerMarkRegular 18 | { 19 | get { return Color.FromArgb(162, this.ColorVeryDarkBackground); } 20 | } 21 | public Color ColorRulerMarkMinor 22 | { 23 | get { return Color.FromArgb(96, this.ColorVeryDarkBackground); } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /WinForms/ItemModels/EventArgs/ListModelItemsEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace AdamsLair.WinForms.ItemModels 7 | { 8 | public class ListModelItemsEventArgs : EventArgs 9 | { 10 | private int index; 11 | private int count; 12 | 13 | public int Index 14 | { 15 | get { return this.index; } 16 | } 17 | public int Count 18 | { 19 | get { return this.count; } 20 | } 21 | 22 | public ListModelItemsEventArgs(int index, int count) 23 | { 24 | if (index < 0) throw new ArgumentException("Index needs to be > 0."); 25 | if (count < 1) throw new ArgumentException("Count needs to be >= 1."); 26 | this.index = index; 27 | this.count = count; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /WinForms/TimelineControls/TimelineModelViewAssignmentAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace AdamsLair.WinForms.TimelineControls 7 | { 8 | [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] 9 | public class TimelineModelViewAssignmentAttribute : Attribute 10 | { 11 | private Type[] validModelTypes; 12 | public Type[] ValidModelTypes 13 | { 14 | get { return this.validModelTypes; } 15 | } 16 | public TimelineModelViewAssignmentAttribute(params Type[] validModelTypes) 17 | { 18 | this.validModelTypes = validModelTypes.Where(t => t != null && (typeof(ITimelineTrackModel).IsAssignableFrom(t) || typeof(ITimelineGraphModel).IsAssignableFrom(t))).ToArray(); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /WinForms/TimelineControls/Models/TimelineTrackModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace AdamsLair.WinForms.TimelineControls 7 | { 8 | public abstract class TimelineTrackModel : ITimelineTrackModel 9 | { 10 | private string trackName = "A Timeline Track"; 11 | 12 | public string TrackName 13 | { 14 | get { return this.trackName; } 15 | set 16 | { 17 | if (this.trackName != value) 18 | { 19 | this.trackName = value; 20 | if (this.TrackNameChanged != null) 21 | this.TrackNameChanged(this, EventArgs.Empty); 22 | } 23 | } 24 | } 25 | public abstract float EndTime { get; } 26 | public abstract float BeginTime { get; } 27 | 28 | public event EventHandler TrackNameChanged; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /WinForms/TimelineControls/EventArgs/TimelineGraphRangeEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Drawing; 6 | 7 | using AdamsLair.WinForms.Drawing; 8 | 9 | namespace AdamsLair.WinForms.TimelineControls 10 | { 11 | public class TimelineGraphRangeEventArgs : TimelineGraphEventArgs 12 | { 13 | private float beginTime; 14 | private float endTime; 15 | 16 | public float BeginTime 17 | { 18 | get { return this.beginTime; } 19 | } 20 | public float EndTime 21 | { 22 | get { return this.endTime; } 23 | } 24 | 25 | public TimelineGraphRangeEventArgs(ITimelineGraphModel graph, float beginTime, float endTime) : base(graph) 26 | { 27 | this.beginTime = beginTime; 28 | this.endTime = endTime; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /WinForms/ItemModels/IMenuModelItem.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Drawing; 6 | using System.Windows.Forms; 7 | using System.Diagnostics; 8 | 9 | namespace AdamsLair.WinForms.ItemModels 10 | { 11 | public interface IMenuModelItem 12 | { 13 | string FullName { get; } 14 | string Name { get; } 15 | Image Icon { get; } 16 | int SortValue { get; } 17 | object Tag { get; } 18 | Keys ShortcutKeys { get; } 19 | bool Visible { get; } 20 | bool Enabled { get; } 21 | bool Checkable { get; } 22 | bool Checked { get; set; } 23 | MenuItemTypeHint TypeHint { get; } 24 | IMenuModelItem Parent { get; } 25 | IEnumerable Items { get; } 26 | IMenuModel Model { get; } 27 | 28 | void RaisePerformAction(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /WinForms/ItemViews/EventArgs/TiledViewItemEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Drawing; 6 | 7 | using AdamsLair.WinForms.Drawing; 8 | 9 | namespace AdamsLair.WinForms.ItemViews 10 | { 11 | public class TiledViewItemEventArgs : TiledViewEventArgs 12 | { 13 | private int modelIndex; 14 | private object item; 15 | 16 | public int ModelIndex 17 | { 18 | get { return this.modelIndex; } 19 | internal set { this.modelIndex = value; } 20 | } 21 | public object Item 22 | { 23 | get { return this.item; } 24 | internal set { this.item = value; } 25 | } 26 | 27 | public TiledViewItemEventArgs(TiledView view, int modelIndex, object item) : base(view) 28 | { 29 | this.modelIndex = modelIndex; 30 | this.item = item; 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /WinForms/ItemModels/EventArgs/MenuModelItemsEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace AdamsLair.WinForms.ItemModels 7 | { 8 | public class MenuModelItemsEventArgs : EventArgs 9 | { 10 | private IMenuModelItem[] items = null; 11 | private bool sortingAffected = false; 12 | 13 | public IEnumerable Items 14 | { 15 | get { return this.items; } 16 | } 17 | public bool IsSortingAffected 18 | { 19 | get { return this.sortingAffected; } 20 | } 21 | 22 | public MenuModelItemsEventArgs(IEnumerable items, bool affectsSorting = false) 23 | { 24 | if (items == null) items = Enumerable.Empty(); 25 | this.items = items.Distinct().ToArray(); 26 | this.sortingAffected = affectsSorting; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /WinForms/ItemViews/EventArgs/MenuStripMenuViewItemEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Windows.Forms; 6 | 7 | using AdamsLair.WinForms.ItemModels; 8 | 9 | namespace AdamsLair.WinForms.ItemViews 10 | { 11 | public class MenuStripMenuViewItemEventArgs : MenuStripMenuViewEventArgs 12 | { 13 | private IMenuModelItem modelItem = null; 14 | private ToolStripItem viewItem = null; 15 | 16 | public IMenuModelItem Modelitem 17 | { 18 | get { return this.modelItem; } 19 | } 20 | public ToolStripItem ViewItem 21 | { 22 | get { return this.viewItem; } 23 | } 24 | 25 | public MenuStripMenuViewItemEventArgs(IMenuModelItem modelItem, ToolStripItem viewItem, MenuStripMenuView view) : base(view) 26 | { 27 | this.modelItem = modelItem; 28 | this.viewItem = viewItem; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /WinForms/PropertyEditing/PropertyEditors/FlaggedEnumPropertyEditor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Windows.Forms; 5 | using System.Drawing; 6 | 7 | using AdamsLair.WinForms.Drawing; 8 | using AdamsLair.WinForms.PropertyEditing.Templates; 9 | 10 | namespace AdamsLair.WinForms.PropertyEditing.Editors 11 | { 12 | public class FlaggedEnumPropertyEditor : BitmaskPropertyEditor 13 | { 14 | public override object DisplayedValue 15 | { 16 | get { return Enum.ToObject(this.EditedType, Convert.ChangeType(this.BitmaskValue, Enum.GetUnderlyingType(this.EditedType))); } 17 | } 18 | protected override void OnEditedTypeChanged() 19 | { 20 | base.OnEditedTypeChanged(); 21 | this.Items = Enum.GetNames(this.EditedType).Select(n => 22 | new BitmaskItem((ulong)Convert.ToUInt64(Enum.Parse(this.EditedType, n)), n)); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /WinForms/ItemViews/EventArgs/TiledViewItemAppearanceEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Drawing; 6 | 7 | using AdamsLair.WinForms.Drawing; 8 | 9 | namespace AdamsLair.WinForms.ItemViews 10 | { 11 | public class TiledViewItemAppearanceEventArgs : TiledViewItemEventArgs 12 | { 13 | private string text = null; 14 | private Image image = null; 15 | 16 | public string DisplayedText 17 | { 18 | get { return this.text; } 19 | set { this.text = value; } 20 | } 21 | public Image DisplayedImage 22 | { 23 | get { return this.image; } 24 | set { this.image = value; } 25 | } 26 | 27 | internal TiledViewItemAppearanceEventArgs(TiledView view) : this(view, -1, null) {} 28 | public TiledViewItemAppearanceEventArgs(TiledView view, int modelIndex, object item) : base(view, modelIndex, item) {} 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /WinForms/Internal/NativeWinAPI.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Windows.Forms; 6 | 7 | namespace AdamsLair.WinForms.NativeWinAPI 8 | { 9 | public enum WindowMessage : int 10 | { 11 | GetText = 0x000D, 12 | GetTextLength = 0x000E, 13 | Paint = 0x000F, 14 | EraseBackground = 0x0014, 15 | HorizontalScroll = 0x0114, 16 | VerticalScroll = 0x0115 17 | } 18 | [Flags] 19 | public enum ExtendedWindowStyles 20 | { 21 | Composited = 0x02000000, 22 | } 23 | public enum ScrollBarCommands : int 24 | { 25 | LineUp = 0, 26 | LineLeft = 0, 27 | LineDown = 1, 28 | LineRight = 1, 29 | PageUp = 2, 30 | PageLeft = 2, 31 | PageDown = 3, 32 | PageRight = 3, 33 | ThumbPosition = 4, 34 | ThumbTrack = 5, 35 | Top = 6, 36 | Left = 6, 37 | Bottom = 7, 38 | Right = 7, 39 | EndScroll = 8, 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /WinForms/TimelineControls/EventArgs/TimelineViewPaintEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Drawing; 6 | 7 | using AdamsLair.WinForms.Drawing; 8 | 9 | namespace AdamsLair.WinForms.TimelineControls 10 | { 11 | public class TimelineViewPaintEventArgs : TimelineViewEventArgs 12 | { 13 | private Graphics graphics = null; 14 | private Rectangle targetRect = Rectangle.Empty; 15 | 16 | public Graphics Graphics 17 | { 18 | get { return this.graphics; } 19 | } 20 | public TimelineViewControlRenderer Renderer 21 | { 22 | get { return this.View.Renderer; } 23 | } 24 | public Rectangle TargetRect 25 | { 26 | get { return this.targetRect; } 27 | } 28 | 29 | public TimelineViewPaintEventArgs(TimelineView view, Graphics graphics, Rectangle targetRect) : base(view) 30 | { 31 | this.graphics = graphics; 32 | this.targetRect = targetRect; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /WinForms/TimelineControls/EventArgs/TimelineViewCursorEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Drawing; 6 | 7 | using AdamsLair.WinForms.Drawing; 8 | 9 | namespace AdamsLair.WinForms.TimelineControls 10 | { 11 | public class TimelineViewCursorEventArgs : TimelineViewEventArgs 12 | { 13 | private float cursorUnits = 0.0f; 14 | private float lastCursorUnits = 0.0f; 15 | 16 | public float CursorUnits 17 | { 18 | get { return this.cursorUnits; } 19 | } 20 | public float LastCursorUnits 21 | { 22 | get { return this.lastCursorUnits; } 23 | } 24 | public float CursorUnitSpeed 25 | { 26 | get { return this.cursorUnits - this.lastCursorUnits; } 27 | } 28 | 29 | public TimelineViewCursorEventArgs(TimelineView view, float cursorUnits, float lastCursorUnits) : base(view) 30 | { 31 | this.cursorUnits = cursorUnits; 32 | this.lastCursorUnits = lastCursorUnits; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /WinForms/ItemViews/EventArgs/TiledViewItemMouseEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Drawing; 6 | using System.Windows.Forms; 7 | 8 | using AdamsLair.WinForms.Drawing; 9 | 10 | namespace AdamsLair.WinForms.ItemViews 11 | { 12 | public class TiledViewItemMouseEventArgs : TiledViewItemEventArgs 13 | { 14 | private Point location; 15 | private MouseButtons buttons; 16 | 17 | public MouseButtons Buttons 18 | { 19 | get { return this.buttons; } 20 | } 21 | public Point Location 22 | { 23 | get { return this.location; } 24 | } 25 | public int X 26 | { 27 | get { return this.location.X; } 28 | } 29 | public int Y 30 | { 31 | get { return this.location.Y; } 32 | } 33 | 34 | public TiledViewItemMouseEventArgs(TiledView view, int modelIndex, object item, Point location, MouseButtons buttons) : base(view, modelIndex, item) 35 | { 36 | this.location = location; 37 | this.buttons = buttons; 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /WinForms/AdamsLair.WinForms.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | AdamsLair.WinForms 5 | $version$ 6 | Adam 7 | Adam 8 | AdamsLair.WinForms 9 | https://github.com/AdamsLair/winforms 10 | false 11 | A collection of custom Controls for Windows.Forms 12 | A collection of custom Controls for Windows.Forms 13 | Windows.Forms WinForms Controls Timeline PropertyGrid ColorPicker 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Adam 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /TestApp/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.34209 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace AdamsLair.WinForms.TestApp.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /WinForms/TimelineControls/EventArgs/TimelineViewSelectionEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Drawing; 6 | 7 | using AdamsLair.WinForms.Drawing; 8 | 9 | namespace AdamsLair.WinForms.TimelineControls 10 | { 11 | public class TimelineViewSelectionEventArgs : TimelineViewEventArgs 12 | { 13 | private float beginTime = 0.0f; 14 | private float endTime = 0.0f; 15 | private float lastBeginTime = 0.0f; 16 | private float lastEndTime = 0.0f; 17 | 18 | public float BeginTime 19 | { 20 | get { return this.beginTime; } 21 | } 22 | public float EndTime 23 | { 24 | get { return this.endTime; } 25 | } 26 | public bool IsEmpty 27 | { 28 | get { return this.beginTime == this.endTime; } 29 | } 30 | public float LastBeginTime 31 | { 32 | get { return this.lastBeginTime; } 33 | } 34 | public float LastEndTime 35 | { 36 | get { return this.lastEndTime; } 37 | } 38 | public bool WasEmpty 39 | { 40 | get { return this.lastBeginTime == this.lastEndTime; } 41 | } 42 | 43 | public TimelineViewSelectionEventArgs(TimelineView view, float begin, float end, float lastBegin, float lastEnd) : base(view) 44 | { 45 | this.beginTime = begin; 46 | this.endTime = end; 47 | this.lastBeginTime = lastBegin; 48 | this.lastEndTime = lastEnd; 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /AdamsLair.WinForms.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual Studio 2010 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestApp", "TestApp\TestApp.csproj", "{B94AF907-0915-4430-BC49-05BA5091D2AB}" 5 | EndProject 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AdamsLair.WinForms", "WinForms\AdamsLair.WinForms.csproj", "{44E2FD11-C687-41ED-B72F-1A4C92479EDC}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {B94AF907-0915-4430-BC49-05BA5091D2AB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {B94AF907-0915-4430-BC49-05BA5091D2AB}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {B94AF907-0915-4430-BC49-05BA5091D2AB}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {B94AF907-0915-4430-BC49-05BA5091D2AB}.Release|Any CPU.Build.0 = Release|Any CPU 18 | {44E2FD11-C687-41ED-B72F-1A4C92479EDC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 19 | {44E2FD11-C687-41ED-B72F-1A4C92479EDC}.Debug|Any CPU.Build.0 = Debug|Any CPU 20 | {44E2FD11-C687-41ED-B72F-1A4C92479EDC}.Release|Any CPU.ActiveCfg = Release|Any CPU 21 | {44E2FD11-C687-41ED-B72F-1A4C92479EDC}.Release|Any CPU.Build.0 = Release|Any CPU 22 | EndGlobalSection 23 | GlobalSection(SolutionProperties) = preSolution 24 | HideSolutionNode = FALSE 25 | EndGlobalSection 26 | EndGlobal 27 | -------------------------------------------------------------------------------- /WinForms/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // Allgemeine Informationen über eine Assembly werden über die folgenden 6 | // Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern, 7 | // die mit einer Assembly verknüpft sind. 8 | [assembly: AssemblyTitle("AdamsLair.WinForms")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("AdamsLair.WinForms")] 13 | [assembly: AssemblyCopyright("")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Durch Festlegen von ComVisible auf "false" werden die Typen in dieser Assembly unsichtbar 18 | // für COM-Komponenten. Wenn Sie auf einen Typ in dieser Assembly von 19 | // COM zugreifen müssen, legen Sie das ComVisible-Attribut für diesen Typ auf "true" fest. 20 | [assembly: ComVisible(false)] 21 | 22 | // Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird 23 | [assembly: Guid("735ee5dc-8c18-4a06-8e64-2f172ddd01cc")] 24 | 25 | // Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten: 26 | // 27 | // Hauptversion 28 | // Nebenversion 29 | // Buildnummer 30 | // Revision 31 | // 32 | // Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern 33 | // übernehmen, indem Sie "*" eingeben: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.1.17")] 36 | -------------------------------------------------------------------------------- /TestApp/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // Allgemeine Informationen über eine Assembly werden über die folgenden 6 | // Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern, 7 | // die mit einer Assembly verknüpft sind. 8 | [assembly: AssemblyTitle("TestApp")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("TestApp")] 13 | [assembly: AssemblyCopyright("Copyright © 2012")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Durch Festlegen von ComVisible auf "false" werden die Typen in dieser Assembly unsichtbar 18 | // für COM-Komponenten. Wenn Sie auf einen Typ in dieser Assembly von 19 | // COM zugreifen müssen, legen Sie das ComVisible-Attribut für diesen Typ auf "true" fest. 20 | [assembly: ComVisible(false)] 21 | 22 | // Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird 23 | [assembly: Guid("8a9f21fe-76b5-49d2-8a17-6cf8b5e00d8f")] 24 | 25 | // Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten: 26 | // 27 | // Hauptversion 28 | // Nebenversion 29 | // Buildnummer 30 | // Revision 31 | // 32 | // Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern 33 | // übernehmen, indem Sie "*" eingeben: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /WinForms/ItemViews/EventArgs/TiledViewItemDrawEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Drawing; 6 | 7 | using AdamsLair.WinForms.Drawing; 8 | 9 | namespace AdamsLair.WinForms.ItemViews 10 | { 11 | public class TiledViewItemDrawEventArgs : TiledViewItemEventArgs 12 | { 13 | private Graphics graphics; 14 | private Rectangle itemRect; 15 | private bool hovered; 16 | private bool selected; 17 | private bool handled; 18 | 19 | public Graphics Graphics 20 | { 21 | get { return this.graphics; } 22 | internal set { this.graphics = value; } 23 | } 24 | public ControlRenderer Renderer 25 | { 26 | get { return this.View.Renderer; } 27 | } 28 | public Rectangle ItemRect 29 | { 30 | get { return this.itemRect; } 31 | internal set { this.itemRect = value; } 32 | } 33 | public bool IsSelected 34 | { 35 | get { return this.selected; } 36 | internal set { this.selected = value; } 37 | } 38 | public bool IsHovered 39 | { 40 | get { return this.hovered; } 41 | internal set { this.hovered = value; } 42 | } 43 | public bool Handled 44 | { 45 | get { return this.handled; } 46 | set { this.handled = true; } 47 | } 48 | 49 | internal TiledViewItemDrawEventArgs(TiledView view) : this(view, -1, null, null, Rectangle.Empty, false, false) {} 50 | public TiledViewItemDrawEventArgs(TiledView view, int modelIndex, object item, Graphics graphics, Rectangle itemRect, bool selected, bool hovered) : base(view, modelIndex, item) 51 | { 52 | this.graphics = graphics; 53 | this.itemRect = itemRect; 54 | this.selected = selected; 55 | this.hovered = hovered; 56 | this.handled = false; 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Build Folders (you can keep bin if you'd like, to store dlls and pdbs) 2 | [Bb]in/ 3 | [Oo]bj/ 4 | 5 | # mstest test results 6 | TestResults 7 | 8 | ## Ignore Visual Studio temporary files, build results, and 9 | ## files generated by popular Visual Studio add-ons. 10 | 11 | # User-specific files 12 | *.suo 13 | *.user 14 | *.sln.docstates 15 | /.vs 16 | 17 | # Build results 18 | [Dd]ebug/ 19 | [Rr]elease/ 20 | x64/ 21 | *_i.c 22 | *_p.c 23 | *.ilk 24 | *.meta 25 | *.obj 26 | *.pch 27 | *.pdb 28 | *.pgc 29 | *.pgd 30 | *.rsp 31 | *.sbr 32 | *.tlb 33 | *.tli 34 | *.tlh 35 | *.tmp 36 | *.log 37 | *.vspscc 38 | *.vssscc 39 | .builds 40 | 41 | # Visual C++ cache files 42 | ipch/ 43 | *.aps 44 | *.ncb 45 | *.opensdf 46 | *.sdf 47 | 48 | # Visual Studio profiler 49 | *.psess 50 | *.vsp 51 | *.vspx 52 | 53 | # Guidance Automation Toolkit 54 | *.gpState 55 | 56 | # ReSharper is a .NET coding add-in 57 | _ReSharper* 58 | 59 | # NCrunch 60 | *.ncrunch* 61 | .*crunch*.local.xml 62 | 63 | # Installshield output folder 64 | [Ee]xpress 65 | 66 | # DocProject is a documentation generator add-in 67 | DocProject/buildhelp/ 68 | DocProject/Help/*.HxT 69 | DocProject/Help/*.HxC 70 | DocProject/Help/*.hhc 71 | DocProject/Help/*.hhk 72 | DocProject/Help/*.hhp 73 | DocProject/Help/Html2 74 | DocProject/Help/html 75 | 76 | # Click-Once directory 77 | publish 78 | 79 | # Publish Web Output 80 | *.Publish.xml 81 | 82 | # NuGet Packages Directory 83 | packages 84 | 85 | # Windows Azure Build Output 86 | csx 87 | *.build.csdef 88 | 89 | # Windows Store app package directory 90 | AppPackages/ 91 | 92 | # Others 93 | [Bb]in 94 | [Oo]bj 95 | sql 96 | TestResults 97 | [Tt]est[Rr]esult* 98 | *.Cache 99 | ClientBin 100 | [Ss]tyle[Cc]op.* 101 | ~$* 102 | *.dbmdl 103 | Generated_Code #added for RIA/Silverlight projects 104 | 105 | # Backup & report files from converting an old project file to a newer 106 | # Visual Studio version. Backup files are not needed, because we have git ;-) 107 | _UpgradeReport_Files/ 108 | Backup*/ 109 | UpgradeLog*.XML 110 | WinForms/AdamsLair.WinForms.xml 111 | -------------------------------------------------------------------------------- /WinForms/Properties/ResourcesCache.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Drawing; 6 | using System.Reflection; 7 | 8 | namespace AdamsLair.WinForms.Properties 9 | { 10 | public static class ResourcesCache 11 | { 12 | public readonly static Bitmap ImageAdd = Resources.ImageAdd; 13 | public readonly static Bitmap ImageDelete = Resources.ImageDelete; 14 | public readonly static Bitmap NumberGripIcon = Resources.NumberGripIcon; 15 | public readonly static Bitmap DropDownIcon = Resources.DropDownIcon; 16 | public readonly static Bitmap ExpandNodeClosedDisabled = Resources.ExpandNodeClosedDisabled; 17 | public readonly static Bitmap ExpandNodeClosedNormal = Resources.ExpandNodeClosedNormal; 18 | public readonly static Bitmap ExpandNodeClosedHot = Resources.ExpandNodeClosedHot; 19 | public readonly static Bitmap ExpandNodeClosedPressed = Resources.ExpandNodeClosedPressed; 20 | public readonly static Bitmap ExpandNodeOpenedDisabled = Resources.ExpandNodeOpenedDisabled; 21 | public readonly static Bitmap ExpandNodeOpenedNormal = Resources.ExpandNodeOpenedNormal; 22 | public readonly static Bitmap ExpandNodeOpenedHot = Resources.ExpandNodeOpenedHot; 23 | public readonly static Bitmap ExpandNodeOpenedPressed = Resources.ExpandNodeOpenedPressed; 24 | public readonly static Bitmap ArrowDown = Resources.ArrowDown; 25 | public readonly static Bitmap ArrowDownLeft = Resources.ArrowDownLeft; 26 | public readonly static Bitmap ArrowDownRight = Resources.ArrowDownRight; 27 | public readonly static Bitmap ArrowUp = Resources.ArrowUp; 28 | public readonly static Bitmap ArrowUpLeft = Resources.ArrowUpLeft; 29 | public readonly static Bitmap ArrowUpRight = Resources.ArrowUpRight; 30 | public readonly static Bitmap ArrowLeft = Resources.ArrowLeft; 31 | public readonly static Bitmap ArrowRight = Resources.ArrowRight; 32 | 33 | public readonly static Font DefaultFont = SystemFonts.DefaultFont; 34 | public readonly static Font DefaultFontSmall = new Font(DefaultFont.FontFamily, DefaultFont.Size * 0.9f, DefaultFont.Unit); 35 | public readonly static Font DefaultFontBold = new Font(DefaultFont, FontStyle.Bold); 36 | public readonly static Font DefaultFontBoldSmall = new Font(DefaultFontSmall, FontStyle.Bold); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /WinForms/TimelineControls/EventArgs/TimelineViewTrackPaintEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Drawing; 6 | 7 | using AdamsLair.WinForms.Drawing; 8 | 9 | namespace AdamsLair.WinForms.TimelineControls 10 | { 11 | public class TimelineViewTrackPaintEventArgs : TimelineViewTrackEventArgs 12 | { 13 | private Graphics graphics = null; 14 | private Rectangle targetRect = Rectangle.Empty; 15 | private float beginTime = 0.0f; 16 | private float endTime = 0.0f; 17 | private QualityLevel qualityHint = QualityLevel.High; 18 | 19 | 20 | public Graphics Graphics 21 | { 22 | get { return this.graphics; } 23 | } 24 | public TimelineViewControlRenderer Renderer 25 | { 26 | get { return this.View.Renderer; } 27 | } 28 | public QualityLevel QualityHint 29 | { 30 | get { return this.qualityHint; } 31 | } 32 | /// 33 | /// [GET] The rectangular area that is occupied by the track that is currently painted. It won't be 34 | /// altered due to clipping and partial repaints, and can be safely relied upon for determining 35 | /// drawing geometry. 36 | /// 37 | public Rectangle TargetRect 38 | { 39 | get { return this.targetRect; } 40 | } 41 | /// 42 | /// [GET] The begin of the currently painted timespan. This value may be altered due to clipping and 43 | /// partial repaints, and does not reflect the tracks or track contents actual begin. 44 | /// 45 | public float BeginTime 46 | { 47 | get { return this.beginTime; } 48 | } 49 | /// 50 | /// [GET] The end of the currently painted timespan. This value may be altered due to clipping and 51 | /// partial repaints, and does not reflect the tracks or track contents actual end. 52 | /// 53 | public float EndTime 54 | { 55 | get { return this.endTime; } 56 | } 57 | 58 | 59 | public TimelineViewTrackPaintEventArgs(TimelineViewTrack track, Graphics graphics, QualityLevel qualityHint, Rectangle targetRect) : this(track, graphics, qualityHint, targetRect, track.ContentBeginTime, track.ContentEndTime) {} 60 | public TimelineViewTrackPaintEventArgs(TimelineViewTrack track, Graphics graphics, QualityLevel qualityHint, Rectangle targetRect, float beginTime, float endTime) : base(track) 61 | { 62 | this.graphics = graphics; 63 | this.targetRect = targetRect; 64 | this.qualityHint = qualityHint; 65 | this.beginTime = beginTime; 66 | this.endTime = endTime; 67 | } 68 | 69 | public QualityLevel GetAdjustedQuality(QualityLevel baseLevel) 70 | { 71 | return (QualityLevel)Math.Min((int)baseLevel, (int)this.qualityHint); 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /WinForms/TimelineControls/Models/TimelineGraphTrackModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace AdamsLair.WinForms.TimelineControls 7 | { 8 | public class TimelineGraphTrackModel : TimelineTrackModel, ITimelineGraphTrackModel 9 | { 10 | private List graphs = new List(); 11 | 12 | public event EventHandler GraphsAdded; 13 | public event EventHandler GraphsRemoved; 14 | public event EventHandler GraphChanged; 15 | 16 | public override float EndTime 17 | { 18 | get { return this.graphs.Max(g => g.EndTime); } 19 | } 20 | public override float BeginTime 21 | { 22 | get { return this.graphs.Min(g => g.BeginTime); } 23 | } 24 | public IEnumerable Graphs 25 | { 26 | get { return this.graphs; } 27 | } 28 | 29 | public void Add(ITimelineGraphModel graph) 30 | { 31 | this.AddRange(new[] { graph }); 32 | } 33 | public void AddRange(IEnumerable graphs) 34 | { 35 | graphs = graphs.Where(t => !this.graphs.Contains(t)).Distinct().ToArray(); 36 | if (!graphs.Any()) return; 37 | 38 | foreach (ITimelineGraphModel graph in graphs) 39 | { 40 | graph.GraphChanged += this.graph_GraphChanged; 41 | } 42 | this.graphs.AddRange(graphs); 43 | 44 | if (this.GraphsAdded != null) 45 | this.GraphsAdded(this, new TimelineGraphCollectionEventArgs(graphs)); 46 | } 47 | public void Remove(ITimelineGraphModel graph) 48 | { 49 | this.RemoveRange(new[] { graph }); 50 | } 51 | public void RemoveRange(IEnumerable graphs) 52 | { 53 | graphs = graphs.Where(t => this.graphs.Contains(t)).Distinct().ToArray(); 54 | if (!graphs.Any()) return; 55 | 56 | foreach (ITimelineGraphModel graph in graphs) 57 | { 58 | graph.GraphChanged -= this.graph_GraphChanged; 59 | this.graphs.Remove(graph); 60 | } 61 | 62 | if (this.GraphsRemoved != null) 63 | this.GraphsRemoved(this, new TimelineGraphCollectionEventArgs(graphs)); 64 | } 65 | public void Clear() 66 | { 67 | ITimelineGraphModel[] oldGraphs = this.graphs.ToArray(); 68 | 69 | foreach (ITimelineGraphModel graph in this.graphs) 70 | { 71 | graph.GraphChanged -= this.graph_GraphChanged; 72 | } 73 | this.graphs.Clear(); 74 | 75 | if (this.GraphsRemoved != null) 76 | this.GraphsRemoved(this, new TimelineGraphCollectionEventArgs(oldGraphs)); 77 | } 78 | 79 | private void graph_GraphChanged(object sender, TimelineGraphRangeEventArgs e) 80 | { 81 | if (this.GraphChanged != null) 82 | this.GraphChanged(this, e); 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /WinForms/ItemViews/TiledViewTextItemEditor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Windows.Forms; 6 | using System.Drawing; 7 | using System.Reflection; 8 | 9 | using AdamsLair.WinForms.Drawing; 10 | using AdamsLair.WinForms.ItemModels; 11 | 12 | namespace AdamsLair.WinForms.ItemViews 13 | { 14 | public class TiledViewTextItemEditor : TextBox, ITiledViewItemEditor 15 | { 16 | private string editedPropertyName = null; 17 | private bool accepted = false; 18 | 19 | public event EventHandler StopEditing = null; 20 | 21 | public string EditedPropertyName 22 | { 23 | get { return this.editedPropertyName; } 24 | set { this.editedPropertyName = value; } 25 | } 26 | Control ITiledViewItemEditor.MainControl 27 | { 28 | get { return this; } 29 | } 30 | bool ITiledViewItemEditor.IsAcceptingValue 31 | { 32 | get { return this.accepted; } 33 | } 34 | 35 | void ITiledViewItemEditor.GetValueFromItem(object item) 36 | { 37 | if (string.IsNullOrEmpty(this.editedPropertyName)) return; 38 | if (item == null) return; 39 | 40 | Type itemType = item.GetType(); 41 | PropertyInfo property = itemType.GetProperty(this.editedPropertyName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); 42 | if (property == null) return; 43 | if (property.PropertyType != typeof(string)) return; 44 | 45 | string val = property.GetValue(item, null) as string; 46 | this.Text = val; 47 | } 48 | bool ITiledViewItemEditor.ApplyValueToItem(object item) 49 | { 50 | if (string.IsNullOrEmpty(this.editedPropertyName)) return true; 51 | if (item == null) return true; 52 | 53 | Type itemType = item.GetType(); 54 | PropertyInfo property = itemType.GetProperty(this.editedPropertyName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); 55 | if (property == null) return true; 56 | if (property.PropertyType != typeof(string)) return true; 57 | 58 | property.SetValue(item, this.Text, null); 59 | return true; 60 | } 61 | 62 | private void Accept() 63 | { 64 | this.accepted = true; 65 | if (this.StopEditing != null) this.StopEditing(this, EventArgs.Empty); 66 | } 67 | private void Reject() 68 | { 69 | this.accepted = false; 70 | if (this.StopEditing != null) this.StopEditing(this, EventArgs.Empty); 71 | } 72 | 73 | protected override void OnKeyDown(KeyEventArgs e) 74 | { 75 | base.OnKeyDown(e); 76 | if (e.KeyCode == Keys.Escape) 77 | this.Reject(); 78 | else if (e.KeyCode == Keys.Return) 79 | this.Accept(); 80 | } 81 | protected override void OnLostFocus(EventArgs e) 82 | { 83 | base.OnLostFocus(e); 84 | this.Accept(); 85 | } 86 | protected override void Dispose(bool disposing) 87 | { 88 | base.Dispose(disposing); 89 | this.Reject(); 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /WinForms/PropertyEditing/EditorTemplates/ComboBoxDropDown.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Drawing; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Windows.Forms; 8 | 9 | namespace AdamsLair.WinForms.PropertyEditing.Templates 10 | { 11 | public partial class ComboBoxDropDown : ListBox 12 | { 13 | private bool openedWithCtrl = false; 14 | private int hoveredIndex = -1; 15 | 16 | public event EventHandler AcceptSelection = null; 17 | public event EventHandler RequestClose = null; 18 | 19 | public int HoveredIndex 20 | { 21 | get { return this.hoveredIndex; } 22 | } 23 | 24 | public ComboBoxDropDown() 25 | { 26 | this.IntegralHeight = false; 27 | this.Font = this.Font; // Prevents parent PopupControl from interfering on resize. 28 | } 29 | public ComboBoxDropDown(IEnumerable items) : this() 30 | { 31 | this.Items.AddRange(items.ToArray()); 32 | } 33 | 34 | protected void Accept() 35 | { 36 | if (this.AcceptSelection != null) this.AcceptSelection(this, EventArgs.Empty); 37 | } 38 | protected void Close() 39 | { 40 | if (this.RequestClose != null) this.RequestClose(this, EventArgs.Empty); 41 | } 42 | 43 | protected override void OnGotFocus(EventArgs e) 44 | { 45 | base.OnGotFocus(e); 46 | this.openedWithCtrl = (Control.ModifierKeys & Keys.Control) == Keys.Control; 47 | } 48 | protected override void OnClick(EventArgs e) 49 | { 50 | base.OnClick(e); 51 | if (this.SelectionMode == SelectionMode.One) 52 | { 53 | this.Accept(); 54 | this.Close(); 55 | } 56 | } 57 | protected override void OnKeyDown(KeyEventArgs e) 58 | { 59 | base.OnKeyDown(e); 60 | if (e.KeyCode == Keys.Return || e.KeyCode == Keys.Left) 61 | { 62 | this.Accept(); 63 | this.Close(); 64 | } 65 | else if (e.KeyCode == Keys.C && e.Control) 66 | { 67 | if (this.SelectedItem != null) 68 | Clipboard.SetText(this.SelectedItem.ToString()); 69 | } 70 | else if (e.KeyCode == Keys.Back || e.KeyCode == Keys.Escape) 71 | { 72 | this.Close(); 73 | } 74 | } 75 | protected override void OnKeyUp(KeyEventArgs e) 76 | { 77 | base.OnKeyUp(e); 78 | if (e.KeyCode == Keys.ControlKey && this.openedWithCtrl) 79 | { 80 | this.Accept(); 81 | this.Close(); 82 | } 83 | } 84 | protected override void OnMouseMove(MouseEventArgs e) 85 | { 86 | base.OnMouseMove(e); 87 | int clientY = e.Y - this.ClientRectangle.Y; 88 | this.hoveredIndex = (clientY / this.ItemHeight) + this.TopIndex; 89 | if (this.hoveredIndex < 0 || this.hoveredIndex >= this.Items.Count) this.hoveredIndex = -1; 90 | } 91 | protected override void OnMouseLeave(EventArgs e) 92 | { 93 | base.OnMouseLeave(e); 94 | this.hoveredIndex = -1; 95 | } 96 | protected override void OnSelectedIndexChanged(EventArgs e) 97 | { 98 | base.OnSelectedIndexChanged(e); 99 | if (this.openedWithCtrl) this.Accept(); 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /WinForms/Internal/ExtMethodsColor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | 4 | namespace AdamsLair.WinForms 5 | { 6 | internal static class ExtMethodsColor 7 | { 8 | public static Color ScaleBrightness(this Color c, float ratio) 9 | { 10 | return Color.FromArgb(c.A, 11 | (byte)Math.Min(Math.Max((float)c.R * ratio, 0.0f), 255.0f), 12 | (byte)Math.Min(Math.Max((float)c.G * ratio, 0.0f), 255.0f), 13 | (byte)Math.Min(Math.Max((float)c.B * ratio, 0.0f), 255.0f)); 14 | } 15 | public static Color ScaleAlpha(this Color c, float ratio) 16 | { 17 | return Color.FromArgb((byte)((float)c.A * ratio), c); 18 | } 19 | public static Color MixWith(this Color c, Color other, float ratio, bool lockBrightness = false) 20 | { 21 | float myRatio = 1.0f - ratio; 22 | if (lockBrightness) 23 | { 24 | int oldBrightness = Math.Max(c.R, Math.Max(c.G, c.B)); 25 | int newBrightness = Math.Max(other.R, Math.Max(other.G, other.B)); 26 | other = other.ScaleBrightness((float)oldBrightness / (float)newBrightness); 27 | } 28 | return Color.FromArgb(c.A, 29 | (byte)Math.Min(Math.Max((float)c.R * myRatio + (float)other.R * ratio, 0.0f), 255.0f), 30 | (byte)Math.Min(Math.Max((float)c.G * myRatio + (float)other.G * ratio, 0.0f), 255.0f), 31 | (byte)Math.Min(Math.Max((float)c.B * myRatio + (float)other.B * ratio, 0.0f), 255.0f)); 32 | } 33 | 34 | public static float GetLuminance(this Color color) 35 | { 36 | return (0.2126f * color.R + 0.7152f * color.G + 0.0722f * color.B) / 255.0f; 37 | } 38 | public static float GetHSVHue(this Color color) 39 | { 40 | return color.GetHue() / 360.0f; 41 | } 42 | public static float GetHSVBrightness(this Color color) 43 | { 44 | return Math.Max(Math.Max(color.R, color.G), color.B) / 255.0f; 45 | } 46 | public static float GetHSVSaturation(this Color color) 47 | { 48 | int max = Math.Max(color.R, Math.Max(color.G, color.B)); 49 | int min = Math.Min(color.R, Math.Min(color.G, color.B)); 50 | 51 | return (max == 0) ? 0.0f : 1.0f - (1.0f * (float)min / (float)max); 52 | } 53 | 54 | public static Color ColorFromHSV(float hue, float saturation, float value) 55 | { 56 | hue *= 360.0f; 57 | hue = (hue + 360.0f) % 360.0f; 58 | saturation = Math.Min(Math.Max(saturation, 0.0f), 1.0f); 59 | value = Math.Min(Math.Max(value, 0.0f), 1.0f); 60 | 61 | int hi = Convert.ToInt32(Math.Floor(hue / 60)) % 6; 62 | double f = hue / 60 - Math.Floor(hue / 60); 63 | 64 | value = value * 255; 65 | int v = Convert.ToInt32(value); 66 | int p = Convert.ToInt32(value * (1 - saturation)); 67 | int q = Convert.ToInt32(value * (1 - f * saturation)); 68 | int t = Convert.ToInt32(value * (1 - (1 - f) * saturation)); 69 | 70 | if (hi == 0) 71 | return Color.FromArgb(255, v, t, p); 72 | else if (hi == 1) 73 | return Color.FromArgb(255, q, v, p); 74 | else if (hi == 2) 75 | return Color.FromArgb(255, p, v, t); 76 | else if (hi == 3) 77 | return Color.FromArgb(255, p, q, v); 78 | else if (hi == 4) 79 | return Color.FromArgb(255, t, p, v); 80 | else 81 | return Color.FromArgb(255, v, p, q); 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /WinForms/PropertyEditing/EditorTemplates/MultiComboBoxDropDown.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Drawing; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Windows.Forms; 8 | 9 | namespace AdamsLair.WinForms.PropertyEditing.Templates 10 | { 11 | public partial class MultiComboBoxDropDown : CheckedListBox 12 | { 13 | private bool openedWithCtrl = false; 14 | private int hoveredIndex = -1; 15 | 16 | public event EventHandler AcceptSelection = null; 17 | public event EventHandler RequestClose = null; 18 | 19 | public int HoveredIndex 20 | { 21 | get { return this.hoveredIndex; } 22 | } 23 | 24 | public MultiComboBoxDropDown() 25 | { 26 | this.IntegralHeight = false; 27 | this.CheckOnClick = true; 28 | this.Font = this.Font; // Prevents parent PopupControl from interfering on resize. 29 | } 30 | public MultiComboBoxDropDown(IEnumerable items) : this() 31 | { 32 | this.Items.AddRange(items.ToArray()); 33 | } 34 | 35 | protected void Accept() 36 | { 37 | if (this.AcceptSelection != null) 38 | this.AcceptSelection(this, EventArgs.Empty); 39 | } 40 | protected void Close() 41 | { 42 | if (this.RequestClose != null) this.RequestClose(this, EventArgs.Empty); 43 | } 44 | 45 | protected override void OnGotFocus(EventArgs e) 46 | { 47 | base.OnGotFocus(e); 48 | this.openedWithCtrl = (Control.ModifierKeys & Keys.Control) == Keys.Control; 49 | } 50 | protected override void OnKeyDown(KeyEventArgs e) 51 | { 52 | base.OnKeyDown(e); 53 | if (e.KeyCode == Keys.Return) 54 | { 55 | int index = this.SelectedIndex; 56 | if (index != -1) this.SetItemChecked(index, !this.GetItemChecked(index)); 57 | } 58 | else if (e.KeyCode == Keys.C && e.Control) 59 | { 60 | if (this.SelectedItem != null) 61 | Clipboard.SetText(this.SelectedItem.ToString()); 62 | } 63 | else if (e.KeyCode == Keys.Back || e.KeyCode == Keys.Left || e.KeyCode == Keys.Escape) 64 | { 65 | this.Accept(); 66 | this.Close(); 67 | } 68 | } 69 | protected override void OnKeyUp(KeyEventArgs e) 70 | { 71 | base.OnKeyUp(e); 72 | if (e.KeyCode == Keys.ControlKey && this.openedWithCtrl) 73 | { 74 | this.Accept(); 75 | this.Close(); 76 | } 77 | } 78 | protected override void OnMouseMove(MouseEventArgs e) 79 | { 80 | base.OnMouseMove(e); 81 | int clientY = e.Y - this.ClientRectangle.Y; 82 | this.hoveredIndex = (clientY / this.ItemHeight) + this.TopIndex; 83 | if (this.hoveredIndex < 0 || this.hoveredIndex >= base.Items.Count) this.hoveredIndex = -1; 84 | } 85 | protected override void OnMouseLeave(EventArgs e) 86 | { 87 | base.OnMouseLeave(e); 88 | this.hoveredIndex = -1; 89 | } 90 | protected override void OnItemCheck(ItemCheckEventArgs ice) 91 | { 92 | base.OnItemCheck(ice); 93 | if (this.IsHandleCreated) 94 | { 95 | // Delay execution until item actually checked 96 | this.BeginInvoke((MethodInvoker)(() => this.Accept())); 97 | } 98 | } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /WinForms/TimelineControls/Models/TimelineModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace AdamsLair.WinForms.TimelineControls 7 | { 8 | public class TimelineModel : ITimelineModel 9 | { 10 | private string unitName = "Seconds"; 11 | private string unitDescription = "Time"; 12 | private float unitBaseScale = 1.0f; 13 | private List trackList = new List(); 14 | 15 | public event EventHandler UnitChanged; 16 | public event EventHandler TracksAdded; 17 | public event EventHandler TracksRemoved; 18 | 19 | public string UnitName 20 | { 21 | get { return this.unitName; } 22 | set 23 | { 24 | if (this.unitName != value) 25 | { 26 | this.unitName = value; 27 | if (this.UnitChanged != null) 28 | this.UnitChanged(this, EventArgs.Empty); 29 | } 30 | } 31 | } 32 | public string UnitDescription 33 | { 34 | get { return this.unitDescription; } 35 | set 36 | { 37 | if (this.unitDescription != value) 38 | { 39 | this.unitDescription = value; 40 | if (this.UnitChanged != null) 41 | this.UnitChanged(this, EventArgs.Empty); 42 | } 43 | } 44 | } 45 | public float UnitBaseScale 46 | { 47 | get { return this.unitBaseScale; } 48 | set 49 | { 50 | if (this.unitBaseScale != value) 51 | { 52 | this.unitBaseScale = value; 53 | if (this.UnitChanged != null) 54 | this.UnitChanged(this, EventArgs.Empty); 55 | } 56 | } 57 | } 58 | public IEnumerable Tracks 59 | { 60 | get { return this.trackList; } 61 | } 62 | 63 | public void Add(ITimelineTrackModel track) 64 | { 65 | this.AddRange(new[] { track }); 66 | } 67 | public void AddRange(IEnumerable tracks) 68 | { 69 | tracks = tracks.Where(t => !this.trackList.Contains(t)).Distinct().ToArray(); 70 | if (!tracks.Any()) return; 71 | 72 | this.trackList.AddRange(tracks); 73 | 74 | if (this.TracksAdded != null) 75 | this.TracksAdded(this, new TimelineTrackModelCollectionEventArgs(tracks)); 76 | } 77 | public void Remove(ITimelineTrackModel track) 78 | { 79 | this.RemoveRange(new[] { track }); 80 | } 81 | public void RemoveRange(IEnumerable tracks) 82 | { 83 | tracks = tracks.Where(t => this.trackList.Contains(t)).Distinct().ToArray(); 84 | if (!tracks.Any()) return; 85 | 86 | foreach (ITimelineTrackModel track in tracks) 87 | { 88 | this.trackList.Remove(track); 89 | } 90 | 91 | if (this.TracksRemoved != null) 92 | this.TracksRemoved(this, new TimelineTrackModelCollectionEventArgs(tracks)); 93 | } 94 | public void Clear() 95 | { 96 | TimelineTrackModelCollectionEventArgs args = new TimelineTrackModelCollectionEventArgs(this.trackList); 97 | 98 | this.trackList.Clear(); 99 | 100 | if (this.TracksRemoved != null) 101 | this.TracksRemoved(this, args); 102 | } 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /WinForms/PropertyEditing/EditorTemplates/EditorTemplate.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Windows.Forms; 5 | using System.Drawing; 6 | 7 | using AdamsLair.WinForms.Drawing; 8 | 9 | namespace AdamsLair.WinForms.PropertyEditing.Templates 10 | { 11 | public abstract class EditorTemplate 12 | { 13 | protected PropertyEditor parent = null; 14 | protected Rectangle rect = Rectangle.Empty; 15 | protected bool readOnly = true; 16 | protected bool hovered = false; 17 | protected bool focused = false; 18 | 19 | public event EventHandler Invalidate = null; 20 | public event EventHandler Edited = null; 21 | public event EventHandler EditingFinished = null; 22 | 23 | public virtual Rectangle Rect 24 | { 25 | get { return this.rect; } 26 | set { this.rect = value; } 27 | } 28 | public virtual bool ReadOnly 29 | { 30 | get { return this.readOnly; } 31 | set { this.readOnly = value; } 32 | } 33 | public PropertyEditor Parent 34 | { 35 | get { return this.parent; } 36 | } 37 | public bool Focused 38 | { 39 | get { return this.focused; } 40 | } 41 | public bool Hovered 42 | { 43 | get { return this.hovered; } 44 | } 45 | public Cursor CurrentCursor 46 | { 47 | get { return (this.parent != null && this.parent.ParentGrid != null) ? this.parent.ParentGrid.Cursor : Cursors.Default; } 48 | set 49 | { 50 | if (this.parent == null) return; 51 | if (this.parent.ParentGrid == null) return; 52 | this.parent.ParentGrid.Cursor = value ?? Cursors.Default; 53 | } 54 | } 55 | protected ControlRenderer ControlRenderer 56 | { 57 | get { return this.parent.ControlRenderer; } 58 | } 59 | 60 | public EditorTemplate(PropertyEditor parent) 61 | { 62 | this.parent = parent; 63 | } 64 | 65 | public virtual void OnGotFocus(EventArgs e) 66 | { 67 | this.focused = true; 68 | } 69 | public virtual void OnLostFocus(EventArgs e) 70 | { 71 | this.focused = false; 72 | } 73 | public virtual void OnMouseMove(MouseEventArgs e) 74 | { 75 | bool lastHovered = this.hovered; 76 | this.hovered = new Rectangle(this.rect.X + 2, this.rect.Y, this.rect.Width - 4, this.rect.Height).Contains(e.Location); 77 | if (lastHovered != this.hovered) this.EmitInvalidate(); 78 | } 79 | public virtual void OnMouseLeave(EventArgs e) 80 | { 81 | if (this.hovered) this.EmitInvalidate(); 82 | this.hovered = false; 83 | } 84 | 85 | protected void EmitInvalidate() 86 | { 87 | if (this.Invalidate != null) 88 | this.Invalidate(this, EventArgs.Empty); 89 | } 90 | protected void EmitEdited(object value) 91 | { 92 | if (this.Edited != null) 93 | this.Edited(this, new PropertyEditorValueEventArgs(this.parent, value)); 94 | } 95 | protected void EmitEditingFinished(object value, FinishReason reason) 96 | { 97 | if (this.EditingFinished != null) 98 | this.EditingFinished(this, new PropertyEditingFinishedEventArgs(this.parent, value, reason)); 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /WinForms/ColorControls/ColorShowBox.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Forms; 3 | using System.Drawing; 4 | using System.Drawing.Drawing2D; 5 | 6 | using AdamsLair.WinForms.Drawing; 7 | 8 | namespace AdamsLair.WinForms.ColorControls 9 | { 10 | public class ColorShowBox : Control 11 | { 12 | private ControlRenderer renderer = new ControlRenderer(); 13 | private Color upperColor = Color.Transparent; 14 | private Color lowerColor = Color.Transparent; 15 | 16 | 17 | public event EventHandler UpperClick = null; 18 | public event EventHandler LowerClick = null; 19 | 20 | 21 | public ControlRenderer Renderer 22 | { 23 | get { return this.renderer; } 24 | } 25 | public Rectangle ColorAreaRectangle 26 | { 27 | get { return new Rectangle( 28 | this.ClientRectangle.X + 2, 29 | this.ClientRectangle.Y + 2, 30 | this.ClientRectangle.Width - 4, 31 | this.ClientRectangle.Height - 4); } 32 | } 33 | public Color Color 34 | { 35 | get { return this.upperColor; } 36 | set { this.upperColor = this.lowerColor = value; this.Invalidate(); } 37 | } 38 | public Color UpperColor 39 | { 40 | get { return this.upperColor; } 41 | set { this.upperColor = value; this.Invalidate(); } 42 | } 43 | public Color LowerColor 44 | { 45 | get { return this.lowerColor; } 46 | set { this.lowerColor = value; this.Invalidate(); } 47 | } 48 | 49 | 50 | public ColorShowBox() 51 | { 52 | this.DoubleBuffered = true; 53 | this.SetStyle(ControlStyles.UserPaint, true); 54 | this.SetStyle(ControlStyles.AllPaintingInWmPaint, true); 55 | this.SetStyle(ControlStyles.Opaque, true); 56 | this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true); 57 | this.SetStyle(ControlStyles.ResizeRedraw, true); 58 | } 59 | 60 | protected void OnUpperClick() 61 | { 62 | if (this.UpperClick != null) 63 | this.UpperClick(this, null); 64 | } 65 | protected void OnLowerClick() 66 | { 67 | if (this.LowerClick != null) 68 | this.LowerClick(this, null); 69 | } 70 | 71 | protected override void OnMouseClick(MouseEventArgs e) 72 | { 73 | base.OnMouseClick(e); 74 | if (e.Y > (this.ClientRectangle.Top + this.ClientRectangle.Bottom) / 2) 75 | this.OnLowerClick(); 76 | else 77 | this.OnUpperClick(); 78 | } 79 | protected override void OnPaint(PaintEventArgs e) 80 | { 81 | base.OnPaint(e); 82 | 83 | Rectangle colorArea = this.ColorAreaRectangle; 84 | 85 | if (this.lowerColor.A < 255 || this.upperColor.A < 255) 86 | e.Graphics.FillRectangle(new HatchBrush(HatchStyle.LargeCheckerBoard, this.renderer.ColorLightBackground, this.renderer.ColorDarkBackground), colorArea); 87 | 88 | e.Graphics.FillRectangle(new SolidBrush(this.upperColor), 89 | colorArea.X, 90 | colorArea.Y, 91 | colorArea.Width, 92 | colorArea.Height / 2 + 1); 93 | e.Graphics.FillRectangle(new SolidBrush(this.lowerColor), 94 | colorArea.X, 95 | colorArea.Y + colorArea.Height / 2 + 1, 96 | colorArea.Width, 97 | colorArea.Height / 2); 98 | 99 | this.renderer.DrawBorder(e.Graphics, this.ClientRectangle, Drawing.BorderStyle.ContentBox, BorderState.Normal); 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /TestApp/TimelineFunctionGraphModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | using AdamsLair.WinForms.TimelineControls; 7 | 8 | namespace AdamsLair.WinForms.TestApp 9 | { 10 | public class TimelineFunctionGraphModel : ITimelineGraphModel 11 | { 12 | public delegate float EnvelopeFunc(float begin, float end); 13 | public delegate float ValueFunc(float x); 14 | 15 | private ValueFunc func; 16 | private EnvelopeFunc maxFunc; 17 | private EnvelopeFunc minFunc; 18 | private float begin; 19 | private float end; 20 | 21 | public event EventHandler GraphChanged; 22 | 23 | public float EndTime 24 | { 25 | get { return this.end; } 26 | set 27 | { 28 | if (this.end != value) 29 | { 30 | float oldEnd = this.end; 31 | this.end = value; 32 | this.RaiseGraphChanged(Math.Min(oldEnd, this.end), Math.Max(oldEnd, this.end)); 33 | } 34 | } 35 | } 36 | public float BeginTime 37 | { 38 | get { return this.begin; } 39 | set 40 | { 41 | if (this.begin != value) 42 | { 43 | float oldBegin = this.begin; 44 | this.begin = value; 45 | this.RaiseGraphChanged(Math.Min(oldBegin, this.begin), Math.Max(oldBegin, this.begin)); 46 | } 47 | } 48 | } 49 | public ValueFunc Function 50 | { 51 | get { return this.func; } 52 | set 53 | { 54 | if (this.func != value) 55 | { 56 | this.func = value; 57 | this.RaiseGraphChanged(this.begin, this.end); 58 | } 59 | } 60 | } 61 | public EnvelopeFunc EnvelopeMaxFunction 62 | { 63 | get { return this.maxFunc; } 64 | set 65 | { 66 | if (this.maxFunc != value) 67 | { 68 | this.maxFunc = value; 69 | this.RaiseGraphChanged(this.begin, this.end); 70 | } 71 | } 72 | } 73 | public EnvelopeFunc EnvelopeMinFunction 74 | { 75 | get { return this.minFunc; } 76 | set 77 | { 78 | if (this.minFunc != value) 79 | { 80 | this.minFunc = value; 81 | this.RaiseGraphChanged(this.begin, this.end); 82 | } 83 | } 84 | } 85 | 86 | 87 | public TimelineFunctionGraphModel(ValueFunc func, EnvelopeFunc minFunc, EnvelopeFunc maxFunc, float begin, float end) 88 | { 89 | this.func = func; 90 | this.minFunc = minFunc; 91 | this.maxFunc = maxFunc; 92 | this.begin = begin; 93 | this.end = end; 94 | } 95 | 96 | public float GetValueAtX(float time) 97 | { 98 | return this.func(time); 99 | } 100 | public float GetMaxValueInRange(float begin, float end) 101 | { 102 | return this.maxFunc(begin, end); 103 | } 104 | public float GetMinValueInRange(float begin, float end) 105 | { 106 | return this.minFunc(begin, end); 107 | } 108 | 109 | private void RaiseGraphChanged() 110 | { 111 | this.RaiseGraphChanged(this.begin, this.end); 112 | } 113 | private void RaiseGraphChanged(float at) 114 | { 115 | this.RaiseGraphChanged(at, at); 116 | } 117 | private void RaiseGraphChanged(float from, float to) 118 | { 119 | if (this.GraphChanged != null) 120 | this.GraphChanged(this, new TimelineGraphRangeEventArgs(this, from, to)); 121 | } 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /WinForms/ItemModels/ListModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace AdamsLair.WinForms.ItemModels 7 | { 8 | public class ListModel : IListModel, IList 9 | { 10 | private List items = new List(); 11 | 12 | public event EventHandler CountChanged; 13 | public event EventHandler IndicesChanged; 14 | 15 | public int Count 16 | { 17 | get { return this.items.Count; } 18 | } 19 | bool ICollection.IsReadOnly 20 | { 21 | get { return false; } 22 | } 23 | public T this[int index] 24 | { 25 | get { return this.items[index]; } 26 | set 27 | { 28 | this.items[index] = value; 29 | this.OnIndicesChanged(index, 1); 30 | } 31 | } 32 | 33 | public ListModel() : this(new T[0]) {} 34 | public ListModel(IEnumerable items) 35 | { 36 | this.items.AddRange(items); 37 | } 38 | 39 | public void Add(T item) 40 | { 41 | this.items.Add(item); 42 | this.OnCountChanged(); 43 | this.OnIndicesChanged(this.items.Count - 1, 1); 44 | } 45 | public void AddRange(IEnumerable items) 46 | { 47 | int oldCount = this.items.Count; 48 | this.items.AddRange(items); 49 | this.OnCountChanged(); 50 | this.OnIndicesChanged(oldCount, this.items.Count - oldCount); 51 | } 52 | public void Insert(int index, T item) 53 | { 54 | this.items.Insert(index, item); 55 | this.OnCountChanged(); 56 | this.OnIndicesChanged(index, this.items.Count - index); 57 | } 58 | public bool Remove(T item) 59 | { 60 | int index = this.items.IndexOf(item); 61 | if (index != -1) 62 | { 63 | this.RemoveAt(index); 64 | return true; 65 | } 66 | else 67 | { 68 | return false; 69 | } 70 | } 71 | public void RemoveRange(IEnumerable items) 72 | { 73 | int oldCount = this.items.Count; 74 | if (oldCount == 0) return; 75 | 76 | int[] indices = items.Select(i => this.items.IndexOf(i)).Where(i => i != -1).ToArray(); 77 | if (indices.Length > 0) 78 | { 79 | Array.Sort(indices); 80 | for (int i = indices.Length - 1; i >= 0; i--) 81 | { 82 | this.items.RemoveAt(indices[i]); 83 | } 84 | this.OnCountChanged(); 85 | this.OnIndicesChanged(indices[0], oldCount - indices[0]); 86 | } 87 | } 88 | public void RemoveAt(int index) 89 | { 90 | this.items.RemoveAt(index); 91 | this.OnCountChanged(); 92 | this.OnIndicesChanged(index, this.items.Count - index); 93 | } 94 | public void Clear() 95 | { 96 | int oldCount = this.items.Count; 97 | this.items.Clear(); 98 | this.OnCountChanged(); 99 | this.OnIndicesChanged(0, oldCount); 100 | } 101 | 102 | public bool Contains(T item) 103 | { 104 | return this.items.Contains(item); 105 | } 106 | public int IndexOf(T item) 107 | { 108 | return this.items.IndexOf(item); 109 | } 110 | 111 | public void CopyTo(T[] array, int arrayIndex) 112 | { 113 | this.items.CopyTo(array, arrayIndex); 114 | } 115 | 116 | object IListModel.GetItemAt(int index) 117 | { 118 | return this.items[index]; 119 | } 120 | int IListModel.GetIndexOf(object item) 121 | { 122 | return this.items.IndexOf((T)item); 123 | } 124 | private void OnCountChanged() 125 | { 126 | if (this.CountChanged != null) 127 | this.CountChanged(this, EventArgs.Empty); 128 | } 129 | private void OnIndicesChanged(int index, int count) 130 | { 131 | if (this.IndicesChanged != null) 132 | this.IndicesChanged(this, new ListModelItemsEventArgs(index, count)); 133 | } 134 | 135 | public IEnumerator GetEnumerator() 136 | { 137 | return this.items.GetEnumerator(); 138 | } 139 | System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() 140 | { 141 | return this.GetEnumerator(); 142 | } 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /WinForms/PropertyEditing/EditorTemplates/BitmaskSelectorDropDown.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Drawing; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Windows.Forms; 8 | 9 | namespace AdamsLair.WinForms.PropertyEditing.Templates 10 | { 11 | public partial class BitmaskSelectorDropDown : CheckedListBox 12 | { 13 | private bool isUpdatingCheckStates = false; 14 | private bool openedWithCtrl = false; 15 | private int hoveredIndex = -1; 16 | 17 | public event EventHandler AcceptSelection = null; 18 | public event EventHandler RequestClose = null; 19 | 20 | public int HoveredIndex 21 | { 22 | get { return this.hoveredIndex; } 23 | } 24 | 25 | 26 | public new IEnumerable Items 27 | { 28 | get { return base.Items.Cast(); } 29 | set 30 | { 31 | base.Items.Clear(); 32 | base.Items.AddRange(value.ToArray()); 33 | } 34 | } 35 | public ulong BitmaskValue 36 | { 37 | get 38 | { 39 | ulong v = 0; 40 | foreach (BitmaskItem item in this.CheckedItems.OfType()) 41 | v |= item.Value; 42 | return v; 43 | } 44 | set 45 | { 46 | this.isUpdatingCheckStates = true; 47 | for (int i = 0; i < base.Items.Count; i++) 48 | { 49 | BitmaskItem item = base.Items[i] as BitmaskItem; 50 | if (item.Value == 0) 51 | this.SetItemChecked(i, value == 0); 52 | else 53 | this.SetItemChecked(i, (item.Value & value) == item.Value); 54 | } 55 | this.isUpdatingCheckStates = false; 56 | } 57 | } 58 | 59 | 60 | public BitmaskSelectorDropDown() 61 | { 62 | this.IntegralHeight = false; 63 | this.CheckOnClick = true; 64 | this.Font = this.Font; // Prevents parent PopupControl from interfering on resize. 65 | } 66 | public BitmaskSelectorDropDown(IEnumerable items) : this() 67 | { 68 | this.Items = items; 69 | } 70 | 71 | protected void Accept() 72 | { 73 | if (this.AcceptSelection != null) 74 | this.AcceptSelection(this, EventArgs.Empty); 75 | } 76 | protected void Close() 77 | { 78 | if (this.RequestClose != null) this.RequestClose(this, EventArgs.Empty); 79 | } 80 | 81 | protected override void OnGotFocus(EventArgs e) 82 | { 83 | base.OnGotFocus(e); 84 | this.openedWithCtrl = (Control.ModifierKeys & Keys.Control) == Keys.Control; 85 | } 86 | protected override void OnKeyDown(KeyEventArgs e) 87 | { 88 | base.OnKeyDown(e); 89 | if (e.KeyCode == Keys.Return) 90 | { 91 | int index = this.SelectedIndex; 92 | if (index != -1) this.SetItemChecked(index, !this.GetItemChecked(index)); 93 | } 94 | else if (e.KeyCode == Keys.C && e.Control) 95 | { 96 | if (this.SelectedItem != null) 97 | Clipboard.SetText((this.SelectedItem as BitmaskItem).Caption); 98 | } 99 | else if (e.KeyCode == Keys.Back || e.KeyCode == Keys.Left || e.KeyCode == Keys.Escape) 100 | { 101 | this.Accept(); 102 | this.Close(); 103 | } 104 | } 105 | protected override void OnKeyUp(KeyEventArgs e) 106 | { 107 | base.OnKeyUp(e); 108 | if (e.KeyCode == Keys.ControlKey && this.openedWithCtrl) 109 | { 110 | this.Accept(); 111 | this.Close(); 112 | } 113 | } 114 | protected override void OnMouseMove(MouseEventArgs e) 115 | { 116 | base.OnMouseMove(e); 117 | int clientY = e.Y - this.ClientRectangle.Y; 118 | this.hoveredIndex = (clientY / this.ItemHeight) + this.TopIndex; 119 | if (this.hoveredIndex < 0 || this.hoveredIndex >= base.Items.Count) this.hoveredIndex = -1; 120 | } 121 | protected override void OnMouseLeave(EventArgs e) 122 | { 123 | base.OnMouseLeave(e); 124 | this.hoveredIndex = -1; 125 | } 126 | protected override void OnItemCheck(ItemCheckEventArgs e) 127 | { 128 | base.OnItemCheck(e); 129 | if (this.isUpdatingCheckStates) return; 130 | 131 | BitmaskItem item = base.Items[e.Index] as BitmaskItem; 132 | 133 | if (item.Value == 0) 134 | this.BitmaskValue = 0; 135 | else if (e.NewValue == CheckState.Checked) 136 | this.BitmaskValue |= item.Value; 137 | else if (e.NewValue == CheckState.Unchecked) 138 | this.BitmaskValue &= ~item.Value; 139 | 140 | this.Accept(); 141 | } 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /WinForms/Drawing/IconImage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Drawing; 5 | using System.Drawing.Drawing2D; 6 | using System.Windows.Forms; 7 | 8 | using AdamsLair.WinForms.Properties; 9 | 10 | namespace AdamsLair.WinForms.Drawing 11 | { 12 | public class IconImage 13 | { 14 | private Image sourceImage = null; 15 | private Bitmap[] images = new Bitmap[4]; 16 | 17 | public Image SourceImage 18 | { 19 | get { return this.sourceImage; } 20 | } 21 | public Image Passive 22 | { 23 | get { return this.images[0]; } 24 | } 25 | public Image Normal 26 | { 27 | get { return this.images[1]; } 28 | } 29 | public Image Active 30 | { 31 | get { return this.images[2]; } 32 | } 33 | public Image Disabled 34 | { 35 | get { return this.images[3]; } 36 | } 37 | 38 | public int Width 39 | { 40 | get { return this.sourceImage.Width; } 41 | } 42 | public int Height 43 | { 44 | get { return this.sourceImage.Height; } 45 | } 46 | public Size Size 47 | { 48 | get { return this.sourceImage.Size; } 49 | } 50 | 51 | public IconImage(Image source) 52 | { 53 | this.sourceImage = source; 54 | 55 | // Generate specific images 56 | var imgAttribs = new System.Drawing.Imaging.ImageAttributes(); 57 | System.Drawing.Imaging.ColorMatrix colorMatrix = null; 58 | { 59 | colorMatrix = new System.Drawing.Imaging.ColorMatrix(new float[][] { 60 | new float[] {1.0f, 0.0f, 0.0f, 0.0f, 0.0f}, 61 | new float[] {0.0f, 1.0f, 0.0f, 0.0f, 0.0f}, 62 | new float[] {0.0f, 0.0f, 1.0f, 0.0f, 0.0f}, 63 | new float[] {0.0f, 0.0f, 0.0f, 0.65f, 0.0f}, 64 | new float[] {0.0f, 0.0f, 0.0f, 0.0f, 1.0f}}); 65 | imgAttribs.SetColorMatrix(colorMatrix); 66 | this.images[0] = new Bitmap(source.Width, source.Height); 67 | using (Graphics g = Graphics.FromImage(this.images[0])) 68 | { 69 | g.DrawImage(source, 70 | new Rectangle(Point.Empty, source.Size), 71 | 0, 0, source.Width, source.Height, GraphicsUnit.Pixel, 72 | imgAttribs); 73 | } 74 | } 75 | { 76 | colorMatrix = new System.Drawing.Imaging.ColorMatrix(new float[][] { 77 | new float[] {1.0f, 0.0f, 0.0f, 0.0f, 0.0f}, 78 | new float[] {0.0f, 1.0f, 0.0f, 0.0f, 0.0f}, 79 | new float[] {0.0f, 0.0f, 1.0f, 0.0f, 0.0f}, 80 | new float[] {0.0f, 0.0f, 0.0f, 1.0f, 0.0f}, 81 | new float[] {0.0f, 0.0f, 0.0f, 0.0f, 1.0f}}); 82 | imgAttribs.SetColorMatrix(colorMatrix); 83 | this.images[1] = new Bitmap(source.Width, source.Height); 84 | using (Graphics g = Graphics.FromImage(this.images[1])) 85 | { 86 | g.DrawImage(source, 87 | new Rectangle(Point.Empty, source.Size), 88 | 0, 0, source.Width, source.Height, GraphicsUnit.Pixel, 89 | imgAttribs); 90 | } 91 | } 92 | { 93 | colorMatrix = new System.Drawing.Imaging.ColorMatrix(new float[][] { 94 | new float[] {1.3f, 0.0f, 0.0f, 0.0f, 0.0f}, 95 | new float[] {0.0f, 1.3f, 0.0f, 0.0f, 0.0f}, 96 | new float[] {0.0f, 0.0f, 1.3f, 0.0f, 0.0f}, 97 | new float[] {0.0f, 0.0f, 0.0f, 1.0f, 0.0f}, 98 | new float[] {0.0f, 0.0f, 0.0f, 0.0f, 1.0f}}); 99 | imgAttribs.SetColorMatrix(colorMatrix); 100 | this.images[2] = new Bitmap(source.Width, source.Height); 101 | using (Graphics g = Graphics.FromImage(this.images[2])) 102 | { 103 | g.DrawImage(source, 104 | new Rectangle(Point.Empty, source.Size), 105 | 0, 0, source.Width, source.Height, GraphicsUnit.Pixel, 106 | imgAttribs); 107 | } 108 | } 109 | { 110 | colorMatrix = new System.Drawing.Imaging.ColorMatrix(new float[][] { 111 | new float[] {0.34f, 0.34f, 0.34f, 0.0f, 0.0f}, 112 | new float[] {0.34f, 0.34f, 0.34f, 0.0f, 0.0f}, 113 | new float[] {0.34f, 0.34f, 0.34f, 0.0f, 0.0f}, 114 | new float[] {0.0f, 0.0f, 0.0f, 0.5f, 0.0f}, 115 | new float[] {0.0f, 0.0f, 0.0f, 0.0f, 1.0f}}); 116 | imgAttribs.SetColorMatrix(colorMatrix); 117 | this.images[3] = new Bitmap(source.Width, source.Height); 118 | using (Graphics g = Graphics.FromImage(this.images[3])) 119 | { 120 | g.DrawImage(source, 121 | new Rectangle(Point.Empty, source.Size), 122 | 0, 0, source.Width, source.Height, GraphicsUnit.Pixel, 123 | imgAttribs); 124 | } 125 | } 126 | } 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /WinForms/PropertyEditing/PropertyEditors/LabelPropertyEditor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Windows.Forms; 5 | using System.Drawing; 6 | 7 | using AdamsLair.WinForms.Drawing; 8 | using AdamsLair.WinForms.PropertyEditing.Templates; 9 | 10 | namespace AdamsLair.WinForms.PropertyEditing.Editors 11 | { 12 | public class LabelPropertyEditor : PropertyEditor 13 | { 14 | private StringEditorTemplate selectableLabel = null; 15 | private string val = null; 16 | private bool valMultiple = false; 17 | 18 | public override object DisplayedValue 19 | { 20 | get { return Convert.ChangeType(this.val, this.EditedType); } 21 | } 22 | 23 | 24 | public LabelPropertyEditor() 25 | { 26 | this.selectableLabel = new StringEditorTemplate(this); 27 | this.selectableLabel.ReadOnly = true; 28 | this.selectableLabel.Invalidate += this.stringEditor_Invalidate; 29 | } 30 | protected override void OnParentEditorChanged() 31 | { 32 | base.OnParentEditorChanged(); 33 | this.Height = 5 + (int)Math.Round((float)this.ControlRenderer.FontRegular.Height); 34 | } 35 | 36 | protected override void OnGetValue() 37 | { 38 | base.OnGetValue(); 39 | this.BeginUpdate(); 40 | object[] values = this.GetValue().ToArray(); 41 | 42 | // Apply values to editors 43 | if (!values.Any()) 44 | { 45 | this.val = null; 46 | } 47 | else 48 | { 49 | object rawValue = values.First(); 50 | this.valMultiple = false; 51 | this.val = this.GetLabelFor(rawValue, ref this.valMultiple); 52 | this.valMultiple = this.valMultiple || values.Any(o => o == null || this.GetLabelFor(o, ref this.valMultiple) != this.val); 53 | } 54 | 55 | this.selectableLabel.Text = this.val; 56 | this.EndUpdate(); 57 | } 58 | 59 | private string GetLabelFor(object rawValue, ref bool highlight) 60 | { 61 | if (rawValue is string) 62 | { 63 | return rawValue as string; 64 | } 65 | else if (rawValue != null) 66 | { 67 | try 68 | { 69 | return rawValue.ToString(); 70 | } 71 | catch (Exception) 72 | { 73 | highlight = true; 74 | return string.Empty; 75 | } 76 | } 77 | else 78 | { 79 | highlight = true; 80 | return string.Empty; 81 | } 82 | } 83 | 84 | protected internal override void OnPaint(PaintEventArgs e) 85 | { 86 | base.OnPaint(e); 87 | this.selectableLabel.OnPaint(e, this.Enabled, this.valMultiple); 88 | } 89 | protected internal override void OnGotFocus(EventArgs e) 90 | { 91 | base.OnGotFocus(e); 92 | this.selectableLabel.OnGotFocus(e); 93 | this.selectableLabel.Select(); 94 | } 95 | protected internal override void OnLostFocus(EventArgs e) 96 | { 97 | base.OnLostFocus(e); 98 | this.selectableLabel.OnLostFocus(e); 99 | } 100 | protected internal override void OnKeyPress(KeyPressEventArgs e) 101 | { 102 | base.OnKeyPress(e); 103 | this.selectableLabel.OnKeyPress(e); 104 | } 105 | protected internal override void OnKeyDown(KeyEventArgs e) 106 | { 107 | base.OnKeyDown(e); 108 | this.selectableLabel.OnKeyDown(e); 109 | } 110 | protected internal override void OnMouseMove(MouseEventArgs e) 111 | { 112 | base.OnMouseMove(e); 113 | this.selectableLabel.OnMouseMove(e); 114 | } 115 | protected internal override void OnMouseLeave(EventArgs e) 116 | { 117 | base.OnMouseLeave(e); 118 | this.selectableLabel.OnMouseLeave(e); 119 | } 120 | protected internal override void OnMouseDown(MouseEventArgs e) 121 | { 122 | base.OnMouseDown(e); 123 | this.selectableLabel.OnMouseDown(e); 124 | } 125 | protected internal override void OnMouseUp(MouseEventArgs e) 126 | { 127 | base.OnMouseUp(e); 128 | this.selectableLabel.OnMouseUp(e); 129 | } 130 | protected internal override void OnMouseDoubleClick(MouseEventArgs e) 131 | { 132 | base.OnMouseDoubleClick(e); 133 | this.selectableLabel.OnMouseDoubleClick(e); 134 | } 135 | 136 | protected override void UpdateGeometry() 137 | { 138 | base.UpdateGeometry(); 139 | this.selectableLabel.Rect = new Rectangle( 140 | this.ClientRectangle.X + 1, 141 | this.ClientRectangle.Y + 1, 142 | this.ClientRectangle.Width - 2, 143 | this.ClientRectangle.Height - 1); 144 | } 145 | 146 | private void stringEditor_Invalidate(object sender, EventArgs e) 147 | { 148 | this.Invalidate(); 149 | } 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /WinForms/PropertyEditing/PropertyEditors/StringPropertyEditor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Windows.Forms; 5 | using System.Drawing; 6 | 7 | using AdamsLair.WinForms.Drawing; 8 | using AdamsLair.WinForms.PropertyEditing.Templates; 9 | 10 | namespace AdamsLair.WinForms.PropertyEditing.Editors 11 | { 12 | public class StringPropertyEditor : PropertyEditor 13 | { 14 | private StringEditorTemplate stringEditor = null; 15 | private string val = null; 16 | private bool valMultiple = false; 17 | 18 | public override object DisplayedValue 19 | { 20 | get { return Convert.ChangeType(this.val, this.EditedType); } 21 | } 22 | 23 | 24 | public StringPropertyEditor() 25 | { 26 | this.stringEditor = new StringEditorTemplate(this); 27 | this.stringEditor.Invalidate += this.stringEditor_Invalidate; 28 | this.stringEditor.Edited += this.stringEditor_Edited; 29 | this.stringEditor.EditingFinished += this.stringEditor_EditingFinished; 30 | 31 | //this.Height = 18; 32 | } 33 | protected override void OnParentEditorChanged() 34 | { 35 | base.OnParentEditorChanged(); 36 | this.Height = 5 + (int)Math.Round((float)this.ControlRenderer.FontRegular.Height); 37 | } 38 | 39 | protected override void OnGetValue() 40 | { 41 | base.OnGetValue(); 42 | this.BeginUpdate(); 43 | object[] values = this.GetValue().ToArray(); 44 | 45 | // Apply values to editors 46 | if (!values.Any()) 47 | this.val = null; 48 | else 49 | { 50 | this.val = (string)values.First(); 51 | this.valMultiple = values.Any(o => o == null || (string)o != this.val); 52 | } 53 | 54 | this.stringEditor.Text = this.val; 55 | this.EndUpdate(); 56 | } 57 | 58 | protected internal override void OnPaint(PaintEventArgs e) 59 | { 60 | base.OnPaint(e); 61 | this.stringEditor.OnPaint(e, this.Enabled, this.valMultiple); 62 | } 63 | protected internal override void OnGotFocus(EventArgs e) 64 | { 65 | base.OnGotFocus(e); 66 | this.stringEditor.OnGotFocus(e); 67 | this.stringEditor.Select(); 68 | } 69 | protected internal override void OnLostFocus(EventArgs e) 70 | { 71 | base.OnLostFocus(e); 72 | this.stringEditor.OnLostFocus(e); 73 | } 74 | protected internal override void OnKeyPress(KeyPressEventArgs e) 75 | { 76 | base.OnKeyPress(e); 77 | this.stringEditor.OnKeyPress(e); 78 | } 79 | protected internal override void OnKeyDown(KeyEventArgs e) 80 | { 81 | base.OnKeyDown(e); 82 | this.stringEditor.OnKeyDown(e); 83 | } 84 | protected internal override void OnMouseMove(MouseEventArgs e) 85 | { 86 | base.OnMouseMove(e); 87 | this.stringEditor.OnMouseMove(e); 88 | } 89 | protected internal override void OnMouseLeave(EventArgs e) 90 | { 91 | base.OnMouseLeave(e); 92 | this.stringEditor.OnMouseLeave(e); 93 | } 94 | protected internal override void OnMouseDown(MouseEventArgs e) 95 | { 96 | base.OnMouseDown(e); 97 | this.stringEditor.OnMouseDown(e); 98 | } 99 | protected internal override void OnMouseUp(MouseEventArgs e) 100 | { 101 | base.OnMouseUp(e); 102 | this.stringEditor.OnMouseUp(e); 103 | } 104 | protected internal override void OnMouseDoubleClick(MouseEventArgs e) 105 | { 106 | base.OnMouseDoubleClick(e); 107 | this.stringEditor.OnMouseDoubleClick(e); 108 | } 109 | 110 | protected override void UpdateGeometry() 111 | { 112 | base.UpdateGeometry(); 113 | this.stringEditor.Rect = new Rectangle( 114 | this.ClientRectangle.X + 1, 115 | this.ClientRectangle.Y + 1, 116 | this.ClientRectangle.Width - 2, 117 | this.ClientRectangle.Height - 1); 118 | } 119 | protected internal override void OnReadOnlyChanged() 120 | { 121 | base.OnReadOnlyChanged(); 122 | this.stringEditor.ReadOnly = this.ReadOnly; 123 | } 124 | 125 | private void stringEditor_Invalidate(object sender, EventArgs e) 126 | { 127 | this.Invalidate(); 128 | } 129 | private void stringEditor_Edited(object sender, EventArgs e) 130 | { 131 | if (this.IsUpdating) return; 132 | if (this.Disposed) return; 133 | 134 | this.val = this.stringEditor.Text; 135 | this.Invalidate(); 136 | this.PerformSetValue(); 137 | this.PerformGetValue(); 138 | } 139 | private void stringEditor_EditingFinished(object sender, PropertyEditingFinishedEventArgs e) 140 | { 141 | this.OnEditingFinished(e.Reason); 142 | } 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /TestApp/TestApp.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | x86 6 | 8.0.30703 7 | 2.0 8 | {B94AF907-0915-4430-BC49-05BA5091D2AB} 9 | Exe 10 | Properties 11 | AdamsLair.WinForms.TestApp 12 | TestApp 13 | v4.5 14 | 15 | 16 | 512 17 | 18 | 19 | AnyCPU 20 | bin\Debug\ 21 | false 22 | 23 | 24 | AnyCPU 25 | bin\Release\ 26 | false 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | Form 46 | 47 | 48 | DemoForm.cs 49 | 50 | 51 | 52 | 53 | 54 | DemoForm.cs 55 | 56 | 57 | ResXFileCodeGenerator 58 | Resources.Designer.cs 59 | Designer 60 | 61 | 62 | True 63 | Resources.resx 64 | True 65 | 66 | 67 | 68 | SettingsSingleFileGenerator 69 | Settings.Designer.cs 70 | 71 | 72 | True 73 | Settings.settings 74 | True 75 | 76 | 77 | 78 | 79 | {44E2FD11-C687-41ED-B72F-1A4C92479EDC} 80 | AdamsLair.WinForms %28AdamsLair.WinForms\AdamsLair.WinForms%29 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 103 | -------------------------------------------------------------------------------- /TestApp/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.34209 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace AdamsLair.WinForms.TestApp.Properties { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("AdamsLair.WinForms.TestApp.Properties.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | 63 | /// 64 | /// Looks up a localized resource of type System.Drawing.Bitmap. 65 | /// 66 | internal static System.Drawing.Bitmap ItemBig { 67 | get { 68 | object obj = ResourceManager.GetObject("ItemBig", resourceCulture); 69 | return ((System.Drawing.Bitmap)(obj)); 70 | } 71 | } 72 | 73 | /// 74 | /// Looks up a localized resource of type System.Drawing.Bitmap. 75 | /// 76 | internal static System.Drawing.Bitmap ItemHigh { 77 | get { 78 | object obj = ResourceManager.GetObject("ItemHigh", resourceCulture); 79 | return ((System.Drawing.Bitmap)(obj)); 80 | } 81 | } 82 | 83 | /// 84 | /// Looks up a localized resource of type System.Drawing.Bitmap. 85 | /// 86 | internal static System.Drawing.Bitmap ItemSmall { 87 | get { 88 | object obj = ResourceManager.GetObject("ItemSmall", resourceCulture); 89 | return ((System.Drawing.Bitmap)(obj)); 90 | } 91 | } 92 | 93 | /// 94 | /// Looks up a localized resource of type System.Drawing.Bitmap. 95 | /// 96 | internal static System.Drawing.Bitmap ItemWide { 97 | get { 98 | object obj = ResourceManager.GetObject("ItemWide", resourceCulture); 99 | return ((System.Drawing.Bitmap)(obj)); 100 | } 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /WinForms/PropertyEditing/PropertyEditors/ObjectSelectorPropertyEditor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Windows.Forms; 5 | using System.Drawing; 6 | 7 | using AdamsLair.WinForms.Drawing; 8 | using AdamsLair.WinForms.PropertyEditing.Templates; 9 | 10 | namespace AdamsLair.WinForms.PropertyEditing.Editors 11 | { 12 | public class ObjectSelectorPropertyEditor : PropertyEditor, IPopupControlHost 13 | { 14 | private ComboBoxEditorTemplate objSelector = null; 15 | private object val = null; 16 | private bool valMultiple = false; 17 | 18 | public override object DisplayedValue 19 | { 20 | get { return this.val; } 21 | } 22 | public IEnumerable Items 23 | { 24 | get { return this.objSelector.DropDownItems.Cast(); } 25 | set 26 | { 27 | this.objSelector.DropDownItems = value; 28 | this.UpdateEditorValue(); 29 | } 30 | } 31 | public bool IsDropDownOpened 32 | { 33 | get { return this.objSelector.IsDropDownOpened; } 34 | } 35 | public ObjectItem DropDownHoveredObject 36 | { 37 | get { return this.objSelector.DropDownHoveredObject as ObjectItem; } 38 | } 39 | 40 | 41 | public ObjectSelectorPropertyEditor() 42 | { 43 | this.objSelector = new ComboBoxEditorTemplate(this); 44 | this.objSelector.Invalidate += this.objSelector_Invalidate; 45 | this.objSelector.Edited += this.objSelector_Edited; 46 | 47 | //this.Height = 18; 48 | } 49 | protected override void OnParentEditorChanged() 50 | { 51 | base.OnParentEditorChanged(); 52 | this.Height = 5 + (int)Math.Round((float)this.ControlRenderer.FontRegular.Height); 53 | } 54 | 55 | public void ShowDropDown() 56 | { 57 | this.objSelector.ShowDropDown(); 58 | } 59 | public void HideDropDown() 60 | { 61 | this.objSelector.HideDropDown(); 62 | } 63 | protected override void OnGetValue() 64 | { 65 | base.OnGetValue(); 66 | this.BeginUpdate(); 67 | object[] values = this.GetValue().ToArray(); 68 | 69 | // Apply values to editors 70 | if (!values.Any()) 71 | this.val = null; 72 | else 73 | { 74 | this.val = values.Where(o => o != null).FirstOrDefault(); 75 | this.valMultiple = values.Any(o => o == null) || !values.All(o => object.Equals(o, this.val)); 76 | } 77 | 78 | this.UpdateEditorValue(); 79 | this.EndUpdate(); 80 | } 81 | 82 | private void UpdateEditorValue() 83 | { 84 | this.objSelector.SelectedObject = this.objSelector.DropDownItems.Cast().FirstOrDefault(i => object.Equals(i.Value, this.val)); 85 | } 86 | 87 | protected internal override void OnPaint(PaintEventArgs e) 88 | { 89 | base.OnPaint(e); 90 | this.objSelector.OnPaint(e, this.Enabled, this.valMultiple); 91 | } 92 | protected internal override void OnGotFocus(EventArgs e) 93 | { 94 | base.OnGotFocus(e); 95 | this.objSelector.OnGotFocus(e); 96 | } 97 | protected internal override void OnLostFocus(EventArgs e) 98 | { 99 | base.OnLostFocus(e); 100 | this.objSelector.OnLostFocus(e); 101 | } 102 | protected internal override void OnMouseMove(MouseEventArgs e) 103 | { 104 | base.OnMouseMove(e); 105 | this.objSelector.OnMouseMove(e); 106 | } 107 | protected internal override void OnMouseLeave(EventArgs e) 108 | { 109 | base.OnMouseLeave(e); 110 | this.objSelector.OnMouseLeave(e); 111 | } 112 | protected internal override void OnMouseDown(MouseEventArgs e) 113 | { 114 | base.OnMouseDown(e); 115 | this.objSelector.OnMouseDown(e); 116 | } 117 | protected internal override void OnMouseUp(MouseEventArgs e) 118 | { 119 | base.OnMouseUp(e); 120 | this.objSelector.OnMouseUp(e); 121 | } 122 | protected internal override void OnKeyDown(KeyEventArgs e) 123 | { 124 | base.OnKeyDown(e); 125 | this.objSelector.OnKeyDown(e); 126 | } 127 | protected internal override void OnKeyUp(KeyEventArgs e) 128 | { 129 | base.OnKeyUp(e); 130 | this.objSelector.OnKeyUp(e); 131 | } 132 | 133 | protected override void UpdateGeometry() 134 | { 135 | base.UpdateGeometry(); 136 | this.objSelector.Rect = new Rectangle( 137 | this.ClientRectangle.X + 1, 138 | this.ClientRectangle.Y + 1, 139 | this.ClientRectangle.Width - 2, 140 | this.ClientRectangle.Height - 1); 141 | } 142 | protected internal override void OnReadOnlyChanged() 143 | { 144 | base.OnReadOnlyChanged(); 145 | this.objSelector.ReadOnly = this.ReadOnly; 146 | } 147 | 148 | private void objSelector_Invalidate(object sender, EventArgs e) 149 | { 150 | this.Invalidate(); 151 | } 152 | private void objSelector_Edited(object sender, EventArgs e) 153 | { 154 | if (this.IsUpdating) return; 155 | if (this.Disposed) return; 156 | 157 | this.val = (this.objSelector.SelectedObject as ObjectItem).Value; 158 | this.Invalidate(); 159 | this.PerformSetValue(); 160 | this.PerformGetValue(); 161 | this.OnEditingFinished(FinishReason.LeapValue); 162 | } 163 | } 164 | } 165 | -------------------------------------------------------------------------------- /WinForms/PropertyEditing/PropertyEditors/BitmaskPropertyEditor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Windows.Forms; 5 | using System.Drawing; 6 | 7 | using AdamsLair.WinForms.Drawing; 8 | using AdamsLair.WinForms.PropertyEditing.Templates; 9 | 10 | namespace AdamsLair.WinForms.PropertyEditing.Editors 11 | { 12 | public class BitmaskPropertyEditor : PropertyEditor, IPopupControlHost 13 | { 14 | private BitmaskEditorTemplate bitmaskSelector = null; 15 | private ulong val = 0L; 16 | private bool valMultiple = false; 17 | 18 | public override object DisplayedValue 19 | { 20 | get { return Convert.ChangeType(this.val, this.EditedType); } 21 | } 22 | public ulong BitmaskValue 23 | { 24 | get { return this.val; } 25 | } 26 | public IEnumerable Items 27 | { 28 | get { return this.bitmaskSelector.DropDownItems; } 29 | set 30 | { 31 | this.bitmaskSelector.DropDownItems = value; 32 | this.bitmaskSelector.BitmaskValue = this.val; 33 | } 34 | } 35 | public bool IsDropDownOpened 36 | { 37 | get { return this.bitmaskSelector.IsDropDownOpened; } 38 | } 39 | public BitmaskItem DropDownHoveredItem 40 | { 41 | get { return this.bitmaskSelector.DropDownHoveredItem; } 42 | } 43 | 44 | 45 | public BitmaskPropertyEditor() 46 | { 47 | this.bitmaskSelector = new BitmaskEditorTemplate(this); 48 | this.bitmaskSelector.Invalidate += this.stringSelector_Invalidate; 49 | this.bitmaskSelector.Edited += this.stringSelector_Edited; 50 | 51 | //this.Height = 18; 52 | } 53 | protected override void OnParentEditorChanged() 54 | { 55 | base.OnParentEditorChanged(); 56 | this.Height = 5 + (int)Math.Round((float)this.ControlRenderer.FontRegular.Height); 57 | } 58 | 59 | public void ShowDropDown() 60 | { 61 | this.bitmaskSelector.ShowDropDown(); 62 | } 63 | public void HideDropDown() 64 | { 65 | this.bitmaskSelector.HideDropDown(); 66 | } 67 | protected override void OnGetValue() 68 | { 69 | base.OnGetValue(); 70 | this.BeginUpdate(); 71 | object[] values = this.GetValue().ToArray(); 72 | IEnumerable valuesNotNull = values.Where(o => o != null); 73 | 74 | // Apply values to editors 75 | if (!valuesNotNull.Any()) 76 | { 77 | this.val = 0L; 78 | } 79 | else 80 | { 81 | this.val = Convert.ToUInt64(valuesNotNull.First()); 82 | this.valMultiple = values.Any(o => o == null) || !values.All(o => this.val == Convert.ToUInt64(o)); 83 | } 84 | 85 | this.bitmaskSelector.BitmaskValue = this.val; 86 | this.EndUpdate(); 87 | } 88 | 89 | protected internal override void OnPaint(PaintEventArgs e) 90 | { 91 | base.OnPaint(e); 92 | this.bitmaskSelector.OnPaint(e, this.Enabled, this.valMultiple); 93 | } 94 | protected internal override void OnGotFocus(EventArgs e) 95 | { 96 | base.OnGotFocus(e); 97 | this.bitmaskSelector.OnGotFocus(e); 98 | } 99 | protected internal override void OnLostFocus(EventArgs e) 100 | { 101 | base.OnLostFocus(e); 102 | this.bitmaskSelector.OnLostFocus(e); 103 | } 104 | protected internal override void OnMouseMove(MouseEventArgs e) 105 | { 106 | base.OnMouseMove(e); 107 | this.bitmaskSelector.OnMouseMove(e); 108 | } 109 | protected internal override void OnMouseLeave(EventArgs e) 110 | { 111 | base.OnMouseLeave(e); 112 | this.bitmaskSelector.OnMouseLeave(e); 113 | } 114 | protected internal override void OnMouseDown(MouseEventArgs e) 115 | { 116 | base.OnMouseDown(e); 117 | this.bitmaskSelector.OnMouseDown(e); 118 | } 119 | protected internal override void OnMouseUp(MouseEventArgs e) 120 | { 121 | base.OnMouseUp(e); 122 | this.bitmaskSelector.OnMouseUp(e); 123 | } 124 | protected internal override void OnKeyDown(KeyEventArgs e) 125 | { 126 | base.OnKeyDown(e); 127 | this.bitmaskSelector.OnKeyDown(e); 128 | } 129 | protected internal override void OnKeyUp(KeyEventArgs e) 130 | { 131 | base.OnKeyUp(e); 132 | this.bitmaskSelector.OnKeyUp(e); 133 | } 134 | 135 | protected override void UpdateGeometry() 136 | { 137 | base.UpdateGeometry(); 138 | this.bitmaskSelector.Rect = new Rectangle( 139 | this.ClientRectangle.X + 1, 140 | this.ClientRectangle.Y + 1, 141 | this.ClientRectangle.Width - 2, 142 | this.ClientRectangle.Height - 1); 143 | } 144 | protected internal override void OnReadOnlyChanged() 145 | { 146 | base.OnReadOnlyChanged(); 147 | this.bitmaskSelector.ReadOnly = this.ReadOnly; 148 | } 149 | 150 | private void stringSelector_Invalidate(object sender, EventArgs e) 151 | { 152 | this.Invalidate(); 153 | } 154 | private void stringSelector_Edited(object sender, EventArgs e) 155 | { 156 | if (this.IsUpdating) return; 157 | if (this.Disposed) return; 158 | 159 | this.val = this.bitmaskSelector.BitmaskValue; 160 | this.Invalidate(); 161 | this.PerformSetValue(); 162 | this.PerformGetValue(); 163 | this.OnEditingFinished(FinishReason.LeapValue); 164 | } 165 | } 166 | } 167 | -------------------------------------------------------------------------------- /WinForms/Internal/ReflectionHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace AdamsLair.WinForms 7 | { 8 | internal static class ReflectionHelper 9 | { 10 | public static object CreateInstanceOf(this Type instanceType, bool noConstructor = false) 11 | { 12 | try 13 | { 14 | if (instanceType == typeof(string)) 15 | return ""; 16 | else if (typeof(Array).IsAssignableFrom(instanceType) && instanceType.GetArrayRank() == 1) 17 | return Array.CreateInstance(instanceType.GetElementType(), 0); 18 | else if (noConstructor) 19 | return System.Runtime.Serialization.FormatterServices.GetUninitializedObject(instanceType); 20 | else 21 | return Activator.CreateInstance(instanceType, true); 22 | } 23 | catch (Exception) 24 | { 25 | return null; 26 | } 27 | } 28 | /// 29 | /// Returns the default instance of a Type. Equals default(T), but works for Reflection. 30 | /// 31 | /// The Type to create a default instance of. 32 | /// 33 | public static object GetDefaultInstanceOf(this Type instanceType) 34 | { 35 | if (instanceType.IsValueType) 36 | return Activator.CreateInstance(instanceType, true); 37 | else 38 | return null; 39 | } 40 | public static bool IsDerivedFrom(this Type type, Type baseType) 41 | { 42 | do 43 | { 44 | if (type.BaseType == baseType) 45 | return true; 46 | 47 | type = type.BaseType; 48 | } while (type != null); 49 | 50 | return false; 51 | } 52 | public static Type GetCommonBaseClass(this IEnumerable types) 53 | { 54 | Type commonBase = null; 55 | foreach (Type type in types) 56 | { 57 | if (commonBase == null) 58 | { 59 | commonBase = type; 60 | continue; 61 | } 62 | while (commonBase != null && !commonBase.IsAssignableFrom(type)) 63 | { 64 | commonBase = commonBase.BaseType ?? typeof(object); 65 | if (commonBase == typeof(object)) return commonBase; 66 | } 67 | } 68 | return commonBase; 69 | } 70 | public static string GetTypeCSCodeName(this Type T, bool shortName = false) 71 | { 72 | StringBuilder typeStr = new StringBuilder(); 73 | 74 | if (T.IsGenericParameter) 75 | { 76 | return T.Name; 77 | } 78 | if (T.IsArray) 79 | { 80 | typeStr.Append(GetTypeCSCodeName(T.GetElementType(), shortName)); 81 | typeStr.Append('['); 82 | typeStr.Append(',', T.GetArrayRank() - 1); 83 | typeStr.Append(']'); 84 | } 85 | else 86 | { 87 | Type[] genArgs = T.IsGenericType ? T.GetGenericArguments() : null; 88 | 89 | if (T.IsNested) 90 | { 91 | Type declType = T.DeclaringType; 92 | if (declType.IsGenericTypeDefinition) 93 | { 94 | Array.Resize(ref genArgs, declType.GetGenericArguments().Length); 95 | declType = declType.MakeGenericType(genArgs); 96 | genArgs = T.GetGenericArguments().Skip(genArgs.Length).ToArray(); 97 | } 98 | string parentName = GetTypeCSCodeName(declType, shortName); 99 | 100 | string[] nestedNameToken = shortName ? T.Name.Split('+') : T.FullName.Split('+'); 101 | string nestedName = nestedNameToken[nestedNameToken.Length - 1]; 102 | 103 | int genTypeSepIndex = nestedName.IndexOf("[["); 104 | if (genTypeSepIndex != -1) nestedName = nestedName.Substring(0, genTypeSepIndex); 105 | genTypeSepIndex = nestedName.IndexOf('`'); 106 | if (genTypeSepIndex != -1) nestedName = nestedName.Substring(0, genTypeSepIndex); 107 | 108 | typeStr.Append(parentName); 109 | typeStr.Append('.'); 110 | typeStr.Append(nestedName); 111 | } 112 | else 113 | { 114 | if (shortName) 115 | typeStr.Append(T.Name.Split(new char[] {'`'}, StringSplitOptions.RemoveEmptyEntries)[0].Replace('+', '.')); 116 | else 117 | typeStr.Append(T.FullName.Split(new char[] {'`'}, StringSplitOptions.RemoveEmptyEntries)[0].Replace('+', '.')); 118 | } 119 | 120 | if (genArgs != null && genArgs.Length > 0) 121 | { 122 | if (T.IsGenericTypeDefinition) 123 | { 124 | typeStr.Append('<'); 125 | typeStr.Append(',', genArgs.Length - 1); 126 | typeStr.Append('>'); 127 | } 128 | else if (T.IsGenericType) 129 | { 130 | typeStr.Append('<'); 131 | for (int i = 0; i < genArgs.Length; i++) 132 | { 133 | typeStr.Append(GetTypeCSCodeName(genArgs[i], shortName)); 134 | if (i < genArgs.Length - 1) 135 | typeStr.Append(','); 136 | } 137 | typeStr.Append('>'); 138 | } 139 | } 140 | } 141 | 142 | return typeStr.Replace('+', '.').ToString(); 143 | } 144 | 145 | public static Type[] FindConcreteTypes(Type abstractType) 146 | { 147 | return AppDomain.CurrentDomain.GetAssemblies(). 148 | Where(a => !a.IsDynamic). 149 | SelectMany(a => a.GetExportedTypes()). 150 | Where(t => !t.IsAbstract && !t.IsInterface && abstractType.IsAssignableFrom(t)). 151 | ToArray(); 152 | } 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /WinForms/PropertyEditing/PropertyEditors/EnumPropertyEditor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Windows.Forms; 5 | using System.Drawing; 6 | 7 | using AdamsLair.WinForms.Drawing; 8 | using AdamsLair.WinForms.PropertyEditing.Templates; 9 | 10 | namespace AdamsLair.WinForms.PropertyEditing.Editors 11 | { 12 | public class EnumPropertyEditor : PropertyEditor, IPopupControlHost 13 | { 14 | private ComboBoxEditorTemplate stringSelector = null; 15 | private Enum val = null; 16 | private bool valMultiple = false; 17 | 18 | public override object DisplayedValue 19 | { 20 | get { return this.val != null ? Convert.ChangeType(this.val, this.EditedType) : this.EditedType.GetDefaultInstanceOf(); } 21 | } 22 | public bool IsDropDownOpened 23 | { 24 | get { return this.stringSelector.IsDropDownOpened; } 25 | } 26 | public string DropDownHoveredName 27 | { 28 | get { return this.stringSelector.DropDownHoveredObject as string; } 29 | } 30 | 31 | 32 | public EnumPropertyEditor() 33 | { 34 | this.stringSelector = new ComboBoxEditorTemplate(this); 35 | this.stringSelector.Invalidate += this.stringSelector_Invalidate; 36 | this.stringSelector.Edited += this.stringSelector_Edited; 37 | 38 | //this.Height = 18; 39 | } 40 | protected override void OnParentEditorChanged() 41 | { 42 | base.OnParentEditorChanged(); 43 | this.Height = 5 + (int)Math.Round((float)this.ControlRenderer.FontRegular.Height); 44 | } 45 | 46 | public void ShowDropDown() 47 | { 48 | this.stringSelector.ShowDropDown(); 49 | } 50 | public void HideDropDown() 51 | { 52 | this.stringSelector.HideDropDown(); 53 | } 54 | protected override void OnGetValue() 55 | { 56 | base.OnGetValue(); 57 | this.BeginUpdate(); 58 | Enum[] values = this.GetValue().Select(o => o is Enum ? (Enum)o : null).ToArray(); 59 | IEnumerable valuesNotNull = values.Where(o => o != null); 60 | 61 | // Apply values to editors 62 | if (!valuesNotNull.Any()) 63 | { 64 | this.val = null; 65 | } 66 | else 67 | { 68 | Enum firstVal = valuesNotNull.First(); 69 | 70 | this.val = firstVal; 71 | this.valMultiple = values.Any(o => o == null) || !values.All(o => Enum.Equals(o, firstVal)); 72 | } 73 | 74 | this.stringSelector.SelectedObject = this.val != null ? this.val.ToString() : null; 75 | this.EndUpdate(); 76 | } 77 | 78 | protected internal override void OnPaint(PaintEventArgs e) 79 | { 80 | base.OnPaint(e); 81 | this.stringSelector.OnPaint(e, this.Enabled, this.valMultiple); 82 | } 83 | protected internal override void OnGotFocus(EventArgs e) 84 | { 85 | base.OnGotFocus(e); 86 | this.stringSelector.OnGotFocus(e); 87 | } 88 | protected internal override void OnLostFocus(EventArgs e) 89 | { 90 | base.OnLostFocus(e); 91 | this.stringSelector.OnLostFocus(e); 92 | } 93 | protected internal override void OnMouseMove(MouseEventArgs e) 94 | { 95 | base.OnMouseMove(e); 96 | this.stringSelector.OnMouseMove(e); 97 | } 98 | protected internal override void OnMouseLeave(EventArgs e) 99 | { 100 | base.OnMouseLeave(e); 101 | this.stringSelector.OnMouseLeave(e); 102 | } 103 | protected internal override void OnMouseDown(MouseEventArgs e) 104 | { 105 | base.OnMouseDown(e); 106 | this.stringSelector.OnMouseDown(e); 107 | } 108 | protected internal override void OnMouseUp(MouseEventArgs e) 109 | { 110 | base.OnMouseUp(e); 111 | this.stringSelector.OnMouseUp(e); 112 | } 113 | protected internal override void OnKeyDown(KeyEventArgs e) 114 | { 115 | base.OnKeyDown(e); 116 | this.stringSelector.OnKeyDown(e); 117 | } 118 | protected internal override void OnKeyUp(KeyEventArgs e) 119 | { 120 | base.OnKeyUp(e); 121 | this.stringSelector.OnKeyUp(e); 122 | } 123 | 124 | protected override void UpdateGeometry() 125 | { 126 | base.UpdateGeometry(); 127 | this.stringSelector.Rect = new Rectangle( 128 | this.ClientRectangle.X + 1, 129 | this.ClientRectangle.Y + 1, 130 | this.ClientRectangle.Width - 2, 131 | this.ClientRectangle.Height - 1); 132 | } 133 | protected internal override void OnReadOnlyChanged() 134 | { 135 | base.OnReadOnlyChanged(); 136 | this.stringSelector.ReadOnly = this.ReadOnly; 137 | } 138 | protected override void OnEditedTypeChanged() 139 | { 140 | base.OnEditedTypeChanged(); 141 | this.stringSelector.DropDownItems = Enum.GetNames(this.EditedType); 142 | } 143 | 144 | private void stringSelector_Invalidate(object sender, EventArgs e) 145 | { 146 | this.Invalidate(); 147 | } 148 | private void stringSelector_Edited(object sender, EventArgs e) 149 | { 150 | if (this.IsUpdating) return; 151 | if (this.Disposed) return; 152 | 153 | object selection = this.stringSelector.SelectedObject; 154 | if (selection == null) return; 155 | 156 | this.val = (Enum)Enum.Parse(this.EditedType, selection.ToString()); 157 | this.Invalidate(); 158 | this.PerformSetValue(); 159 | this.PerformGetValue(); 160 | this.OnEditingFinished(FinishReason.LeapValue); 161 | } 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /WinForms/PropertyEditing/PropertyEditors/BoolPropertyEditor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Windows.Forms; 5 | using System.Drawing; 6 | 7 | using AdamsLair.WinForms.Drawing; 8 | 9 | namespace AdamsLair.WinForms.PropertyEditing.Editors 10 | { 11 | public class BoolPropertyEditor : PropertyEditor 12 | { 13 | private CheckState state = CheckState.Unchecked; 14 | private bool hovered = false; 15 | private bool pressed = false; 16 | 17 | public override object DisplayedValue 18 | { 19 | get { return Convert.ChangeType(this.state == CheckState.Checked, this.EditedType); } 20 | } 21 | 22 | public BoolPropertyEditor() 23 | { 24 | //this.Height = 16; 25 | } 26 | protected override void OnParentEditorChanged() 27 | { 28 | base.OnParentEditorChanged(); 29 | this.Height = Math.Max(13, 3 + (int)Math.Round((float)this.ControlRenderer.FontRegular.Height)); 30 | } 31 | 32 | protected override void OnGetValue() 33 | { 34 | base.OnGetValue(); 35 | this.BeginUpdate(); 36 | CheckState lastState = this.state; 37 | object[] values = this.GetValue().ToArray(); 38 | 39 | // Apply values to editors 40 | if (!values.Any()) 41 | this.state = CheckState.Unchecked; 42 | else 43 | { 44 | int trueCount = values.Count(o => o != null && (bool)Convert.ToBoolean(o)); 45 | if (!this.ReadOnly && (values.Any(o => o == null) || (trueCount > 0 && trueCount < values.Count()))) 46 | this.state = CheckState.Indeterminate; 47 | else 48 | this.state = trueCount > 0 ? CheckState.Checked : CheckState.Unchecked; 49 | } 50 | 51 | this.EndUpdate(); 52 | if (this.state != lastState) this.Invalidate(); 53 | } 54 | protected override void OnSetValue() 55 | { 56 | if (this.state == CheckState.Indeterminate) return; 57 | base.OnSetValue(); 58 | } 59 | 60 | protected void ToggleState() 61 | { 62 | if (this.state == CheckState.Checked) 63 | this.state = CheckState.Unchecked; 64 | else 65 | this.state = CheckState.Checked; 66 | 67 | this.Invalidate(); 68 | this.PerformSetValue(); 69 | this.PerformGetValue(); 70 | this.OnEditingFinished(FinishReason.LeapValue); 71 | } 72 | protected void SetState(bool value) 73 | { 74 | this.state = value ? CheckState.Checked : CheckState.Unchecked; 75 | 76 | this.Invalidate(); 77 | this.PerformSetValue(); 78 | this.PerformGetValue(); 79 | this.OnEditingFinished(FinishReason.LeapValue); 80 | } 81 | 82 | protected internal override void OnPaint(PaintEventArgs e) 83 | { 84 | base.OnPaint(e); 85 | 86 | CheckBoxState boxState = CheckBoxState.UncheckedNormal; 87 | bool boxEnabled = this.Enabled && !this.ReadOnly; 88 | bool hot = this.hovered | this.Focused; 89 | if (this.state == CheckState.Checked) 90 | { 91 | if (!boxEnabled) boxState = CheckBoxState.CheckedDisabled; 92 | else if (this.pressed) boxState = CheckBoxState.CheckedPressed; 93 | else if (hot) boxState = CheckBoxState.CheckedHot; 94 | else boxState = CheckBoxState.CheckedNormal; 95 | } 96 | else if (this.state == CheckState.Unchecked) 97 | { 98 | if (!boxEnabled) boxState = CheckBoxState.UncheckedDisabled; 99 | else if (this.pressed) boxState = CheckBoxState.UncheckedPressed; 100 | else if (hot) boxState = CheckBoxState.UncheckedHot; 101 | else boxState = CheckBoxState.UncheckedNormal; 102 | } 103 | else if (this.state == CheckState.Indeterminate) 104 | { 105 | if (!boxEnabled) boxState = CheckBoxState.MixedDisabled; 106 | else if (this.pressed) boxState = CheckBoxState.MixedPressed; 107 | else if (hot) boxState = CheckBoxState.MixedHot; 108 | else boxState = CheckBoxState.MixedNormal; 109 | } 110 | 111 | Size boxSize = ControlRenderer.CheckBoxSize; 112 | Point boxLoc = new Point( 113 | this.ClientRectangle.X + 2, 114 | this.ClientRectangle.Y + this.ClientRectangle.Height / 2 - boxSize.Height / 2); 115 | ControlRenderer.DrawCheckBox(e.Graphics, boxLoc, boxState); 116 | } 117 | protected internal override void OnMouseMove(MouseEventArgs e) 118 | { 119 | base.OnMouseMove(e); 120 | bool lastHovered = this.hovered; 121 | this.hovered = !this.ReadOnly && this.ClientRectangle.Contains(e.Location); 122 | if (lastHovered != this.hovered) this.Invalidate(); 123 | } 124 | protected internal override void OnMouseLeave(EventArgs e) 125 | { 126 | base.OnMouseLeave(e); 127 | if (this.hovered) this.Invalidate(); 128 | this.hovered = false; 129 | this.pressed = false; 130 | } 131 | protected internal override void OnMouseDown(MouseEventArgs e) 132 | { 133 | base.OnMouseDown(e); 134 | if (this.hovered && (e.Button & MouseButtons.Left) != MouseButtons.None) 135 | { 136 | if (!this.pressed) this.Invalidate(); 137 | this.pressed = true; 138 | } 139 | } 140 | protected internal override void OnMouseUp(MouseEventArgs e) 141 | { 142 | base.OnMouseUp(e); 143 | if ((e.Button & MouseButtons.Left) != MouseButtons.None) 144 | { 145 | if (this.hovered && this.pressed) this.ToggleState(); 146 | if (this.pressed) this.Invalidate(); 147 | this.pressed = false; 148 | } 149 | } 150 | protected internal override void OnKeyDown(KeyEventArgs e) 151 | { 152 | base.OnKeyDown(e); 153 | if (e.KeyCode == Keys.Return) 154 | { 155 | this.ToggleState(); 156 | e.Handled = true; 157 | } 158 | else if (e.KeyCode == Keys.Delete) 159 | { 160 | this.SetState(false); 161 | e.Handled = true; 162 | } 163 | else if (e.Control && e.KeyCode == Keys.C) 164 | { 165 | Clipboard.SetText((this.state == CheckState.Checked).ToString()); 166 | e.Handled = true; 167 | } 168 | else if (e.Control && e.KeyCode == Keys.V) 169 | { 170 | bool temp; 171 | if (bool.TryParse(Clipboard.GetText(), out temp)) 172 | this.SetState(temp); 173 | e.Handled = true; 174 | } 175 | } 176 | } 177 | } 178 | -------------------------------------------------------------------------------- /WinForms/ItemModels/MenuModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.IO; 6 | 7 | namespace AdamsLair.WinForms.ItemModels 8 | { 9 | public class MenuModel : IMenuModel 10 | { 11 | private List items = new List(); 12 | 13 | public event EventHandler ItemsAdded = null; 14 | public event EventHandler ItemsRemoved = null; 15 | public event EventHandler ItemsChanged = null; 16 | 17 | public IEnumerable Items 18 | { 19 | get { return this.items; } 20 | } 21 | public IEnumerable ItemsDeep 22 | { 23 | get 24 | { 25 | if (this.items == null) yield break; 26 | foreach (MenuModelItem i in this.items) 27 | { 28 | yield return i; 29 | foreach (MenuModelItem j in i.ItemsDeep) 30 | { 31 | yield return j; 32 | } 33 | } 34 | } 35 | } 36 | 37 | public MenuModelItem GetItem(string fullItemName) 38 | { 39 | return this.GetItem(SplitItemName(fullItemName)); 40 | } 41 | public MenuModelItem GetItem(string[] itemNameTreePath) 42 | { 43 | return GetItemDeep(this.items, itemNameTreePath); 44 | } 45 | public MenuModelItem RequestItem(string fullItemName, Action onCreatingNewItem = null) 46 | { 47 | return this.RequestItem(SplitItemName(fullItemName), onCreatingNewItem); 48 | } 49 | public MenuModelItem RequestItem(string[] itemNameTreePath, Action onCreatingNewItem = null) 50 | { 51 | return RequestItem(this.items, itemNameTreePath, i => this.AddItem(i), onCreatingNewItem); 52 | } 53 | 54 | public void AddItem(MenuModelItem item) 55 | { 56 | this.AddItems(new[] { item }); 57 | } 58 | public void AddItems(IEnumerable items) 59 | { 60 | List actual = new List(); 61 | foreach (MenuModelItem item in items) 62 | { 63 | if (item.Parent != null) continue; 64 | if (item.Model != null) continue; 65 | item.Model = this; 66 | actual.Add(item); 67 | } 68 | this.items.AddRange(actual); 69 | this.RaiseItemsAdded(actual); 70 | } 71 | public void RemoveItem(MenuModelItem item) 72 | { 73 | this.RemoveItems(new[] { item }); 74 | } 75 | public void RemoveItems(IEnumerable items) 76 | { 77 | List actual = new List(); 78 | foreach (MenuModelItem item in items) 79 | { 80 | if (item.Parent != null) continue; 81 | if (item.Model != this) continue; 82 | actual.Add(item); 83 | this.items.Remove(item); 84 | } 85 | this.RaiseItemsRemoved(actual); 86 | foreach (MenuModelItem item in actual) 87 | { 88 | item.Model = null; 89 | } 90 | } 91 | public void ClearItems() 92 | { 93 | IMenuModelItem[] oldItems = this.items.ToArray(); 94 | foreach (MenuModelItem item in this.items) 95 | { 96 | item.Model = null; 97 | } 98 | this.items.Clear(); 99 | this.RaiseItemsRemoved(oldItems); 100 | } 101 | 102 | internal void RaiseItemsAdded(IEnumerable items) 103 | { 104 | if (this.ItemsAdded != null) 105 | this.ItemsAdded(this, new MenuModelItemsEventArgs(items)); 106 | } 107 | internal void RaiseItemsRemoved(IEnumerable items) 108 | { 109 | if (this.ItemsRemoved != null) 110 | this.ItemsRemoved(this, new MenuModelItemsEventArgs(items)); 111 | } 112 | internal void RaiseItemsChanged(IEnumerable items, bool affectsSorting = false) 113 | { 114 | if (this.ItemsChanged != null) 115 | this.ItemsChanged(this, new MenuModelItemsEventArgs(items, affectsSorting)); 116 | } 117 | 118 | IEnumerable IMenuModel.Items 119 | { 120 | get { return this.items; } 121 | } 122 | 123 | internal static string[] SplitItemName(string fullItemName) 124 | { 125 | fullItemName = fullItemName.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar); 126 | return fullItemName.Split(new char[] { Path.DirectorySeparatorChar }, StringSplitOptions.None); 127 | } 128 | internal static MenuModelItem GetItemDeep(IEnumerable rootItems, string[] itemNameTreePath) 129 | { 130 | IEnumerable itemCollection = rootItems; 131 | MenuModelItem item = null; 132 | for (int nameIndex = 0; nameIndex < itemNameTreePath.Length; nameIndex++) 133 | { 134 | item = itemCollection.FirstOrDefault(i => i.Name == itemNameTreePath[nameIndex]); 135 | if (item == null) return null; 136 | 137 | itemCollection = item.Items; 138 | } 139 | return item; 140 | } 141 | internal static MenuModelItem RequestItem(IEnumerable rootItems, string[] itemNameTreePath, Action addAction, Action configureAction) 142 | { 143 | // Check if such item already exists. Returns it, if it does. 144 | { 145 | MenuModelItem existingItem = GetItemDeep(rootItems, itemNameTreePath); 146 | if (existingItem != null) return existingItem; 147 | } 148 | 149 | // Create an item that matches the specified full name 150 | MenuModelItem resultItem = null; 151 | { 152 | // Create the root item 153 | MenuModelItem item = rootItems.FirstOrDefault(c => string.Equals(c.Name, itemNameTreePath[0], StringComparison.InvariantCultureIgnoreCase)); 154 | if (item == null) 155 | { 156 | item = new MenuModelItem(itemNameTreePath[0]); 157 | if (configureAction != null) 158 | configureAction(item); 159 | addAction(item); 160 | } 161 | 162 | // Create subsequent items 163 | resultItem = item; 164 | for (int i = 1; i < itemNameTreePath.Length; i++) 165 | { 166 | resultItem = item.Items.FirstOrDefault(c => string.Equals(c.Name, itemNameTreePath[i], StringComparison.InvariantCultureIgnoreCase)); 167 | if (resultItem == null) 168 | { 169 | resultItem = new MenuModelItem(itemNameTreePath[i]); 170 | if (configureAction != null) 171 | configureAction(resultItem); 172 | item.AddItem(resultItem); 173 | } 174 | item = resultItem; 175 | } 176 | } 177 | 178 | return resultItem; 179 | } 180 | } 181 | } 182 | -------------------------------------------------------------------------------- /WinForms/ColorControls/ColorPickerDialog.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 122 | AAEAAAD/////AQAAAAAAAAAMAgAAAFFTeXN0ZW0uRHJhd2luZywgVmVyc2lvbj00LjAuMC4wLCBDdWx0 123 | dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWIwM2Y1ZjdmMTFkNTBhM2EFAQAAABVTeXN0ZW0uRHJh 124 | d2luZy5Qb2ludEYCAAAAAXgBeQAACwsCAAAAAAAAPwAAAD8L 125 | 126 | 127 | -------------------------------------------------------------------------------- /WinForms/TimelineControls/Models/TimelineLinearGraphModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace AdamsLair.WinForms.TimelineControls 7 | { 8 | public class TimelineLinearGraphModel : ITimelineGraphModel 9 | { 10 | public struct Key : IComparable, IEquatable 11 | { 12 | public float X; 13 | public float Y; 14 | 15 | public Key(float x, float y) 16 | { 17 | this.X = x; 18 | this.Y = y; 19 | } 20 | 21 | int IComparable.CompareTo(Key other) 22 | { 23 | return this.X.CompareTo(other.X); 24 | } 25 | bool IEquatable.Equals(Key other) 26 | { 27 | return this.X == other.X && this.Y == other.Y; 28 | } 29 | } 30 | 31 | private List values = new List(); 32 | private float minSampleDist = float.MaxValue; 33 | 34 | public event EventHandler GraphChanged; 35 | 36 | public float EndTime 37 | { 38 | get { return this.values.Count > 0 ? this.values[this.values.Count - 1].X : 0.0f; } 39 | } 40 | public float BeginTime 41 | { 42 | get { return this.values.Count > 0 ? this.values[0].X : 0.0f; } 43 | } 44 | public IEnumerable Samples 45 | { 46 | get { return this.values; } 47 | set 48 | { 49 | if (value != this.values) 50 | { 51 | List newSamples = value.ToList(); 52 | this.Clear(); 53 | this.AddRange(newSamples); 54 | } 55 | } 56 | } 57 | 58 | 59 | public TimelineLinearGraphModel() {} 60 | public TimelineLinearGraphModel(IEnumerable samples) 61 | { 62 | this.values = samples.ToList(); 63 | this.values.Sort(); 64 | } 65 | public TimelineLinearGraphModel(IEnumerable samples, float sampleRate, float startX = 0.0f) 66 | { 67 | int sampleCount = samples.Count(); 68 | this.values.Capacity = sampleCount; 69 | 70 | float x = startX; 71 | float xPerSample = 1.0f / sampleRate; 72 | foreach (float y in samples) 73 | { 74 | this.values.Add(new Key(x, y)); 75 | x += xPerSample; 76 | } 77 | } 78 | 79 | public void AddRange(IEnumerable values) 80 | { 81 | this.values.AddRange(values); 82 | this.values.Sort(); 83 | this.UpdateMinSampleDist(); 84 | this.RaiseGraphChanged(values.Min(v => v.X), values.Max(v => v.X)); 85 | } 86 | public void Add(Key frame) 87 | { 88 | int insertIndex = this.SearchIndexBelow(frame.X) + 1; 89 | 90 | if (insertIndex >= this.values.Count) 91 | this.values.Add(frame); 92 | else if (this.values[insertIndex].X == frame.X) 93 | this.values[insertIndex] = frame; 94 | else 95 | this.values.Insert(insertIndex, frame); 96 | 97 | if (insertIndex > 0) 98 | this.minSampleDist = Math.Min(this.minSampleDist, this.values[insertIndex].X - this.values[insertIndex - 1].X); 99 | if (insertIndex + 1 < this.values.Count) 100 | this.minSampleDist = Math.Min(this.minSampleDist, this.values[insertIndex + 1].X - this.values[insertIndex].X); 101 | 102 | this.RaiseGraphChanged(frame.X); 103 | } 104 | public void Add(float x, float y) 105 | { 106 | this.Add(new Key(x, y)); 107 | } 108 | public void Remove(float x) 109 | { 110 | this.values.RemoveAll(f => f.X == x); 111 | this.UpdateMinSampleDist(); 112 | this.RaiseGraphChanged(x); 113 | } 114 | public void Clear() 115 | { 116 | float begin = this.BeginTime; 117 | float end = this.EndTime; 118 | this.values.Clear(); 119 | this.minSampleDist = float.MaxValue; 120 | this.RaiseGraphChanged(begin, end); 121 | } 122 | 123 | public float GetValueAtX(float time) 124 | { 125 | int frameCount = this.values.Count; 126 | if (frameCount == 0) return 0.0f; 127 | 128 | int baseIndex = this.SearchIndexBelow(time); 129 | if (baseIndex < 0) return this.values[0].Y; 130 | if (baseIndex == frameCount - 1) return this.values[frameCount - 1].Y; 131 | 132 | int nextIndex = (baseIndex + 1) % frameCount; 133 | float nextX = this.values[nextIndex].X; 134 | if (nextX < this.values[baseIndex].X) nextX += this.EndTime; 135 | 136 | float factor = Math.Max(Math.Min((time - this.values[baseIndex].X) / (nextX - this.values[baseIndex].X), 1.0f), 0.0f); 137 | return this.values[baseIndex].Y * (1.0f - factor) + this.values[nextIndex].Y * factor; 138 | } 139 | public float GetMaxValueInRange(float begin, float end) 140 | { 141 | int frameCount = this.values.Count; 142 | if (frameCount == 0) return 0.0f; 143 | 144 | float result = Math.Max(this.GetValueAtX(begin), this.GetValueAtX(end)); 145 | int index = this.SearchIndexBelow(begin) + 1; 146 | while (index < this.values.Count && this.values[index].X < end) 147 | { 148 | result = Math.Max(result, this.values[index].Y); 149 | index++; 150 | } 151 | 152 | return result; 153 | } 154 | public float GetMinValueInRange(float begin, float end) 155 | { 156 | int frameCount = this.values.Count; 157 | if (frameCount == 0) return 0.0f; 158 | 159 | float result = Math.Min(this.GetValueAtX(begin), this.GetValueAtX(end)); 160 | int index = this.SearchIndexBelow(begin) + 1; 161 | while (index < this.values.Count && this.values[index].X < end) 162 | { 163 | result = Math.Min(result, this.values[index].Y); 164 | index++; 165 | } 166 | 167 | return result; 168 | } 169 | 170 | private int SearchIndexBelow(float x) 171 | { 172 | int left = 0; 173 | int right = this.values.Count - 1; 174 | while (right >= left) 175 | { 176 | int mid = (left + right) / 2; 177 | float midTime = this.values[mid].X; 178 | if (midTime > x) 179 | { 180 | right = mid - 1; 181 | } 182 | else if (midTime <= x) 183 | { 184 | if (left != mid) 185 | { 186 | left = mid; 187 | } 188 | else 189 | { 190 | float rightTime = this.values[right].X; 191 | if (rightTime <= x) 192 | return right; 193 | else 194 | return left; 195 | } 196 | } 197 | else if (left == right) 198 | { 199 | break; 200 | } 201 | } 202 | return -1; 203 | } 204 | private void UpdateMinSampleDist() 205 | { 206 | this.minSampleDist = float.MaxValue; 207 | for (int i = 1; i < this.values.Count; i++) 208 | { 209 | this.minSampleDist = Math.Min(this.minSampleDist, this.values[i].X - this.values[i - 1].X); 210 | } 211 | } 212 | 213 | private void RaiseGraphChanged(float at) 214 | { 215 | this.RaiseGraphChanged(at, at); 216 | } 217 | private void RaiseGraphChanged(float from, float to) 218 | { 219 | // Expand the specified range due to linear interpolation changes 220 | int belowIndex = this.SearchIndexBelow(from); 221 | int aboveIndex = this.SearchIndexBelow(to); 222 | if (belowIndex != -1) from = this.values[belowIndex].X; 223 | if (aboveIndex != -1) to = (aboveIndex + 1 < this.values.Count) ? this.values[aboveIndex + 1].X : this.EndTime; 224 | 225 | if (this.GraphChanged != null) 226 | this.GraphChanged(this, new TimelineGraphRangeEventArgs(this, from, to)); 227 | } 228 | } 229 | } 230 | -------------------------------------------------------------------------------- /TestApp/Properties/Resources.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 122 | ..\Resources\ItemBig.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 123 | 124 | 125 | ..\Resources\ItemHigh.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 126 | 127 | 128 | ..\Resources\ItemSmall.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 129 | 130 | 131 | ..\Resources\ItemWide.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 132 | 133 | -------------------------------------------------------------------------------- /TestApp/DemoForm.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 122 | AAEAAAD/////AQAAAAAAAAAMAgAAAFFTeXN0ZW0uRHJhd2luZywgVmVyc2lvbj00LjAuMC4wLCBDdWx0 123 | dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWIwM2Y1ZjdmMTFkNTBhM2EFAQAAABVTeXN0ZW0uRHJh 124 | d2luZy5Qb2ludEYCAAAAAXgBeQAACwsCAAAAAAAAPwAAAD8L 125 | 126 | 127 | 128 | 129 | AAEAAAD/////AQAAAAAAAAAMAgAAAFFTeXN0ZW0uRHJhd2luZywgVmVyc2lvbj00LjAuMC4wLCBDdWx0 130 | dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWIwM2Y1ZjdmMTFkNTBhM2EFAQAAABVTeXN0ZW0uRHJh 131 | d2luZy5Qb2ludEYCAAAAAXgBeQAACwsCAAAAAAAAPwAAAD8L 132 | 133 | 134 | 135 | 136 | AAEAAAD/////AQAAAAAAAAAMAgAAAFFTeXN0ZW0uRHJhd2luZywgVmVyc2lvbj00LjAuMC4wLCBDdWx0 137 | dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWIwM2Y1ZjdmMTFkNTBhM2EFAQAAABVTeXN0ZW0uRHJh 138 | d2luZy5Qb2ludEYCAAAAAXgBeQAACwsCAAAAAAAAPwAAAD8L 139 | 140 | 141 | 142 | 17, 17 143 | 144 | -------------------------------------------------------------------------------- /.nuget/NuGet.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $(MSBuildProjectDirectory)\..\ 5 | 6 | 7 | true 8 | 9 | 10 | false 11 | 12 | 13 | false 14 | 15 | 16 | false 17 | 18 | 19 | 20 | 21 | 25 | 26 | 27 | 28 | 29 | $([System.IO.Path]::Combine($(SolutionDir), ".nuget")) 30 | $([System.IO.Path]::Combine($(ProjectDir), "packages.config")) 31 | 32 | 33 | 34 | 35 | $(SolutionDir).nuget 36 | packages.config 37 | 38 | 39 | 40 | 41 | $(NuGetToolsPath)\nuget.exe 42 | @(PackageSource) 43 | 44 | "$(NuGetExePath)" 45 | mono --runtime=v4.0.30319 $(NuGetExePath) 46 | 47 | $(TargetDir.Trim('\\')) 48 | 49 | -RequireConsent 50 | 51 | $(NuGetCommand) install "$(PackagesConfig)" -source "$(PackageSources)" $(RequireConsentSwitch) -solutionDir "$(SolutionDir) " 52 | $(NuGetCommand) pack "$(ProjectPath)" -p Configuration=$(Configuration) -o "$(PackageOutputDir)" -symbols 53 | 54 | 55 | 56 | RestorePackages; 57 | $(ResolveReferencesDependsOn); 58 | 59 | 60 | 61 | 62 | $(BuildDependsOn); 63 | BuildPackage; 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 89 | 90 | 93 | 94 | 95 | 96 | 98 | 99 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 150 | 151 | 152 | 153 | -------------------------------------------------------------------------------- /WinForms/TimelineControls/TimelineViewTrack.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Drawing; 6 | using System.Windows.Forms; 7 | 8 | namespace AdamsLair.WinForms.TimelineControls 9 | { 10 | public abstract class TimelineViewTrack 11 | { 12 | private TimelineView parentView = null; 13 | private ITimelineTrackModel model = null; 14 | private int baseHeight = 100; 15 | private int fillHeight = 0; 16 | 17 | private int height; 18 | private float contentBeginTime; 19 | private float contentEndTime; 20 | 21 | 22 | public event EventHandler ContentWidthChanged = null; 23 | public event EventHandler HeightChanged = null; 24 | public event EventHandler HeightSettingsChanged = null; 25 | 26 | 27 | public TimelineView ParentView 28 | { 29 | get { return this.parentView; } 30 | internal set 31 | { 32 | if (this.parentView != null) 33 | { 34 | this.parentView.Resize -= this.parentView_Resize; 35 | this.parentView.UnitZoomChanged -= this.parentView_UnitZoomChanged; 36 | this.parentView.ViewScrolled -= this.parentView_ViewScrolled; 37 | this.parentView.UnitChanged -= this.parentView_UnitChanged; 38 | } 39 | this.parentView = value; 40 | if (this.parentView != null) 41 | { 42 | this.parentView.Resize += this.parentView_Resize; 43 | this.parentView.UnitZoomChanged += this.parentView_UnitZoomChanged; 44 | this.parentView.ViewScrolled += this.parentView_ViewScrolled; 45 | this.parentView.UnitChanged += this.parentView_UnitChanged; 46 | } 47 | } 48 | } 49 | 50 | public ITimelineTrackModel Model 51 | { 52 | get { return this.model; } 53 | internal set 54 | { 55 | if (this.model != value) 56 | { 57 | TimelineTrackModelChangedEventArgs args = new TimelineTrackModelChangedEventArgs(this.model, value); 58 | this.model = value; 59 | this.OnModelChanged(args); 60 | } 61 | } 62 | } 63 | public int BaseHeight 64 | { 65 | get { return this.baseHeight; } 66 | set 67 | { 68 | if (this.baseHeight != value) 69 | { 70 | this.baseHeight = value; 71 | this.OnHeightSettingsChanged(); 72 | } 73 | } 74 | } 75 | public int FillHeight 76 | { 77 | get { return this.fillHeight; } 78 | set 79 | { 80 | if (this.fillHeight != value) 81 | { 82 | this.fillHeight = value; 83 | this.OnHeightSettingsChanged(); 84 | } 85 | } 86 | } 87 | public int Height 88 | { 89 | get { return this.height; } 90 | internal set 91 | { 92 | if (this.height != value) 93 | { 94 | this.height = value; 95 | this.OnHeightChanged(); 96 | } 97 | } 98 | } 99 | public float ContentBeginTime 100 | { 101 | get { return this.contentBeginTime; } 102 | } 103 | public float ContentEndTime 104 | { 105 | get { return this.contentEndTime; } 106 | } 107 | 108 | 109 | public void Invalidate() 110 | { 111 | if (this.parentView == null) return; 112 | 113 | this.Invalidate(this.parentView.UnitScroll, this.parentView.UnitScroll + this.parentView.VisibleUnitWidth); 114 | } 115 | public void Invalidate(float fromUnits, float toUnits) 116 | { 117 | if (this.parentView == null) return; 118 | if (fromUnits > toUnits) 119 | { 120 | float temp = fromUnits; 121 | fromUnits = toUnits; 122 | toUnits = temp; 123 | } 124 | 125 | Rectangle rectOnParent = this.parentView.GetTrackRectangle(this); 126 | 127 | float fromPixels = Math.Max(this.parentView.GetPosAtUnit(fromUnits), rectOnParent.Left + this.parentView.LeftSidebarSize) - 1; 128 | float toPixels = Math.Min(this.parentView.GetPosAtUnit(toUnits), rectOnParent.Right - this.parentView.RightSidebarSize) + 2; 129 | 130 | Rectangle targetRect = new Rectangle( 131 | (int)fromPixels, 132 | rectOnParent.Y, 133 | (int)(toPixels - fromPixels), 134 | rectOnParent.Height); 135 | rectOnParent.Intersect(targetRect); 136 | rectOnParent.Intersect(this.parentView.ClientRectangle); 137 | if (rectOnParent.IsEmpty) return; 138 | 139 | this.parentView.Invalidate(rectOnParent); 140 | } 141 | public void InvalidateLeftSidebar() 142 | { 143 | if (this.parentView == null) return; 144 | 145 | Rectangle trackRect = this.parentView.GetTrackRectangle(this); 146 | Rectangle rectOnParent; 147 | Rectangle targetRect; 148 | 149 | rectOnParent = trackRect; 150 | targetRect = new Rectangle( 151 | rectOnParent.X, 152 | rectOnParent.Y, 153 | this.parentView.LeftSidebarSize, 154 | rectOnParent.Height); 155 | rectOnParent.Intersect(targetRect); 156 | rectOnParent.Intersect(this.parentView.ClientRectangle); 157 | if (!rectOnParent.IsEmpty) 158 | { 159 | this.parentView.Invalidate(rectOnParent); 160 | } 161 | } 162 | public void InvalidateRightSidebar() 163 | { 164 | if (this.parentView == null) return; 165 | 166 | Rectangle trackRect = this.parentView.GetTrackRectangle(this); 167 | Rectangle rectOnParent; 168 | Rectangle targetRect; 169 | 170 | rectOnParent = trackRect; 171 | targetRect = new Rectangle( 172 | rectOnParent.Right - this.parentView.RightSidebarSize, 173 | rectOnParent.Y, 174 | this.parentView.RightSidebarSize, 175 | rectOnParent.Height); 176 | rectOnParent.Intersect(targetRect); 177 | rectOnParent.Intersect(this.parentView.ClientRectangle); 178 | if (!rectOnParent.IsEmpty) 179 | { 180 | this.parentView.Invalidate(rectOnParent); 181 | } 182 | } 183 | 184 | protected internal void UpdateContentWidth() 185 | { 186 | float newBegin; 187 | float newEnd; 188 | this.CalculateContentWidth(out newBegin, out newEnd); 189 | if (newBegin != this.contentBeginTime || newEnd != this.contentEndTime) 190 | { 191 | this.contentBeginTime = newBegin; 192 | this.contentEndTime = newEnd; 193 | this.OnContentWidthChanged(); 194 | } 195 | } 196 | protected virtual void CalculateContentWidth(out float beginTime, out float endTime) 197 | { 198 | beginTime = 0.0f; 199 | endTime = 0.0f; 200 | } 201 | 202 | protected virtual void OnModelChanged(TimelineTrackModelChangedEventArgs e) 203 | { 204 | if (e.OldModel != null) 205 | { 206 | e.OldModel.TrackNameChanged -= this.model_TrackNameChanged; 207 | } 208 | if (e.Model != null) 209 | { 210 | e.Model.TrackNameChanged += this.model_TrackNameChanged; 211 | } 212 | this.UpdateContentWidth(); 213 | this.Invalidate(); 214 | } 215 | protected internal virtual void OnPaint(TimelineViewTrackPaintEventArgs e) {} 216 | protected internal virtual void OnPaintLeftSidebar(TimelineViewTrackPaintEventArgs e) {} 217 | protected internal virtual void OnPaintRightSidebar(TimelineViewTrackPaintEventArgs e) {} 218 | protected internal virtual void OnPaintOverlay(TimelineViewTrackPaintEventArgs e) {} 219 | protected internal virtual void OnMouseEnter(EventArgs e) {} 220 | protected internal virtual void OnMouseLeave(EventArgs e) {} 221 | protected internal virtual void OnMouseMove(MouseEventArgs e) {} 222 | protected internal virtual void OnCursorMove(TimelineViewCursorEventArgs e) { } 223 | protected internal virtual void OnCursorEnter(TimelineViewCursorEventArgs e) { } 224 | protected internal virtual void OnCursorLeave(TimelineViewCursorEventArgs e) { } 225 | protected internal virtual void OnTimeSelectionChanged(TimelineViewSelectionEventArgs e) {} 226 | protected virtual void OnHeightSettingsChanged() 227 | { 228 | if (this.HeightSettingsChanged != null) 229 | this.HeightSettingsChanged(this, EventArgs.Empty); 230 | } 231 | protected virtual void OnHeightChanged() 232 | { 233 | if (this.HeightChanged != null) 234 | this.HeightChanged(this, EventArgs.Empty); 235 | } 236 | protected virtual void OnContentWidthChanged() 237 | { 238 | if (this.ContentWidthChanged != null) 239 | this.ContentWidthChanged(this, EventArgs.Empty); 240 | } 241 | protected virtual void OnViewportChanged() {} 242 | 243 | private void parentView_UnitChanged(object sender, EventArgs e) 244 | { 245 | this.OnViewportChanged(); 246 | } 247 | private void parentView_ViewScrolled(object sender, EventArgs e) 248 | { 249 | this.OnViewportChanged(); 250 | } 251 | private void parentView_UnitZoomChanged(object sender, EventArgs e) 252 | { 253 | this.OnViewportChanged(); 254 | } 255 | private void parentView_Resize(object sender, EventArgs e) 256 | { 257 | this.OnViewportChanged(); 258 | } 259 | private void model_TrackNameChanged(object sender, EventArgs e) 260 | { 261 | this.Invalidate(); 262 | } 263 | } 264 | } 265 | -------------------------------------------------------------------------------- /WinForms/PropertyEditing/EditorTemplates/MultiComboBoxEditorTemplate.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Windows.Forms; 5 | using System.Drawing; 6 | 7 | using AdamsLair.WinForms.Drawing; 8 | using ButtonState = AdamsLair.WinForms.Drawing.ButtonState; 9 | 10 | namespace AdamsLair.WinForms.PropertyEditing.Templates 11 | { 12 | public class MultiComboBoxEditorTemplate : EditorTemplate, IPopupControlHost 13 | { 14 | private const string ClipboardDataFormat = "MultiComboBoxEditorTemplateData"; 15 | 16 | private List selectedObjects = new List(); 17 | private string selectedObjStr = ""; 18 | private bool pressed = false; 19 | private DateTime mouseClosed = DateTime.MinValue; 20 | private int dropdownHeight = 100; 21 | private MultiComboBoxDropDown dropdown = null; 22 | private List dropdownItems = new List(); 23 | private PopupControl popupControl = new PopupControl(); 24 | 25 | public IEnumerable SelectedObjects 26 | { 27 | get { return this.selectedObjects; } 28 | set 29 | { 30 | if (this.IsDropDownOpened) return; // Don't override while the user is selecting 31 | string lastObjStr = this.selectedObjStr; 32 | 33 | this.selectedObjects = value.ToList(); 34 | this.selectedObjStr = this.DefaultValueStringGenerator(this.selectedObjects); 35 | if (this.dropdown != null) 36 | { 37 | for (int i = 0; i < this.dropdown.Items.Count; i++) 38 | this.dropdown.SetItemChecked(i, value.Contains(this.dropdown.Items[i])); 39 | } 40 | 41 | if (lastObjStr != this.selectedObjStr) this.EmitInvalidate(); 42 | } 43 | } 44 | public bool IsDropDownOpened 45 | { 46 | get { return this.dropdown != null; } 47 | } 48 | public object DropDownHoveredObject 49 | { 50 | get 51 | { 52 | if (this.dropdown.HoveredIndex == -1) return null; 53 | return this.dropdown.Items[this.dropdown.HoveredIndex]; 54 | } 55 | } 56 | public int DropDownHeight 57 | { 58 | get { return this.dropdownHeight; } 59 | set { this.dropdownHeight = value; } 60 | } 61 | public IEnumerable DropDownItems 62 | { 63 | get { return this.dropdownItems; } 64 | set 65 | { 66 | this.dropdownItems = value.ToList(); 67 | if (this.dropdown != null) 68 | { 69 | this.dropdown.Items.Clear(); 70 | this.dropdown.Items.AddRange(this.dropdownItems.ToArray()); 71 | } 72 | } 73 | } 74 | 75 | public MultiComboBoxEditorTemplate(PropertyEditor parent) : base(parent) 76 | { 77 | this.popupControl.PopupControlHost = this; 78 | this.popupControl.Closed += this.popupControl_Closed; 79 | } 80 | 81 | public void OnPaint(PaintEventArgs e, bool enabled, bool multiple) 82 | { 83 | ButtonState comboState = ButtonState.Normal; 84 | if (!enabled || this.ReadOnly) 85 | comboState = ButtonState.Disabled; 86 | else if (this.pressed || this.IsDropDownOpened || (this.focused && (Control.ModifierKeys & Keys.Control) == Keys.Control)) 87 | comboState = ButtonState.Pressed; 88 | else if (this.hovered || this.focused) 89 | comboState = ButtonState.Hot; 90 | 91 | ControlRenderer.DrawComboBox(e.Graphics, this.rect, comboState, this.selectedObjStr); 92 | } 93 | public override void OnLostFocus(EventArgs e) 94 | { 95 | if (this.focused) this.EmitEditingFinished(this.selectedObjects, FinishReason.LostFocus); 96 | base.OnLostFocus(e); 97 | } 98 | public override void OnMouseMove(MouseEventArgs e) 99 | { 100 | base.OnMouseMove(e); 101 | if (this.ReadOnly) this.hovered = false; 102 | } 103 | public void OnMouseDown(MouseEventArgs e) 104 | { 105 | if (this.rect.Contains(e.Location)) 106 | { 107 | if (this.hovered && (e.Button & MouseButtons.Left) != MouseButtons.None && (DateTime.Now - this.mouseClosed).TotalMilliseconds > 200) 108 | { 109 | this.pressed = true; 110 | this.EmitInvalidate(); 111 | } 112 | } 113 | } 114 | public void OnMouseUp(MouseEventArgs e) 115 | { 116 | if (this.pressed && (e.Button & MouseButtons.Left) != MouseButtons.None) 117 | { 118 | if (this.hovered) this.ShowDropDown(); 119 | this.pressed = false; 120 | this.EmitInvalidate(); 121 | } 122 | } 123 | public void OnKeyUp(KeyEventArgs e) 124 | { 125 | if (e.KeyCode == Keys.ControlKey) 126 | this.EmitInvalidate(); 127 | } 128 | public void OnKeyDown(KeyEventArgs e) 129 | { 130 | if (e.KeyCode == Keys.ControlKey) 131 | this.EmitInvalidate(); 132 | 133 | if (e.KeyCode == Keys.Return || e.KeyCode == Keys.Right || (e.KeyCode == Keys.Down && e.Control)) 134 | { 135 | this.ShowDropDown(); 136 | e.Handled = true; 137 | } 138 | else if (e.Control && e.KeyCode == Keys.C) 139 | { 140 | DataObject data = new DataObject(); 141 | data.SetText(this.selectedObjStr); 142 | data.SetData(ClipboardDataFormat, this.selectedObjects); 143 | Clipboard.SetDataObject(data); 144 | e.Handled = true; 145 | } 146 | else if (e.Control && e.KeyCode == Keys.V) 147 | { 148 | bool success = false; 149 | List pasteObjProxy = null; 150 | if (Clipboard.ContainsData(ClipboardDataFormat)) 151 | { 152 | List pasteObj = Clipboard.GetData(ClipboardDataFormat) as List; 153 | pasteObjProxy = pasteObj.Select(p => this.dropdownItems.FirstOrDefault(obj => object.Equals(obj, p))).Where(o => o != null).ToList(); 154 | } 155 | else if (Clipboard.ContainsText()) 156 | { 157 | string[] pasteObj = Clipboard.GetText().Split(new [] { ", " }, StringSplitOptions.RemoveEmptyEntries); 158 | pasteObjProxy = pasteObj.Select(p => this.dropdownItems.FirstOrDefault(obj => obj != null && p == obj.ToString())).ToList(); 159 | } 160 | if (pasteObjProxy != null && pasteObjProxy.Count > 0) 161 | { 162 | this.selectedObjects = pasteObjProxy; 163 | this.selectedObjStr = this.DefaultValueStringGenerator(this.selectedObjects); 164 | this.EmitInvalidate(); 165 | this.EmitEdited(this.selectedObjects); 166 | success = true; 167 | } 168 | if (!success) System.Media.SystemSounds.Beep.Play(); 169 | e.Handled = true; 170 | } 171 | } 172 | 173 | public void ShowDropDown() 174 | { 175 | if (this.dropdown != null) return; 176 | if (this.ReadOnly) return; 177 | PropertyGrid parentGrid = this.Parent.ParentGrid; 178 | 179 | this.dropdown = new MultiComboBoxDropDown(this.dropdownItems); 180 | for (int i = 0; i < this.dropdown.Items.Count; i++) 181 | this.dropdown.SetItemChecked(i, this.selectedObjects.Contains(this.dropdown.Items[i])); 182 | 183 | Size dropDownSize = new Size( 184 | this.rect.Width, 185 | Math.Min(this.dropdownHeight, this.dropdown.PreferredHeight)); 186 | 187 | Point dropDownLoc = new Point( 188 | this.rect.X + parentGrid.AutoScrollPosition.X, 189 | this.rect.Y + parentGrid.AutoScrollPosition.Y); 190 | dropDownLoc.Y += this.rect.Height + 1; 191 | 192 | this.dropdown.Location = dropDownLoc; 193 | this.dropdown.Size = dropDownSize; 194 | this.dropdown.RequestClose += this.dropdown_RequestClose; 195 | this.dropdown.AcceptSelection += this.dropdown_AcceptSelection; 196 | 197 | this.popupControl.Show(parentGrid, this.dropdown, dropDownLoc.X, dropDownLoc.Y, dropDownSize.Width, dropDownSize.Height, PopupResizeMode.None); 198 | 199 | this.EmitInvalidate(); 200 | } 201 | public void HideDropDown() 202 | { 203 | if (this.dropdown == null) return; 204 | if (!this.dropdown.Disposing && !this.dropdown.IsDisposed) 205 | this.dropdown.Dispose(); 206 | this.dropdown = null; 207 | 208 | this.EmitInvalidate(); 209 | } 210 | private void dropdown_RequestClose(object sender, EventArgs e) 211 | { 212 | this.HideDropDown(); 213 | } 214 | private void dropdown_AcceptSelection(object sender, EventArgs e) 215 | { 216 | if (this.selectedObjects.Any(o => !this.dropdown.CheckedItems.Contains(o)) || 217 | this.dropdown.CheckedItems.Cast().Any(o => !this.selectedObjects.Contains(o))) 218 | { 219 | this.selectedObjects = this.dropdown.CheckedItems.Cast().ToList(); 220 | this.selectedObjStr = this.DefaultValueStringGenerator(this.selectedObjects); 221 | this.EmitInvalidate(); 222 | this.EmitEdited(this.selectedObjects); 223 | } 224 | } 225 | private void popupControl_Closed(object sender, ToolStripDropDownClosedEventArgs e) 226 | { 227 | this.HideDropDown(); 228 | this.mouseClosed = DateTime.Now; 229 | } 230 | 231 | protected string DefaultValueStringGenerator(IEnumerable objEnum) 232 | { 233 | string valueString = ""; 234 | foreach (object obj in objEnum) 235 | valueString += (valueString.Length > 0 ? ", " : "") + obj.ToString(); 236 | return valueString; 237 | } 238 | } 239 | } 240 | -------------------------------------------------------------------------------- /WinForms/PropertyEditing/EditorTemplates/BitmaskEditorTemplate.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Windows.Forms; 5 | using System.Drawing; 6 | 7 | using AdamsLair.WinForms.Drawing; 8 | using ButtonState = AdamsLair.WinForms.Drawing.ButtonState; 9 | 10 | namespace AdamsLair.WinForms.PropertyEditing.Templates 11 | { 12 | public class BitmaskEditorTemplate : EditorTemplate, IPopupControlHost 13 | { 14 | private const string ClipboardDataFormat = "BitmaskEditorTemplateData"; 15 | 16 | private ulong bitmask = 0; 17 | private string bitmaskStr = ""; 18 | private bool pressed = false; 19 | private DateTime mouseClosed = DateTime.MinValue; 20 | private int dropdownHeight = 100; 21 | private BitmaskSelectorDropDown dropdown = null; 22 | private List dropdownItems = new List(); 23 | private PopupControl popupControl = new PopupControl(); 24 | 25 | public ulong BitmaskValue 26 | { 27 | get { return this.bitmask; } 28 | set 29 | { 30 | if (this.IsDropDownOpened) return; // Don't override while the user is selecting 31 | string lastObjStr = this.bitmaskStr; 32 | 33 | this.bitmask = value; 34 | this.bitmaskStr = this.DefaultValueStringGenerator(this.bitmask); 35 | if (this.dropdown != null) this.dropdown.BitmaskValue = this.bitmask; 36 | 37 | if (lastObjStr != this.bitmaskStr) this.EmitInvalidate(); 38 | } 39 | } 40 | public bool IsDropDownOpened 41 | { 42 | get { return this.dropdown != null; } 43 | } 44 | public BitmaskItem DropDownHoveredItem 45 | { 46 | get 47 | { 48 | if (this.dropdown.HoveredIndex == -1) return null; 49 | return this.dropdown.Items.ElementAtOrDefault(this.dropdown.HoveredIndex); 50 | } 51 | } 52 | public int DropDownHeight 53 | { 54 | get { return this.dropdownHeight; } 55 | set { this.dropdownHeight = value; } 56 | } 57 | public IEnumerable DropDownItems 58 | { 59 | get { return this.dropdownItems; } 60 | set 61 | { 62 | this.dropdownItems = value.OrderBy(i => i.Value).ToList(); 63 | if (this.dropdown != null) this.dropdown.Items = this.dropdownItems; 64 | } 65 | } 66 | 67 | public BitmaskEditorTemplate(PropertyEditor parent) : base(parent) 68 | { 69 | this.popupControl.PopupControlHost = this; 70 | this.popupControl.Closed += this.popupControl_Closed; 71 | } 72 | 73 | public void OnPaint(PaintEventArgs e, bool enabled, bool multiple) 74 | { 75 | ButtonState comboState = ButtonState.Normal; 76 | if (!enabled || this.ReadOnly) 77 | comboState = ButtonState.Disabled; 78 | else if (this.pressed || this.IsDropDownOpened || (this.focused && (Control.ModifierKeys & Keys.Control) == Keys.Control)) 79 | comboState = ButtonState.Pressed; 80 | else if (this.hovered || this.focused) 81 | comboState = ButtonState.Hot; 82 | 83 | ControlRenderer.DrawComboBox(e.Graphics, this.rect, comboState, this.bitmaskStr); 84 | } 85 | public override void OnLostFocus(EventArgs e) 86 | { 87 | if (this.focused) this.EmitEditingFinished(this.BitmaskValue, FinishReason.LostFocus); 88 | base.OnLostFocus(e); 89 | } 90 | public override void OnMouseMove(MouseEventArgs e) 91 | { 92 | base.OnMouseMove(e); 93 | if (this.ReadOnly) this.hovered = false; 94 | } 95 | public void OnMouseDown(MouseEventArgs e) 96 | { 97 | if (this.rect.Contains(e.Location)) 98 | { 99 | if (this.hovered && (e.Button & MouseButtons.Left) != MouseButtons.None && (DateTime.Now - this.mouseClosed).TotalMilliseconds > 200) 100 | { 101 | this.pressed = true; 102 | this.EmitInvalidate(); 103 | } 104 | } 105 | } 106 | public void OnMouseUp(MouseEventArgs e) 107 | { 108 | if (this.pressed && (e.Button & MouseButtons.Left) != MouseButtons.None) 109 | { 110 | if (this.hovered) this.ShowDropDown(); 111 | this.pressed = false; 112 | this.EmitInvalidate(); 113 | } 114 | } 115 | public void OnKeyUp(KeyEventArgs e) 116 | { 117 | if (e.KeyCode == Keys.ControlKey) 118 | this.EmitInvalidate(); 119 | } 120 | public void OnKeyDown(KeyEventArgs e) 121 | { 122 | if (e.KeyCode == Keys.ControlKey) 123 | this.EmitInvalidate(); 124 | 125 | if (e.KeyCode == Keys.Return || e.KeyCode == Keys.Right || (e.KeyCode == Keys.Down && e.Control)) 126 | { 127 | this.ShowDropDown(); 128 | e.Handled = true; 129 | } 130 | else if (e.Control && e.KeyCode == Keys.C) 131 | { 132 | DataObject data = new DataObject(); 133 | data.SetText(this.bitmaskStr); 134 | data.SetData(ClipboardDataFormat, this.bitmask); 135 | Clipboard.SetDataObject(data); 136 | e.Handled = true; 137 | } 138 | else if (e.Control && e.KeyCode == Keys.V) 139 | { 140 | bool success = false; 141 | ulong pasteValue = 0; 142 | if (Clipboard.ContainsData(ClipboardDataFormat)) 143 | { 144 | pasteValue = (ulong)Clipboard.GetData(ClipboardDataFormat); 145 | success = true; 146 | } 147 | else if (Clipboard.ContainsText()) 148 | { 149 | string[] pasteObj = Clipboard.GetText().Split(new [] { ", " }, StringSplitOptions.RemoveEmptyEntries); 150 | foreach (string p in pasteObj) 151 | { 152 | if (p == null) continue; 153 | BitmaskItem item = this.dropdownItems.FirstOrDefault(obj => obj != null && p == obj.ToString()); 154 | if (item != null) 155 | { 156 | pasteValue |= item.Value; 157 | success = true; 158 | } 159 | } 160 | } 161 | if (success) 162 | { 163 | this.bitmask = pasteValue; 164 | this.bitmaskStr = this.DefaultValueStringGenerator(this.bitmask); 165 | this.EmitInvalidate(); 166 | this.EmitEdited(this.bitmask); 167 | } 168 | else 169 | System.Media.SystemSounds.Beep.Play(); 170 | e.Handled = true; 171 | } 172 | } 173 | 174 | public void ShowDropDown() 175 | { 176 | if (this.dropdown != null) return; 177 | if (this.ReadOnly) return; 178 | PropertyGrid parentGrid = this.Parent.ParentGrid; 179 | 180 | this.dropdown = new BitmaskSelectorDropDown(this.dropdownItems); 181 | this.dropdown.BitmaskValue = this.bitmask; 182 | 183 | Size dropDownSize = new Size( 184 | this.rect.Width, 185 | Math.Min( 186 | this.dropdownHeight, 187 | (this.dropdown.ItemHeight * this.dropdown.Items.Count()) + this.dropdown.Margin.Vertical)); 188 | 189 | Point dropDownLoc = new Point( 190 | this.rect.X + parentGrid.AutoScrollPosition.X, 191 | this.rect.Y + parentGrid.AutoScrollPosition.Y); 192 | dropDownLoc.Y += this.rect.Height + 1; 193 | 194 | this.dropdown.Location = dropDownLoc; 195 | this.dropdown.Size = dropDownSize; 196 | this.dropdown.RequestClose += this.dropdown_RequestClose; 197 | this.dropdown.AcceptSelection += this.dropdown_AcceptSelection; 198 | 199 | this.popupControl.Show(parentGrid, this.dropdown, dropDownLoc.X, dropDownLoc.Y, dropDownSize.Width, dropDownSize.Height, PopupResizeMode.None); 200 | 201 | this.EmitInvalidate(); 202 | } 203 | public void HideDropDown() 204 | { 205 | if (this.popupControl.Visible) 206 | this.popupControl.Hide(); 207 | 208 | if (this.dropdown != null) 209 | { 210 | if (!this.dropdown.Disposing && !this.dropdown.IsDisposed) 211 | this.dropdown.Dispose(); 212 | this.dropdown = null; 213 | } 214 | 215 | this.EmitInvalidate(); 216 | } 217 | private void dropdown_RequestClose(object sender, EventArgs e) 218 | { 219 | this.HideDropDown(); 220 | } 221 | private void dropdown_AcceptSelection(object sender, EventArgs e) 222 | { 223 | if (this.bitmask != this.dropdown.BitmaskValue) 224 | { 225 | this.bitmask = this.dropdown.BitmaskValue; 226 | this.bitmaskStr = this.DefaultValueStringGenerator(this.bitmask); 227 | this.EmitInvalidate(); 228 | this.EmitEdited(this.bitmask); 229 | } 230 | } 231 | private void popupControl_Closed(object sender, ToolStripDropDownClosedEventArgs e) 232 | { 233 | this.HideDropDown(); 234 | this.mouseClosed = DateTime.Now; 235 | } 236 | 237 | protected string DefaultValueStringGenerator(ulong bitmask) 238 | { 239 | ulong num = bitmask; 240 | int index = this.dropdownItems.Count - 1; 241 | System.Text.StringBuilder builder = new System.Text.StringBuilder(); 242 | bool flag = true; 243 | ulong num3 = num; 244 | while (index >= 0) 245 | { 246 | if ((index == 0) && (this.dropdownItems[index].Value == 0L)) break; 247 | if ((num & this.dropdownItems[index].Value) == this.dropdownItems[index].Value) 248 | { 249 | num -= this.dropdownItems[index].Value; 250 | if (!flag) builder.Insert(0, ", "); 251 | builder.Insert(0, this.dropdownItems[index].Caption); 252 | flag = false; 253 | } 254 | index--; 255 | } 256 | if (num != 0L) return bitmask.ToString(); 257 | if (num3 != 0L) return builder.ToString(); 258 | if (this.dropdownItems.Count > 0 && this.dropdownItems[0].Value == 0L) return this.dropdownItems[0].Caption; 259 | return "0"; 260 | } 261 | } 262 | } 263 | -------------------------------------------------------------------------------- /WinForms/PropertyEditing/EditorTemplates/ComboBoxEditorTemplate.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Windows.Forms; 5 | using System.Drawing; 6 | 7 | using AdamsLair.WinForms.Drawing; 8 | using ButtonState = AdamsLair.WinForms.Drawing.ButtonState; 9 | 10 | namespace AdamsLair.WinForms.PropertyEditing.Templates 11 | { 12 | public class ComboBoxEditorTemplate : EditorTemplate, IPopupControlHost 13 | { 14 | private const string ClipboardDataFormat = "ComboBoxEditorTemplateData"; 15 | 16 | private object selectedObject = null; 17 | private string selectedObjStr = ""; 18 | private bool pressed = false; 19 | private DateTime mouseClosed = DateTime.MinValue; 20 | private int dropdownHeight = 100; 21 | private ComboBoxDropDown dropdown = null; 22 | private List dropdownItems = new List(); 23 | private PopupControl popupControl = new PopupControl(); 24 | 25 | public object SelectedObject 26 | { 27 | get { return this.selectedObject; } 28 | set 29 | { 30 | if (this.IsDropDownOpened) return; // Don't override while the user is selecting 31 | string lastObjStr = this.selectedObjStr; 32 | 33 | this.selectedObject = value; 34 | this.selectedObjStr = this.DefaultValueStringGenerator(this.selectedObject); 35 | if (this.dropdown != null) this.dropdown.SelectedItem = this.selectedObject; 36 | 37 | if (lastObjStr != this.selectedObjStr) this.EmitInvalidate(); 38 | } 39 | } 40 | public bool IsDropDownOpened 41 | { 42 | get { return this.dropdown != null; } 43 | } 44 | public object DropDownHoveredObject 45 | { 46 | get 47 | { 48 | if (this.dropdown.HoveredIndex == -1) return null; 49 | return this.dropdown.Items[this.dropdown.HoveredIndex]; 50 | } 51 | } 52 | public int DropDownHeight 53 | { 54 | get { return this.dropdownHeight; } 55 | set { this.dropdownHeight = value; } 56 | } 57 | public IEnumerable DropDownItems 58 | { 59 | get { return this.dropdownItems; } 60 | set 61 | { 62 | this.dropdownItems = value.ToList(); 63 | if (this.dropdown != null) 64 | { 65 | this.dropdown.Items.Clear(); 66 | this.dropdown.Items.AddRange(this.dropdownItems.ToArray()); 67 | } 68 | } 69 | } 70 | 71 | public ComboBoxEditorTemplate(PropertyEditor parent) : base(parent) 72 | { 73 | this.popupControl.PopupControlHost = this; 74 | this.popupControl.Closed += this.popupControl_Closed; 75 | } 76 | 77 | public void OnPaint(PaintEventArgs e, bool enabled, bool multiple) 78 | { 79 | ButtonState comboState = ButtonState.Normal; 80 | if (!enabled || this.ReadOnly) 81 | comboState = ButtonState.Disabled; 82 | else if (this.pressed || this.IsDropDownOpened || (this.focused && (Control.ModifierKeys & Keys.Control) == Keys.Control)) 83 | comboState = ButtonState.Pressed; 84 | else if (this.hovered || this.focused) 85 | comboState = ButtonState.Hot; 86 | 87 | ControlRenderer.DrawComboBox(e.Graphics, this.rect, comboState, this.selectedObjStr); 88 | } 89 | public override void OnLostFocus(EventArgs e) 90 | { 91 | if (this.focused) this.EmitEditingFinished(this.selectedObject, FinishReason.LostFocus); 92 | base.OnLostFocus(e); 93 | } 94 | public override void OnMouseMove(MouseEventArgs e) 95 | { 96 | base.OnMouseMove(e); 97 | if (this.ReadOnly) this.hovered = false; 98 | } 99 | public void OnMouseDown(MouseEventArgs e) 100 | { 101 | if (this.rect.Contains(e.Location)) 102 | { 103 | if (this.hovered && (e.Button & MouseButtons.Left) != MouseButtons.None && (DateTime.Now - this.mouseClosed).TotalMilliseconds > 200) 104 | { 105 | this.pressed = true; 106 | this.EmitInvalidate(); 107 | } 108 | } 109 | } 110 | public void OnMouseUp(MouseEventArgs e) 111 | { 112 | if (this.pressed && (e.Button & MouseButtons.Left) != MouseButtons.None) 113 | { 114 | if (this.hovered) this.ShowDropDown(); 115 | this.pressed = false; 116 | this.EmitInvalidate(); 117 | } 118 | } 119 | public void OnKeyUp(KeyEventArgs e) 120 | { 121 | if (e.KeyCode == Keys.ControlKey) 122 | this.EmitInvalidate(); 123 | } 124 | public void OnKeyDown(KeyEventArgs e) 125 | { 126 | if (e.KeyCode == Keys.ControlKey) 127 | this.EmitInvalidate(); 128 | 129 | if (e.KeyCode == Keys.Return || e.KeyCode == Keys.Right) 130 | { 131 | this.ShowDropDown(); 132 | e.Handled = true; 133 | } 134 | else if (e.KeyCode == Keys.Down && e.Control) 135 | { 136 | this.ShowDropDown(); 137 | //int index = this.dropdownItems.IndexOf(this.selectedObject); 138 | //this.selectedObject = this.dropdownItems[(index + 1) % this.dropdownItems.Count]; 139 | //this.EmitEdited(); 140 | e.Handled = true; 141 | } 142 | else if (e.KeyCode == Keys.Up && e.Control) 143 | { 144 | this.ShowDropDown(); 145 | //int index = this.dropdownItems.IndexOf(this.selectedObject); 146 | //this.selectedObject = this.dropdownItems[(index + this.dropdownItems.Count - 1) % this.dropdownItems.Count]; 147 | //this.EmitEdited(); 148 | e.Handled = true; 149 | } 150 | else if (e.Control && e.KeyCode == Keys.C) 151 | { 152 | if (this.selectedObject != null) 153 | { 154 | DataObject data = new DataObject(); 155 | data.SetText(this.selectedObjStr); 156 | data.SetData(ClipboardDataFormat, this.selectedObject); 157 | Clipboard.SetDataObject(data); 158 | } 159 | else 160 | Clipboard.Clear(); 161 | e.Handled = true; 162 | } 163 | else if (e.Control && e.KeyCode == Keys.V) 164 | { 165 | bool success = false; 166 | if (Clipboard.ContainsData(ClipboardDataFormat) || Clipboard.ContainsText()) 167 | { 168 | object pasteObjProxy = null; 169 | if (Clipboard.ContainsData(ClipboardDataFormat)) 170 | { 171 | object pasteObj = Clipboard.GetData(ClipboardDataFormat); 172 | pasteObjProxy = this.dropdownItems.FirstOrDefault(obj => object.Equals(obj, pasteObj)); 173 | } 174 | else if (Clipboard.ContainsText()) 175 | { 176 | string pasteObj = Clipboard.GetText(); 177 | pasteObjProxy = this.dropdownItems.FirstOrDefault(obj => obj != null && obj.ToString() == pasteObj); 178 | } 179 | if (pasteObjProxy != null) 180 | { 181 | if (this.selectedObject != pasteObjProxy) 182 | { 183 | this.selectedObject = pasteObjProxy; 184 | this.selectedObjStr = this.DefaultValueStringGenerator(this.selectedObject); 185 | this.EmitInvalidate(); 186 | this.EmitEdited(this.selectedObject); 187 | } 188 | success = true; 189 | } 190 | } 191 | if (!success) System.Media.SystemSounds.Beep.Play(); 192 | e.Handled = true; 193 | } 194 | } 195 | 196 | public void ShowDropDown() 197 | { 198 | if (this.dropdown != null) return; 199 | if (this.ReadOnly) return; 200 | PropertyGrid parentGrid = this.Parent.ParentGrid; 201 | 202 | this.dropdown = new ComboBoxDropDown(this.dropdownItems); 203 | this.dropdown.SelectedItem = this.selectedObject; 204 | 205 | Size dropDownSize = new Size( 206 | this.rect.Width, 207 | Math.Min(this.dropdownHeight, this.dropdown.PreferredHeight)); 208 | 209 | Point dropDownLoc = new Point( 210 | this.rect.X + parentGrid.AutoScrollPosition.X, 211 | this.rect.Y + parentGrid.AutoScrollPosition.Y); 212 | dropDownLoc.Y += this.rect.Height + 1; 213 | 214 | this.dropdown.Location = dropDownLoc; 215 | this.dropdown.Size = dropDownSize; 216 | this.dropdown.AcceptSelection += this.dropdown_AcceptSelection; 217 | this.dropdown.RequestClose += this.dropdown_RequestClose; 218 | 219 | this.popupControl.Show(parentGrid, this.dropdown, dropDownLoc.X, dropDownLoc.Y, dropDownSize.Width, dropDownSize.Height, PopupResizeMode.None); 220 | 221 | this.EmitInvalidate(); 222 | } 223 | public void HideDropDown() 224 | { 225 | if (this.popupControl.Visible) 226 | this.popupControl.Hide(); 227 | 228 | if (this.dropdown != null) 229 | { 230 | if (!this.dropdown.Disposing && !this.dropdown.IsDisposed) 231 | this.dropdown.Dispose(); 232 | this.dropdown = null; 233 | } 234 | 235 | this.EmitInvalidate(); 236 | } 237 | private void dropdown_AcceptSelection(object sender, EventArgs e) 238 | { 239 | if (this.selectedObject != this.dropdown.SelectedItem) 240 | { 241 | this.selectedObject = this.dropdown.SelectedItem; 242 | this.selectedObjStr = this.DefaultValueStringGenerator(this.selectedObject); 243 | this.EmitInvalidate(); 244 | this.EmitEdited(this.selectedObject); 245 | } 246 | } 247 | private void dropdown_RequestClose(object sender, EventArgs e) 248 | { 249 | this.HideDropDown(); 250 | } 251 | private void popupControl_Closed(object sender, ToolStripDropDownClosedEventArgs e) 252 | { 253 | this.HideDropDown(); 254 | this.mouseClosed = DateTime.Now; 255 | } 256 | 257 | protected string DefaultValueStringGenerator(object obj) 258 | { 259 | return this.selectedObject != null ? this.selectedObject.ToString() : ""; 260 | } 261 | } 262 | } 263 | --------------------------------------------------------------------------------