/* Copyright (C) 2014-2019 de4dot@gmail.com This file is part of dnSpy dnSpy is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. dnSpy is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with dnSpy. If not, see . */ using System; using System.ComponentModel; namespace dnSpy.Contracts.Controls.ToolWindows { /// /// options /// [Flags] public enum EditableValueOptions { /// /// No bit is set /// None = 0, /// /// Single click to edit text /// SingleClick = 0x00000001, } /// /// Implemented by data that can be edited /// public interface IEditableValue : INotifyPropertyChanged { /// /// Gets the options /// EditableValueOptions Options { get; } /// /// true if the value can be edited, false if it's read-only /// bool CanEdit { get; } /// /// When true is written to this property, the edit textbox is made visible and the /// user can edit the value. The control will write false to it when the edit operation /// is completed (eg. the user hit enter or escape.) /// The control also writes true to this property if the user double clicks it. /// bool IsEditingValue { get; set; } /// /// Returns the text shown in the control /// /// EditableValueTextInfo GetText(); /// /// The control calls this method to write the new value /// /// New text void SetText(string text); } /// /// Edit value flags /// [Flags] public enum EditValueFlags { /// /// No bit is set /// None = 0, /// /// Select the text /// SelectText = 0x00000001, } /// /// Contains the text to edit /// public readonly struct EditableValueTextInfo { /// /// Gets the text /// public string Text { get; } /// /// Flags /// public EditValueFlags Flags { get; } /// /// Constructor /// /// Text to edit /// Flags public EditableValueTextInfo(string text, EditValueFlags flags = EditValueFlags.SelectText) { Text = text ?? throw new ArgumentNullException(nameof(text)); Flags = flags; } } abstract class EditableValue : IEditableValue { public event PropertyChangedEventHandler? PropertyChanged; public virtual EditableValueOptions Options => EditableValueOptions.None; public virtual bool CanEdit => true; public bool IsEditingValue { get => isEditingValue; set { if (isEditingValue == value) return; isEditingValue = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsEditingValue))); } } bool isEditingValue; public abstract EditableValueTextInfo GetText(); public abstract void SetText(string text); } sealed class EditableValueImpl : EditableValue { readonly Func getText; readonly Action setText; readonly Func canEdit; static readonly Func defaultCanEdit = () => true; public override EditableValueOptions Options { get; } public override bool CanEdit => canEdit(); public EditableValueImpl(Func getText, Action setText, Func? canEdit = null, EditableValueOptions options = EditableValueOptions.None) { if (getText is null) throw new ArgumentNullException(nameof(getText)); this.getText = () => new EditableValueTextInfo(getText() ?? string.Empty); this.setText = setText ?? throw new ArgumentNullException(nameof(setText)); this.canEdit = canEdit ?? defaultCanEdit; Options = options; } public EditableValueImpl(Func getText, Action setText, Func? canEdit = null, EditableValueOptions options = EditableValueOptions.None) { this.getText = getText ?? throw new ArgumentNullException(nameof(getText)); this.setText = setText ?? throw new ArgumentNullException(nameof(setText)); this.canEdit = canEdit ?? defaultCanEdit; Options = options; } public override EditableValueTextInfo GetText() => getText(); public override void SetText(string text) => setText(text); } }