├── SimpleDota2EditorWPF ├── Properties │ ├── Resources.ru-RU.Designer.cs │ ├── Settings.settings │ ├── Settings.Designer.cs │ └── AssemblyInfo.cs ├── Images │ ├── Up.png │ ├── Down.png │ ├── Items.ico │ ├── Units.ico │ ├── Units.png │ ├── about.png │ ├── close.png │ ├── exit.png │ ├── help.png │ ├── open.png │ ├── redo.ico │ ├── save.png │ ├── undo.ico │ ├── AutoTab.png │ ├── Comment.png │ ├── Delete.png │ ├── EditKV.png │ ├── Folder.png │ ├── Heroes.ico │ ├── Heroes.png │ ├── Object.png │ ├── Rename.png │ ├── Abilities.ico │ ├── CreateKV.png │ ├── FindHide.png │ ├── FindNext.png │ ├── FindPrev.png │ ├── FindShow.png │ ├── UnComment.png │ ├── settings.png │ ├── FolderClosed.png │ ├── CreateKVBlock.png │ ├── FolderOpenned.png │ └── AbilitiesOverride.ico ├── App.xaml ├── packages.config ├── ScriptsUtils │ └── KV │ │ ├── BasicCompletionValues.kv │ │ ├── BasicCompletionKV.cs │ │ ├── KVScriptResourcesKeys.Designer.cs │ │ ├── KVScriptResourcesValues.Designer.cs │ │ ├── KVScriptResourcesKeys.resx │ │ └── KVScriptResourcesValues.resx ├── App.config ├── App.xaml.cs ├── Dialogs │ ├── RenameDialog.xaml │ ├── SystemCommentEditorDialog.xaml │ ├── RenameDialog.xaml.cs │ ├── FindWindowDialog.xaml │ ├── SystemCommentEditorDialog.xaml.cs │ └── FindWindowDialog.xaml.cs ├── Panels │ ├── TextEditorKVPanel.xaml │ ├── TextEditorLUAPanel.xaml │ ├── KV │ │ ├── MyCompletionData.cs │ │ └── OffsetColorizer.cs │ ├── EditorsCollectionPanel.xaml │ ├── StartPagePanel.xaml │ ├── StartPagePanel.xaml.cs │ ├── ObjectsViewPanel.xaml │ └── EditorsCollectionPanel.xaml.cs ├── AboutBoxWindow.xaml.cs ├── IEditor.cs ├── LuaEditorMainWindow.xaml ├── LuaEditorMainWindow.xaml.cs ├── AboutBoxWindow.xaml └── Lua.xshd ├── KVGridUIWPF ├── KVType.cs ├── ItemTypes.cs ├── packages.config ├── KVGridSubFieldItemInterface.cs ├── App.config ├── Properties │ ├── Settings.settings │ ├── Settings.Designer.cs │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ └── Resources.resx ├── KVGridItemAbstract.cs ├── App.xaml ├── App.xaml.cs ├── KVGridItemInterface.cs ├── KVGrid.xaml ├── Items │ ├── SubFieldItems │ │ ├── KVSFITextBox.xaml │ │ └── KVSFITextBox.xaml.cs │ ├── KeyValueItems │ │ ├── KVGridItem_TextText.xaml │ │ └── KVGridItem_TextText.xaml.cs │ ├── KVGridBlock.xaml │ └── KVGridBlock.xaml.cs ├── MainWindow.xaml ├── MainWindow.xaml.cs ├── KVGrid.xaml.cs └── KVGridUIWPF.csproj ├── SomeUtils ├── packages.config ├── ObjectCloner.cs ├── DotaResourceManager.cs ├── Properties │ └── AssemblyInfo.cs ├── StringUtils.cs ├── UndoRedoManager.cs └── SomeUtils.csproj ├── CodeAnalysGenerators ├── App.config ├── Program.cs ├── Files │ └── npc_heroes_custom.txt ├── Properties │ └── AssemblyInfo.cs ├── KVKeys.cs └── CodeAnalysGenerators.csproj ├── KV reloaded ├── KVreloaded.cs ├── Attibute │ └── KeyValue.cs ├── ParserToken.cs ├── KVSettings.cs ├── Properties │ └── AssemblyInfo.cs ├── ErrorParser.cs ├── SystemComment.cs ├── KV reloaded.csproj ├── KVToken.cs ├── TokenAnalizer.cs └── ParserUtils.cs ├── README.md ├── .gitattributes ├── SimpleDota2EditorWPF.sln └── .gitignore /SimpleDota2EditorWPF/Properties/Resources.ru-RU.Designer.cs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /KVGridUIWPF/KVType.cs: -------------------------------------------------------------------------------- 1 | namespace KVGridUIWPF 2 | { 3 | public enum KVType 4 | { 5 | Key, Value, 6 | } 7 | } -------------------------------------------------------------------------------- /SimpleDota2EditorWPF/Images/Up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Oplkill/Simple-Dota-2-Editor/HEAD/SimpleDota2EditorWPF/Images/Up.png -------------------------------------------------------------------------------- /SimpleDota2EditorWPF/Images/Down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Oplkill/Simple-Dota-2-Editor/HEAD/SimpleDota2EditorWPF/Images/Down.png -------------------------------------------------------------------------------- /SimpleDota2EditorWPF/Images/Items.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Oplkill/Simple-Dota-2-Editor/HEAD/SimpleDota2EditorWPF/Images/Items.ico -------------------------------------------------------------------------------- /SimpleDota2EditorWPF/Images/Units.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Oplkill/Simple-Dota-2-Editor/HEAD/SimpleDota2EditorWPF/Images/Units.ico -------------------------------------------------------------------------------- /SimpleDota2EditorWPF/Images/Units.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Oplkill/Simple-Dota-2-Editor/HEAD/SimpleDota2EditorWPF/Images/Units.png -------------------------------------------------------------------------------- /SimpleDota2EditorWPF/Images/about.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Oplkill/Simple-Dota-2-Editor/HEAD/SimpleDota2EditorWPF/Images/about.png -------------------------------------------------------------------------------- /SimpleDota2EditorWPF/Images/close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Oplkill/Simple-Dota-2-Editor/HEAD/SimpleDota2EditorWPF/Images/close.png -------------------------------------------------------------------------------- /SimpleDota2EditorWPF/Images/exit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Oplkill/Simple-Dota-2-Editor/HEAD/SimpleDota2EditorWPF/Images/exit.png -------------------------------------------------------------------------------- /SimpleDota2EditorWPF/Images/help.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Oplkill/Simple-Dota-2-Editor/HEAD/SimpleDota2EditorWPF/Images/help.png -------------------------------------------------------------------------------- /SimpleDota2EditorWPF/Images/open.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Oplkill/Simple-Dota-2-Editor/HEAD/SimpleDota2EditorWPF/Images/open.png -------------------------------------------------------------------------------- /SimpleDota2EditorWPF/Images/redo.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Oplkill/Simple-Dota-2-Editor/HEAD/SimpleDota2EditorWPF/Images/redo.ico -------------------------------------------------------------------------------- /SimpleDota2EditorWPF/Images/save.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Oplkill/Simple-Dota-2-Editor/HEAD/SimpleDota2EditorWPF/Images/save.png -------------------------------------------------------------------------------- /SimpleDota2EditorWPF/Images/undo.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Oplkill/Simple-Dota-2-Editor/HEAD/SimpleDota2EditorWPF/Images/undo.ico -------------------------------------------------------------------------------- /SimpleDota2EditorWPF/Images/AutoTab.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Oplkill/Simple-Dota-2-Editor/HEAD/SimpleDota2EditorWPF/Images/AutoTab.png -------------------------------------------------------------------------------- /SimpleDota2EditorWPF/Images/Comment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Oplkill/Simple-Dota-2-Editor/HEAD/SimpleDota2EditorWPF/Images/Comment.png -------------------------------------------------------------------------------- /SimpleDota2EditorWPF/Images/Delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Oplkill/Simple-Dota-2-Editor/HEAD/SimpleDota2EditorWPF/Images/Delete.png -------------------------------------------------------------------------------- /SimpleDota2EditorWPF/Images/EditKV.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Oplkill/Simple-Dota-2-Editor/HEAD/SimpleDota2EditorWPF/Images/EditKV.png -------------------------------------------------------------------------------- /SimpleDota2EditorWPF/Images/Folder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Oplkill/Simple-Dota-2-Editor/HEAD/SimpleDota2EditorWPF/Images/Folder.png -------------------------------------------------------------------------------- /SimpleDota2EditorWPF/Images/Heroes.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Oplkill/Simple-Dota-2-Editor/HEAD/SimpleDota2EditorWPF/Images/Heroes.ico -------------------------------------------------------------------------------- /SimpleDota2EditorWPF/Images/Heroes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Oplkill/Simple-Dota-2-Editor/HEAD/SimpleDota2EditorWPF/Images/Heroes.png -------------------------------------------------------------------------------- /SimpleDota2EditorWPF/Images/Object.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Oplkill/Simple-Dota-2-Editor/HEAD/SimpleDota2EditorWPF/Images/Object.png -------------------------------------------------------------------------------- /SimpleDota2EditorWPF/Images/Rename.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Oplkill/Simple-Dota-2-Editor/HEAD/SimpleDota2EditorWPF/Images/Rename.png -------------------------------------------------------------------------------- /KVGridUIWPF/ItemTypes.cs: -------------------------------------------------------------------------------- 1 | namespace KVGridUIWPF 2 | { 3 | public enum ItemTypes 4 | { 5 | TextText, 6 | Block, 7 | } 8 | } -------------------------------------------------------------------------------- /SimpleDota2EditorWPF/Images/Abilities.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Oplkill/Simple-Dota-2-Editor/HEAD/SimpleDota2EditorWPF/Images/Abilities.ico -------------------------------------------------------------------------------- /SimpleDota2EditorWPF/Images/CreateKV.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Oplkill/Simple-Dota-2-Editor/HEAD/SimpleDota2EditorWPF/Images/CreateKV.png -------------------------------------------------------------------------------- /SimpleDota2EditorWPF/Images/FindHide.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Oplkill/Simple-Dota-2-Editor/HEAD/SimpleDota2EditorWPF/Images/FindHide.png -------------------------------------------------------------------------------- /SimpleDota2EditorWPF/Images/FindNext.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Oplkill/Simple-Dota-2-Editor/HEAD/SimpleDota2EditorWPF/Images/FindNext.png -------------------------------------------------------------------------------- /SimpleDota2EditorWPF/Images/FindPrev.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Oplkill/Simple-Dota-2-Editor/HEAD/SimpleDota2EditorWPF/Images/FindPrev.png -------------------------------------------------------------------------------- /SimpleDota2EditorWPF/Images/FindShow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Oplkill/Simple-Dota-2-Editor/HEAD/SimpleDota2EditorWPF/Images/FindShow.png -------------------------------------------------------------------------------- /SimpleDota2EditorWPF/Images/UnComment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Oplkill/Simple-Dota-2-Editor/HEAD/SimpleDota2EditorWPF/Images/UnComment.png -------------------------------------------------------------------------------- /SimpleDota2EditorWPF/Images/settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Oplkill/Simple-Dota-2-Editor/HEAD/SimpleDota2EditorWPF/Images/settings.png -------------------------------------------------------------------------------- /SimpleDota2EditorWPF/Images/FolderClosed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Oplkill/Simple-Dota-2-Editor/HEAD/SimpleDota2EditorWPF/Images/FolderClosed.png -------------------------------------------------------------------------------- /SimpleDota2EditorWPF/Images/CreateKVBlock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Oplkill/Simple-Dota-2-Editor/HEAD/SimpleDota2EditorWPF/Images/CreateKVBlock.png -------------------------------------------------------------------------------- /SimpleDota2EditorWPF/Images/FolderOpenned.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Oplkill/Simple-Dota-2-Editor/HEAD/SimpleDota2EditorWPF/Images/FolderOpenned.png -------------------------------------------------------------------------------- /SimpleDota2EditorWPF/Images/AbilitiesOverride.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Oplkill/Simple-Dota-2-Editor/HEAD/SimpleDota2EditorWPF/Images/AbilitiesOverride.ico -------------------------------------------------------------------------------- /SomeUtils/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /KVGridUIWPF/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /KVGridUIWPF/KVGridSubFieldItemInterface.cs: -------------------------------------------------------------------------------- 1 | namespace KVGridUIWPF 2 | { 3 | public interface KVGridSubFieldItemInterface 4 | { 5 | string Text { get; set; } 6 | } 7 | } -------------------------------------------------------------------------------- /KVGridUIWPF/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /CodeAnalysGenerators/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /CodeAnalysGenerators/Program.cs: -------------------------------------------------------------------------------- 1 | namespace CodeAnalysGenerators 2 | { 3 | class Program 4 | { 5 | static void Main(string[] args) 6 | { 7 | KVKeys.Start(); 8 | } 9 | 10 | 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /KVGridUIWPF/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /SimpleDota2EditorWPF/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /KV reloaded/KVreloaded.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | 3 | namespace KV_reloaded 4 | { 5 | public class KVreloaded 6 | { 7 | public KVToken MainToken; 8 | 9 | public void LoadKVText(string text) 10 | { 11 | MainToken = TokenAnalizer.AnaliseText(text).FirstOrDefault(); 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /KV reloaded/Attibute/KeyValue.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace KV_reloaded 4 | { 5 | [AttributeUsage(AttributeTargets.Method)] 6 | public class KeyValue : Attribute 7 | { 8 | public string place { get; set; } 9 | public KeyValue(string place) 10 | { 11 | this.place = place; 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /CodeAnalysGenerators/Files/npc_heroes_custom.txt: -------------------------------------------------------------------------------- 1 | //File edited with Simple Dota 2 Editor 2 | //https://github.com/Oplkill/Simple-Dota-2-Editor 3 | 4 | 5 | "DOTAHeroes" 6 | {//@ #Folder="New folder 85924072" 7 | 8 | 9 | 10 | 11 | "New_object_85925210"{"Name" "Oplkill"}"New_object_81324681"{"bla" "000"}//@ #Folder="New folder 85924072" 12 | "New_object_81567660"{}}} 13 | -------------------------------------------------------------------------------- /KVGridUIWPF/KVGridItemAbstract.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Controls; 2 | 3 | namespace KVGridUIWPF 4 | { 5 | public abstract class KVGridItemAbstract : UserControl 6 | { 7 | 8 | 9 | public new KVGrid.TextChangedFunc OnTextChanged; 10 | 11 | 12 | public string[] comments; //todo удалить и изменить, временное решение оформления 13 | } 14 | } -------------------------------------------------------------------------------- /SimpleDota2EditorWPF/App.xaml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /KVGridUIWPF/App.xaml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /KVGridUIWPF/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Configuration; 4 | using System.Data; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | 9 | namespace KVGridUIWPF 10 | { 11 | /// 12 | /// Логика взаимодействия для App.xaml 13 | /// 14 | public partial class App : Application 15 | { 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /KV reloaded/ParserToken.cs: -------------------------------------------------------------------------------- 1 | namespace KV_reloaded 2 | { 3 | public class ParserToken 4 | { 5 | public string Text = ""; 6 | public ParserTokenType Type = ParserTokenType.Nil; 7 | } 8 | 9 | public enum ParserTokenType 10 | { 11 | Nil, 12 | NewLine, 13 | Space, 14 | Comment, 15 | Text, 16 | NewBlock, 17 | EndBlock, 18 | Eof, 19 | } 20 | } -------------------------------------------------------------------------------- /SimpleDota2EditorWPF/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /SomeUtils/ObjectCloner.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using System.Runtime.Serialization.Formatters.Binary; 3 | 4 | namespace SomeUtils 5 | { 6 | public static class ObjectCloner 7 | { 8 | public static T DeepClone(this T source) where T : class 9 | { 10 | MemoryStream stream = new MemoryStream(); 11 | BinaryFormatter formatter = new BinaryFormatter(); 12 | formatter.Serialize(stream, source); 13 | stream.Position = 0; 14 | return (T)formatter.Deserialize(stream); 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /SimpleDota2EditorWPF/ScriptsUtils/KV/BasicCompletionValues.kv: -------------------------------------------------------------------------------- 1 | 2 | "Values" 3 | { 4 | "BaseClass" 5 | { 6 | "ability_datadriven" "#AbilityDataDriven" 7 | "ability_lua" "#AbilityLua" 8 | } 9 | 10 | "var_type" 11 | { 12 | "FIELD_INTEGER" "#FieldInteger" 13 | "FIELD_FLOAT" "#FieldFloat" 14 | } 15 | 16 | "AbilityUnitTargetTeam" 17 | { 18 | "DOTA_UNIT_TARGET_TEAM_ENEMY" "descr" 19 | "DOTA_UNIT_TARGET_TEAM_FRIENDLY" "descr" 20 | } 21 | 22 | "AbilityBehavior" 23 | { 24 | "DOTA_ABILITY_BEHAVIOR_PASSIVE" "Descr" 25 | "DOTA_ABILITY_BEHAVIOR_HIDDEN" "Descr" 26 | } 27 | } -------------------------------------------------------------------------------- /SimpleDota2EditorWPF/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Simple-Dota-2-Editor 2 | Simple Dota 2 editor txt files with KV style objects and lua editing. 3 | 4 | Download binars there https://github.com/Oplkill/Simple-Dota-2-Editor/releases 5 | 6 | See plans there https://trello.com/b/EtSKnLuW/simple-dota-2-editor 7 | 8 | ![screenshot of sample](http://pastexen.com/i/NXVbcaVeYc.png) 9 | ![screenshot of sample](http://pastexen.com/i/WiRpIIZALm.png) 10 | ![screenshot of sample](http://pastexen.com/i/0FYeslhqq0.png) 11 | ![screenshot of sample](http://pastexen.com/i/wpLQ9Lvymr.png) 12 | 13 | 14 | Video v0.04Alpha 15 | https://youtu.be/gE4UOq4E0Ow 16 | -------------------------------------------------------------------------------- /SimpleDota2EditorWPF/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Configuration; 4 | using System.Data; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | 9 | namespace SimpleDota2EditorWPF 10 | { 11 | /// 12 | /// Логика взаимодействия для App.xaml 13 | /// 14 | public partial class App : Application 15 | { 16 | public App() 17 | { 18 | 19 | } 20 | public void Run() 21 | { 22 | Run(new ObjectEditorMainWindow()); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /KVGridUIWPF/KVGridItemInterface.cs: -------------------------------------------------------------------------------- 1 | namespace KVGridUIWPF 2 | { 3 | public interface KVGridItemInterface 4 | { 5 | int ItemHeight { get; } 6 | 7 | ItemTypes ItemType { get; } 8 | 9 | KVGridBlock ParentBlock { get; set; } 10 | 11 | KVGrid GridOwner { get; set; } 12 | 13 | string KeyText { get; set; } 14 | 15 | /// 16 | /// Can be null if doesnt contain value (eq Block) 17 | /// Will be empty if value empty 18 | /// 19 | string ValueText { get; set; } 20 | 21 | bool Selected { get; set; } 22 | 23 | int Id { get; set; } 24 | 25 | KVGrid.TextChangedFunc OnTextChanged { get; set; } 26 | } 27 | } -------------------------------------------------------------------------------- /KV reloaded/KVSettings.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | 4 | namespace KV_reloaded 5 | { 6 | public static class KVSettings 7 | { 8 | public static string MakeClassInKV(Type t, string headerKV) 9 | { 10 | //KeyValue kvAttributes = (KeyValue)Attribute.GetCustomAttribute(t, typeof(KeyValue)); 11 | 12 | var fields = t.GetFields(); 13 | KVToken token = new KVToken(string.IsNullOrWhiteSpace(headerKV) ? "Settings" : headerKV); 14 | 15 | foreach (var f in fields) 16 | { 17 | KeyValue kvAtr = (KeyValue)Attribute.GetCustomAttribute(f, typeof(KeyValue)); 18 | } 19 | 20 | return token.ToString(); 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /KVGridUIWPF/KVGrid.xaml: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /KVGridUIWPF/Items/SubFieldItems/KVSFITextBox.xaml: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /SimpleDota2EditorWPF/ScriptsUtils/KV/BasicCompletionKV.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using ICSharpCode.AvalonEdit.CodeCompletion; 8 | using KV_reloaded; 9 | using SimpleDota2EditorWPF.Panels; 10 | 11 | namespace SimpleDota2EditorWPF.ScriptsUtils.KV 12 | { 13 | public static class BasicCompletionKV 14 | { 15 | public static KVToken Keys = new KVToken(""); 16 | public static KVToken Values = new KVToken(""); 17 | 18 | public static void Init() 19 | { 20 | loadKv("ScriptsUtils\\KV\\BasicCompletionKeys.kv", ref Keys); 21 | loadKv("ScriptsUtils\\KV\\BasicCompletionValues.kv", ref Values); 22 | } 23 | 24 | private static void loadKv(string file, ref KVToken token) 25 | { 26 | if (!File.Exists(file)) 27 | return; 28 | 29 | token = TokenAnalizer.AnaliseText(File.ReadAllText(file)).FirstOrDefault(); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /KVGridUIWPF/MainWindow.xaml: -------------------------------------------------------------------------------- 1 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 38 | 41 | 44 | 47 | 50 | 53 | 56 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 71 | 72 | 73 | 78 | 79 | 80 | 83 | 84 | 95 | 96 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /SimpleDota2EditorWPF/Dialogs/FindWindowDialog.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Shapes; 14 | 15 | namespace SimpleDota2EditorWPF.Dialogs 16 | { 17 | /// 18 | /// Логика взаимодействия для FindWindowDialog.xaml 19 | /// 20 | public partial class FindWindowDialog : Window 21 | { 22 | public FindWindowDialog() 23 | { 24 | InitializeComponent(); 25 | } 26 | 27 | public FindStruct GetFindSettingsStruct() 28 | { 29 | return new FindStruct() 30 | { 31 | text = textBoxFind.Text, 32 | replaceText = textBoxReplace.Text, 33 | loop = checkBoxLoop.IsChecked != null && checkBoxLoop.IsChecked.Value, 34 | registr = checkBoxRegister.IsChecked != null && checkBoxRegister.IsChecked.Value ? 35 | StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase, 36 | }; 37 | } 38 | 39 | private void buttonPrev_Click(object sender, RoutedEventArgs e) 40 | { 41 | var selectedContent = AllPanels.LayoutDocumentPane.SelectedContent?.Content as IEditor; 42 | if (selectedContent == null) return; 43 | if (String.IsNullOrEmpty(textBoxFind.Text)) 44 | { 45 | this.Title = "Find" + " - " + "Find box is empty!"; //todo move to resource 46 | textBoxFind.Focus(); 47 | return; 48 | } 49 | 50 | var reachedStart = selectedContent.FindPrev(GetFindSettingsStruct()); 51 | if (reachedStart == null) 52 | this.Title = "Find" + " - " + "Didn't finded anything"; //todo move to resource 53 | else if (reachedStart == true) 54 | this.Title = "Find" + " - " + "Reached start of document"; //todo move to resource 55 | else if (this.Title != "Find") 56 | this.Title = "Find"; //todo move to resource 57 | 58 | } 59 | 60 | private void buttonNext_Click(object sender, RoutedEventArgs e) 61 | { 62 | var selectedContent = AllPanels.LayoutDocumentPane.SelectedContent?.Content as IEditor; 63 | if (selectedContent == null) return; 64 | if (String.IsNullOrEmpty(textBoxFind.Text)) 65 | { 66 | this.Title = "Find" + " - " + "Find box is empty!"; //todo move to resource 67 | textBoxFind.Focus(); 68 | return; 69 | } 70 | 71 | var reachedEnd = selectedContent.FindNext(GetFindSettingsStruct()); 72 | if (reachedEnd == null) 73 | this.Title = "Find" + " - " + "Didn't finded anything"; //todo move to resource 74 | else if (reachedEnd == true) 75 | this.Title = "Find" + " - " + "Reached end of document"; //todo move to resource 76 | else if (this.Title != "Find") 77 | this.Title = "Find"; //todo move to resource 78 | } 79 | 80 | private void buttonCount_Click(object sender, RoutedEventArgs e) 81 | { 82 | var selectedContent = AllPanels.LayoutDocumentPane.SelectedContent?.Content as IEditor; 83 | if (selectedContent == null) return; 84 | if (String.IsNullOrEmpty(textBoxFind.Text)) 85 | { 86 | this.Title = "Find" + " - " + "Find box is empty!"; //todo move to resource 87 | textBoxFind.Focus(); 88 | return; 89 | } 90 | 91 | int number = selectedContent.CountIt(GetFindSettingsStruct()); 92 | this.Title = "Find" + " - " + "Number items " + number; //todo move to resource 93 | } 94 | 95 | private void buttonReplace_Click(object sender, RoutedEventArgs e) 96 | { 97 | var selectedContent = AllPanels.LayoutDocumentPane.SelectedContent?.Content as IEditor; 98 | if (selectedContent == null) return; 99 | if (String.IsNullOrEmpty(textBoxFind.Text)) 100 | { 101 | this.Title = "Find" + " - " + "Find box is empty!"; //todo move to resource 102 | textBoxFind.Focus(); 103 | return; 104 | } 105 | 106 | var allReplaced = selectedContent.Replace(GetFindSettingsStruct()); 107 | if (allReplaced == null) 108 | this.Title = "Find" + " - " + "Didn't finded anything"; //todo move to resource 109 | else if (allReplaced == true) 110 | this.Title = "Find" + " - " + "Nothing left to replace"; //todo move to resource 111 | else if (this.Title != "Find") 112 | this.Title = "Find"; //todo move to resource 113 | } 114 | 115 | private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) 116 | { 117 | e.Cancel = true; 118 | this.Hide(); 119 | } 120 | 121 | private void Window_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e) 122 | { 123 | if (this.Title != "Find") 124 | this.Title = "Find"; //todo move to resource 125 | } 126 | } 127 | 128 | //todo rename it 129 | public struct FindStruct 130 | { 131 | public StringComparison registr; 132 | public string text; 133 | public string replaceText; 134 | public bool loop; 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /KVGridUIWPF/KVGrid.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Windows; 5 | using System.Windows.Controls; 6 | using System.Windows.Controls.Primitives; 7 | using KVGridUIWPF.Items.KeyValueItems; 8 | 9 | namespace KVGridUIWPF 10 | { 11 | /// 12 | /// Логика взаимодействия для KVGrid.xaml 13 | /// 14 | public partial class KVGrid : UserControl 15 | { 16 | public delegate void TextChangedFunc(KVGridItemInterface item, string oldText, string newText, KVType type); 17 | public KVGrid() 18 | { 19 | InitializeComponent(); 20 | 21 | kvGridBlock1.HideKVBlockControls(true); 22 | kvGridBlock1.GridOwner = this; 23 | currentUnicId = 0; //todo generic id random 24 | 25 | kvGridBlock1.Id = GetMyId(); 26 | } 27 | 28 | public List Items => kvGridBlock1.Items; 29 | 30 | public KVGridBlock MainBlock => kvGridBlock1; 31 | 32 | public void AddItem(ItemTypes type, string key, string value) 33 | { 34 | Control item = null; 35 | switch (type) 36 | { 37 | case ItemTypes.TextText: 38 | item = new KVGridItem_TextText() { KeyText = key, ValueText = value }; 39 | break; 40 | 41 | case ItemTypes.Block: 42 | item = new KVGridBlock() { KeyText = key }; 43 | break; 44 | 45 | default: 46 | return; 47 | } 48 | kvGridBlock1.AddItem(this, (KVGridItemInterface)item, -1); 49 | this.Height = kvGridBlock1.Height; 50 | } 51 | 52 | /// 53 | /// Swapping items 54 | /// 55 | public void SwapItems(KVGridItemInterface item1, KVGridItemInterface item2) 56 | { 57 | if (item1.ParentBlock == item2.ParentBlock) 58 | { item1.ParentBlock.SwapItems(item1, item2); return; } 59 | 60 | //todo 61 | } 62 | 63 | /// 64 | /// Getting item which upper @item. If @item first in block, it will be return block which contain @item. 65 | /// Returns null if @item uppest of all items of this kvGrid. 66 | /// 67 | public KVGridItemInterface GetItemUpperThatItem(KVGridItemInterface item) 68 | { 69 | var block = item.ParentBlock; 70 | var index = block.Items.IndexOf(item); 71 | 72 | if (index == 0) 73 | { 74 | if (block == MainBlock) 75 | return null; 76 | else 77 | return block; 78 | } 79 | else 80 | return block.Items[index - 1]; 81 | } 82 | 83 | /// 84 | /// Getting item which downer @item. 85 | /// returns null if @item downer of all items of this kvGrid. 86 | /// 87 | public KVGridItemInterface GetItemDownerThatItem(KVGridItemInterface item) 88 | { 89 | var block = item.ParentBlock; 90 | var index = block.Items.IndexOf(item); 91 | 92 | if (index == block.Items.Count - 1) 93 | { 94 | if (block == MainBlock) 95 | return null; 96 | else 97 | return GetItemDownerThatItem(block); 98 | } 99 | else 100 | return block.Items[index + 1]; 101 | } 102 | 103 | public void MoveItemUpThrough(KVGridItemInterface item) 104 | { 105 | var block = item.ParentBlock; 106 | var index = block.Items.IndexOf(item); 107 | 108 | if (index == 0) 109 | { 110 | if (block == MainBlock) 111 | return; 112 | block.RemoveItem(item, false); 113 | block.ParentBlock.AddItem(this, item, block.ParentBlock.Items.IndexOf(block)); 114 | } 115 | else 116 | block.SwapItems(block.Items[index - 1], item); 117 | } 118 | 119 | public void MoveItemDownThrough(KVGridItemInterface item) 120 | { 121 | var block = item.ParentBlock; 122 | var index = block.Items.IndexOf(item); 123 | 124 | if (index == block.Items.Count - 1) 125 | { 126 | if (block == MainBlock) 127 | return; 128 | block.RemoveItem(item, false); 129 | block.ParentBlock.AddItem(this, item, block.ParentBlock.Items.IndexOf(block) + 1); 130 | } 131 | else 132 | block.SwapItems(block.Items[index + 1], item); 133 | } 134 | 135 | public KVGridItemInterface SelectedItem 136 | { 137 | get { return selectedItem; } 138 | set 139 | { 140 | if (selectedItem == value) return; 141 | 142 | if (selectedItem != null) selectedItem.Selected = false; 143 | if (value == null) 144 | { 145 | selectedItem = null; 146 | return; 147 | } 148 | if (value.GridOwner != this) return; 149 | 150 | selectedItem = value; 151 | selectedItem.Selected = true; 152 | } 153 | } 154 | 155 | public KVGridItemInterface GetItemById(int id) 156 | { 157 | return MainBlock.FindItemId(id); 158 | } 159 | 160 | public int GetMyId() 161 | { 162 | return currentUnicId++; 163 | } 164 | 165 | private KVGridItemInterface selectedItem; 166 | private int currentUnicId; 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /KVGridUIWPF/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 | text/microsoft-resx 107 | 108 | 109 | 2.0 110 | 111 | 112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 113 | 114 | 115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | -------------------------------------------------------------------------------- /SimpleDota2EditorWPF/Panels/EditorsCollectionPanel.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | using System.Windows.Controls; 9 | using System.Windows.Data; 10 | using System.Windows.Documents; 11 | using System.Windows.Input; 12 | using System.Windows.Media; 13 | using System.Windows.Media.Imaging; 14 | using System.Windows.Navigation; 15 | using System.Windows.Shapes; 16 | using KV_reloaded; 17 | using SimpleDota2EditorWPF.Dialogs; 18 | using Xceed.Wpf.AvalonDock.Layout; 19 | 20 | namespace SimpleDota2EditorWPF.Panels 21 | { 22 | /// 23 | /// Логика взаимодействия для EditorsCollectionPanel.xaml 24 | /// 25 | public partial class EditorsCollectionPanel : UserControl, IEditor 26 | { 27 | public IEditor ParentEditor { get; set; } 28 | public bool? FindNext(FindStruct find) 29 | { 30 | if (DocumentsPane.SelectedContent.Content is IEditor) 31 | return ((IEditor) DocumentsPane.SelectedContent.Content).FindNext(find); 32 | return null; 33 | } 34 | 35 | public bool? FindPrev(FindStruct find) 36 | { 37 | if (DocumentsPane.SelectedContent.Content is IEditor) 38 | return ((IEditor)DocumentsPane.SelectedContent.Content).FindPrev(find); 39 | return null; 40 | } 41 | 42 | public int CountIt(FindStruct find) 43 | { 44 | if (DocumentsPane.SelectedContent.Content is IEditor) 45 | return ((IEditor)DocumentsPane.SelectedContent.Content).CountIt(find); 46 | return 0; 47 | } 48 | 49 | public bool? Replace(FindStruct find) 50 | { 51 | if (DocumentsPane.SelectedContent.Content is IEditor) 52 | return ((IEditor)DocumentsPane.SelectedContent.Content).Replace(find); 53 | return null; 54 | } 55 | 56 | public bool Edited 57 | { 58 | get { return edited; } 59 | set 60 | { 61 | PanelDocument.Title = PanelName + (value ? @" *" : ""); 62 | edited = value; 63 | } 64 | } 65 | private bool edited; 66 | public EditorsCollectionPanel() 67 | { 68 | InitializeComponent(); 69 | } 70 | 71 | public string PanelName 72 | { 73 | get { return panelName; } 74 | set 75 | { 76 | PanelDocument.Title = value + (Edited ? @" *" : ""); 77 | var panels = DocumentsPane.Children.Where(doc => doc.Content is IEditor); 78 | foreach (var panel in panels) 79 | { 80 | if (((IEditor) panel.Content).PanelName == panelName) 81 | { 82 | ((IEditor) panel.Content).PanelName = value; 83 | } 84 | } 85 | panelName = value; 86 | } 87 | } 88 | 89 | private string panelName; 90 | public KVToken ObjectRef { get; set; } 91 | public ObjectsViewPanel.ObjectTypePanel ObjectType { get; set; } 92 | public Settings.EditorType EditorType { get; } 93 | public void ForceClose() 94 | { 95 | var panels = DocumentsPane.Children.Where(doc => doc.Content is IEditor); 96 | 97 | foreach (var panel in panels) 98 | { 99 | ((IEditor)panel.Content).ForceClose(); 100 | } 101 | } 102 | 103 | public ErrorParser SaveChanges() 104 | { 105 | ErrorParser errors = null; 106 | var panels = DocumentsPane.Children.Where(doc => doc.Content is IEditor); 107 | 108 | foreach (var panel in panels) 109 | { 110 | var error = ((IEditor) panel.Content).SaveChanges(); 111 | if (error != null) 112 | errors = error; 113 | } 114 | 115 | return errors; 116 | } 117 | 118 | public void Closing(object sender, CancelEventArgs e) 119 | { 120 | var errors = SaveChanges(); 121 | 122 | if (errors == null) 123 | return; 124 | 125 | var dialog = MessageBox.Show(Properties.Resources.TextContainErrors, Properties.Resources.TextContainErrorsCapture, MessageBoxButton.YesNo); 126 | switch (dialog) 127 | { 128 | case MessageBoxResult.Yes: 129 | break; 130 | 131 | case MessageBoxResult.No: 132 | e.Cancel = true; 133 | break; 134 | } 135 | } 136 | 137 | public LayoutDocument PanelDocument { get; set; } 138 | public void Update() 139 | { 140 | var panels = DocumentsPane.Children.Where(doc => doc.Content is IEditor); 141 | 142 | foreach (var panel in panels) 143 | { 144 | ((IEditor)panel.Content).Update(); 145 | } 146 | } 147 | 148 | public void IsActiveChanged(object sender, EventArgs e) 149 | { 150 | var selectedContent = AllPanels.LayoutDocumentPane.SelectedContent?.Content; 151 | 152 | bool showKv = selectedContent is TextEditorKVPanel; 153 | bool showLua = selectedContent is TextEditorLUAPanel; 154 | if (selectedContent is EditorsCollectionPanel) 155 | { 156 | var content = ((EditorsCollectionPanel)selectedContent).DocumentsPane.SelectedContent.Content; 157 | showKv = content is TextEditorKVPanel; 158 | showLua = content is TextEditorLUAPanel; 159 | } 160 | AllPanels.ObjectEditorForm.ShowEditorsMenu(showKv, showLua); 161 | } 162 | 163 | 164 | } 165 | } 166 | -------------------------------------------------------------------------------- /KV reloaded/TokenAnalizer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace KV_reloaded 5 | { 6 | public static class TokenAnalizer 7 | { 8 | public static List AnaliseText(string text) 9 | { 10 | List tokens = new List(); 11 | int n = 0; 12 | int line = 1; 13 | int symbol = 0; 14 | 15 | while (text.Length > n) 16 | { 17 | var tok = GetKVToken(text, null, ref n, ref line, ref symbol); 18 | if(tok == null) 19 | break; 20 | tokens.Add(tok); 21 | } 22 | 23 | return tokens; 24 | } 25 | 26 | public static KVToken GetKVToken(string text, KVToken parent, ref int n, ref int line, ref int symbol) 27 | { 28 | KVToken kvToken = new KVToken {Parent = parent}; 29 | CommentPlace commentPlace = CommentPlace.BeforeKey; 30 | ParserToken tok; 31 | bool key = true; 32 | 33 | tok = GetToken(text, ref n, ref line, ref symbol); 34 | while (true) 35 | { 36 | if (tok.Type == ParserTokenType.NewLine || tok.Type == ParserTokenType.Space || tok.Type == ParserTokenType.Comment) 37 | { 38 | if (kvToken.comments[(int) commentPlace] == null) 39 | kvToken.comments[(int) commentPlace] = ""; 40 | 41 | if (tok.Type == ParserTokenType.Comment && tok.Text.IndexOf("//@", StringComparison.Ordinal) == 0) 42 | { 43 | kvToken.SystemComment = SystemComment.AnalyseSystemComment(tok.Text); 44 | } 45 | else 46 | kvToken.comments[(int) commentPlace] += tok.Text; 47 | } 48 | else if(tok.Type == ParserTokenType.Text) 49 | { 50 | if (key) 51 | { 52 | if(string.IsNullOrEmpty(tok.Text)) 53 | throw new ErrorParser(KvError.EmptyKey, line, symbol); 54 | kvToken.Key = tok.Text; 55 | commentPlace = CommentPlace.AfterKey; 56 | key = false; 57 | } 58 | else 59 | { 60 | kvToken.Value = tok.Text; 61 | kvToken.Type = KVTokenType.KVsimple; 62 | break; 63 | } 64 | } 65 | else if (tok.Type == ParserTokenType.NewBlock) 66 | { 67 | kvToken.Type = KVTokenType.KVblock; 68 | kvToken.Children = new List(); 69 | KVToken childKvToken = GetKVToken(text, kvToken, ref n, ref line, ref symbol); 70 | while (childKvToken != null) 71 | { 72 | kvToken.Children.Add(childKvToken); 73 | if(childKvToken.Type == KVTokenType.Comment) 74 | break; 75 | childKvToken = GetKVToken(text, kvToken, ref n, ref line, ref symbol); 76 | } 77 | return kvToken; 78 | } 79 | else if(tok.Type == ParserTokenType.EndBlock) 80 | { 81 | if (kvToken.comments[(int) commentPlace] == null) 82 | return null; 83 | 84 | kvToken.Type = KVTokenType.Comment; 85 | kvToken.Value = kvToken.comments[(int) commentPlace]; 86 | kvToken.comments[(int) commentPlace] = null; 87 | return kvToken; 88 | } 89 | else 90 | { 91 | return null; 92 | } 93 | tok = GetToken(text, ref n, ref line, ref symbol); 94 | } 95 | 96 | 97 | return kvToken; 98 | } 99 | 100 | public static ParserToken GetToken(string text, ref int n, ref int line, ref int symbol) 101 | { 102 | ParserToken tok = new ParserToken(); 103 | 104 | if (n >= text.Length) 105 | { 106 | tok.Type = ParserTokenType.Eof; 107 | return tok; 108 | } 109 | 110 | if (SomeUtils.StringUtils.IsSpaceOrTab(text[n])) 111 | { 112 | tok.Type = ParserTokenType.Space; 113 | tok.Text = ParserUtils.SkipSpace(text, ref n, ref line, ref symbol); 114 | 115 | return tok; 116 | } 117 | 118 | switch (text[n]) 119 | { 120 | case '\n': 121 | tok.Type = ParserTokenType.NewLine; 122 | tok.Text = "\n"; 123 | n++; 124 | line++; 125 | symbol = 0; 126 | return tok; 127 | 128 | case '/': 129 | tok.Type = ParserTokenType.Comment; 130 | tok.Text = ParserUtils.SkipComment(text, ref n, ref line, ref symbol); 131 | return tok; 132 | 133 | case '\"': 134 | tok.Type = ParserTokenType.Text; 135 | tok.Text = ParserUtils.SkipText(text, ref n, ref line, ref symbol); 136 | return tok; 137 | 138 | case '{': 139 | tok.Type = ParserTokenType.NewBlock; 140 | n++; 141 | symbol++; 142 | return tok; 143 | 144 | case '}': 145 | tok.Type = ParserTokenType.EndBlock; 146 | n++; 147 | symbol++; 148 | return tok; 149 | } 150 | 151 | throw new ErrorParser(KvError.UndefinitedSymbols, line, symbol); 152 | } 153 | } 154 | } -------------------------------------------------------------------------------- /SimpleDota2EditorWPF/ScriptsUtils/KV/KVScriptResourcesKeys.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 | Base class description 122 | 123 | 124 | Particle description 125 | 126 | -------------------------------------------------------------------------------- /SimpleDota2EditorWPF/ScriptsUtils/KV/KVScriptResourcesValues.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 | Ability descr 122 | 123 | 124 | Spell by lua 125 | 126 | 127 | Float 128 | 129 | 130 | Integer 131 | 132 | -------------------------------------------------------------------------------- /SimpleDota2EditorWPF/Lua.xshd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | &<>~!%^*()-+=|\/{}[]:;"' , .? 15 | 16 | 17 | --[[ 18 | ]] 19 | 20 | 21 | 22 | -- 23 | 24 | 25 | 26 | ' 27 | ' 28 | 29 | 30 | 31 | 32 | " 33 | " 34 | 35 | 36 | 37 | [[ 38 | ]] 39 | 40 | 41 | 42 | ( 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 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 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | <>~!@%^*()-+=|\#/{}[]:;"' , .? 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | -------------------------------------------------------------------------------- /KV reloaded/ParserUtils.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using System.Linq; 3 | 4 | namespace KV_reloaded 5 | { 6 | public static class ParserUtils 7 | { 8 | public static string SkipComment(string text, ref int n, ref int line, ref int symbol) 9 | { 10 | int i = n; 11 | n++; 12 | symbol++; 13 | if (text[n] != '/') 14 | throw new ErrorParser(KvError.NotOveredComment, line, symbol); 15 | n++; 16 | 17 | n = SkipComment(text, n); 18 | if (n == text.Length) 19 | return text.Substring(i); 20 | n++; 21 | line++; 22 | symbol = 0; 23 | 24 | return text.Substring(i, n - i); 25 | } 26 | 27 | /// 28 | /// returning end of comment (position '\n' symbol or text.Length) 29 | /// 30 | public static int SkipComment(string text, int offset) 31 | { 32 | int end = FindSymbol(text, '\n', offset); 33 | return (end != -1) ? end : text.Length; 34 | } 35 | 36 | public static string SkipText(string text, ref int n, ref int line, ref int symbol) 37 | { 38 | n++; 39 | symbol++; 40 | int i = n; 41 | while (text[n] != '\"') 42 | { 43 | n++; 44 | symbol++; 45 | } 46 | string str = text.Substring(i, n - i); 47 | n++; 48 | symbol++; 49 | 50 | return str; 51 | } 52 | 53 | public static string SkipSpace(string text, ref int n, ref int line, ref int symbol) 54 | { 55 | int i = n; 56 | symbol = n = SkipSpace(text, n); 57 | return text.Substring(i, n - i); 58 | } 59 | 60 | public static int SkipSpace(string text, int offset) 61 | { 62 | while (offset < text.Length && SomeUtils.StringUtils.IsSpaceOrTab(text[offset])) 63 | { 64 | offset++; 65 | } 66 | 67 | return offset; 68 | } 69 | 70 | public static bool AllBlocksHasPare(string str) 71 | { 72 | return str.Count(s => s == '{') == str.Count(s => s == '}'); 73 | } 74 | 75 | public static int FindSymbol(string text, char symbol, int start) 76 | { 77 | int len = text.Length; 78 | while (start < len) 79 | { 80 | if (text[start] == symbol) 81 | { 82 | int symb = thisSymbolInCommentZone(text, start); 83 | if (symb == -1) 84 | return start; 85 | else 86 | start = symb; 87 | } 88 | 89 | start++; 90 | } 91 | 92 | return -1; 93 | } 94 | 95 | /// 96 | /// Getting first prev symbol thruegh comments 97 | /// 98 | public static int GetPositionFirstPrevSymbol(string text, char symbol, int start) 99 | { 100 | if (text.Length <= start) 101 | return -1; 102 | while (start > 0) 103 | { 104 | if (text[start] == symbol) 105 | { 106 | int symb = thisSymbolInCommentZone(text, start); 107 | if (symb == -1) 108 | return start; 109 | else 110 | start = symb; 111 | } 112 | 113 | start--; 114 | } 115 | 116 | return -1; 117 | } 118 | 119 | /// 120 | /// Getting first next symbol thruegh comments 121 | /// 122 | public static int GetPositionFirstNextSymbol(string text, char symbol, int start) 123 | { 124 | if (text.Length <= start) 125 | return -1; 126 | int len = text.Length; 127 | while (start < len) 128 | { 129 | if (text[start] == symbol) 130 | { 131 | int symb = thisSymbolInCommentZone(text, start); 132 | if (symb == -1) 133 | break; 134 | else if ((symb = SkipComment(text, symb)) != len) 135 | start = symb; 136 | else 137 | return -1; 138 | } 139 | 140 | start++; 141 | } 142 | 143 | return start; 144 | } 145 | 146 | /// 147 | /// If it in comment zone - returns start of comment, else - "-1" 148 | /// 149 | public static int thisSymbolInCommentZone(string text, int symbPos) 150 | { 151 | while (symbPos > 0 && symbPos < text.Length) 152 | { 153 | if (text[symbPos] == '/' && text[symbPos-1] == '/') 154 | return symbPos - 1; 155 | else if (text[symbPos] == '\n') 156 | return -1; 157 | 158 | symbPos--; 159 | } 160 | 161 | return -1; 162 | } 163 | 164 | public static string GetKeyText(string text, int offset) 165 | { 166 | int pos = GetPositionFirstPrevSymbol(text, '\n', offset); 167 | string line = text.Substring(pos + 1, offset - pos); 168 | 169 | int posStart = GetPositionFirstNextSymbol(line, '\"', 0); 170 | pos = GetPositionFirstNextSymbol(line, '\"', posStart + 1); 171 | 172 | return line.Substring(posStart + 1, pos - posStart - 1); 173 | } 174 | 175 | /// 176 | /// true - значит это ключ 177 | /// false - это значение 178 | /// null - это ни ключ, ни значение. Неопределенно 179 | /// 180 | public static bool? ItsKey(string text, int offset) 181 | { 182 | int pos = GetPositionFirstPrevSymbol(text, '\n', offset); 183 | int localOfsset = offset - pos; 184 | string line = text.Substring(pos + 1, localOfsset); 185 | 186 | pos = GetPositionFirstNextSymbol(line, '\"', 0); 187 | if (pos == -1) 188 | return null; 189 | if (pos + 1 >= line.Length) 190 | return true; 191 | pos = GetPositionFirstNextSymbol(line, '\"', pos + 1); 192 | if (pos == -1) 193 | return true; 194 | 195 | pos = GetPositionFirstNextSymbol(line, '\"', pos + 1); 196 | if (pos == -1 || pos == localOfsset) 197 | return null; 198 | pos = GetPositionFirstNextSymbol(line, '\"', pos + 1); 199 | if (pos == -1) 200 | return false; 201 | if (pos < localOfsset) 202 | return null; 203 | else 204 | return false; 205 | 206 | return null; 207 | } 208 | 209 | /// 210 | /// Возвращает текст ключа блока, который содержит этот offset 211 | /// Если это корень, то возвращается пустая строка 212 | /// Null если есть ошибка 213 | /// 214 | public static string GetOwnerKeyBlockText(string text, int offset) 215 | { 216 | int pos = GetPositionFirstPrevSymbol(text, '{', offset); 217 | if (pos == -1) return ""; 218 | pos = GetPositionFirstPrevSymbol(text, '\"', pos); 219 | if (pos == -1) return null; 220 | int posStart = GetPositionFirstPrevSymbol(text, '\"', pos - 1); 221 | if (posStart == -1) return null; 222 | if (posStart + 1 >= pos) return null; 223 | 224 | return text.Substring(posStart + 1, pos - posStart - 1); 225 | } 226 | 227 | public static bool ThisPositionStartOfComment(string text, int offset) 228 | { 229 | return offset + 1 <= text.Length 230 | && text[offset] == '/' 231 | && text[offset + 1] == '/'; 232 | } 233 | } 234 | } -------------------------------------------------------------------------------- /KVGridUIWPF/KVGridUIWPF.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {E8420BB9-95C6-448A-B11C-88552D073C00} 8 | WinExe 9 | Properties 10 | KVGridUIWPF 11 | KVGridUIWPF 12 | v4.6.1 13 | 512 14 | {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 15 | 4 16 | true 17 | 18 | 19 | AnyCPU 20 | true 21 | full 22 | false 23 | bin\Debug\ 24 | DEBUG;TRACE 25 | prompt 26 | 4 27 | 28 | 29 | AnyCPU 30 | pdbonly 31 | true 32 | bin\Release\ 33 | TRACE 34 | prompt 35 | 4 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 4.0 48 | 49 | 50 | 51 | 52 | 53 | ..\packages\Extended.Wpf.Toolkit.2.9\lib\net40\Xceed.Wpf.AvalonDock.dll 54 | True 55 | 56 | 57 | ..\packages\Extended.Wpf.Toolkit.2.9\lib\net40\Xceed.Wpf.AvalonDock.Themes.Aero.dll 58 | True 59 | 60 | 61 | ..\packages\Extended.Wpf.Toolkit.2.9\lib\net40\Xceed.Wpf.AvalonDock.Themes.Metro.dll 62 | True 63 | 64 | 65 | ..\packages\Extended.Wpf.Toolkit.2.9\lib\net40\Xceed.Wpf.AvalonDock.Themes.VS2010.dll 66 | True 67 | 68 | 69 | ..\packages\Extended.Wpf.Toolkit.2.9\lib\net40\Xceed.Wpf.DataGrid.dll 70 | True 71 | 72 | 73 | ..\packages\Extended.Wpf.Toolkit.2.9\lib\net40\Xceed.Wpf.Toolkit.dll 74 | True 75 | 76 | 77 | 78 | 79 | MSBuild:Compile 80 | Designer 81 | 82 | 83 | Designer 84 | MSBuild:Compile 85 | 86 | 87 | Designer 88 | MSBuild:Compile 89 | 90 | 91 | Designer 92 | MSBuild:Compile 93 | 94 | 95 | Designer 96 | MSBuild:Compile 97 | 98 | 99 | MSBuild:Compile 100 | Designer 101 | 102 | 103 | App.xaml 104 | Code 105 | 106 | 107 | KVGridItem_TextText.xaml 108 | 109 | 110 | KVSFITextBox.xaml 111 | 112 | 113 | 114 | KVGrid.xaml 115 | 116 | 117 | KVGridBlock.xaml 118 | 119 | 120 | 121 | 122 | 123 | 124 | MainWindow.xaml 125 | Code 126 | 127 | 128 | 129 | 130 | Code 131 | 132 | 133 | True 134 | True 135 | Resources.resx 136 | 137 | 138 | True 139 | Settings.settings 140 | True 141 | 142 | 143 | ResXFileCodeGenerator 144 | Resources.Designer.cs 145 | 146 | 147 | 148 | SettingsSingleFileGenerator 149 | Settings.Designer.cs 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | {AC78AC0C-F24C-440C-89DC-AF8DA50CCC13} 159 | SplitContainer 160 | 161 | 162 | 163 | 164 | 171 | -------------------------------------------------------------------------------- /SimpleDota2EditorWPF/Panels/KV/OffsetColorizer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics.CodeAnalysis; 3 | using System.Windows.Media; 4 | using ICSharpCode.AvalonEdit.Document; 5 | using ICSharpCode.AvalonEdit.Rendering; 6 | 7 | namespace SimpleDota2EditorWPF.Panels.KV 8 | { 9 | public class OffsetColorizer : DocumentColorizingTransformer 10 | { 11 | public string tempText; 12 | private SolidColorBrush[] brushes; 13 | private SolidColorBrush sameSelectionsBrush; 14 | public string selectedText; 15 | 16 | public OffsetColorizer() 17 | { 18 | Update(); 19 | } 20 | 21 | public void Update() 22 | { 23 | brushes = new SolidColorBrush[6]; 24 | brushes[(int)KV_STYLES.STYLE_DEFAULT] = new SolidColorBrush((Color)ColorConverter.ConvertFromString(DataBase.Settings.HighSetts.DefaultWordColor)); 25 | brushes[(int)KV_STYLES.STYLE_COMMENT] = new SolidColorBrush((Color)ColorConverter.ConvertFromString(DataBase.Settings.HighSetts.CommentColor)); 26 | brushes[(int)KV_STYLES.STYLE_KVBLOCK] = new SolidColorBrush((Color)ColorConverter.ConvertFromString(DataBase.Settings.HighSetts.KVBlockColor)); 27 | brushes[(int)KV_STYLES.STYLE_KEY] = new SolidColorBrush((Color)ColorConverter.ConvertFromString(DataBase.Settings.HighSetts.KeyColor)); 28 | brushes[(int)KV_STYLES.STYLE_VALUE_STRING] = new SolidColorBrush((Color)ColorConverter.ConvertFromString(DataBase.Settings.HighSetts.ValueStringColor)); 29 | brushes[(int)KV_STYLES.STYLE_VALUE_NUMBER] = new SolidColorBrush((Color)ColorConverter.ConvertFromString(DataBase.Settings.HighSetts.ValueNumberColor)); 30 | 31 | sameSelectionsBrush = new SolidColorBrush(Colors.Blue); 32 | sameSelectionsBrush.Opacity = 0.5; 33 | } 34 | 35 | protected override void ColorizeLine(DocumentLine line) 36 | { 37 | if (line.Length == 0) 38 | return; 39 | 40 | try 41 | { 42 | var pos = line.Offset; 43 | var endPos = line.EndOffset; 44 | bool key = true; // Ожидается, что будет далее, ключ(true) или значение(false) 45 | 46 | var ch = tempText[pos]; 47 | colorizeSelectedWordInLine(tempText.Substring(pos, line.Length), pos); 48 | while (pos < endPos) 49 | { 50 | ch = tempText[pos]; 51 | if (!SomeUtils.StringUtils.IsSpaceOrTab(ch) || ch != '\n') 52 | switch (ch) 53 | { 54 | case '\"': 55 | int end = nextCharThroughIs(tempText, pos, '\"'); 56 | if (end == -1) 57 | { 58 | ChangeLinePart(pos, endPos + 1, element => element.TextRunProperties.SetForegroundBrush( 59 | brushes[key ? (int)KV_STYLES.STYLE_KEY : (int)KV_STYLES.STYLE_VALUE_STRING])); 60 | return; 61 | } 62 | 63 | int isBlock = nextCharThroughIs(tempText, end + 1, '{'); 64 | if (isBlock != -1) 65 | { 66 | key = true; 67 | if (end > endPos) end = endPos; 68 | ChangeLinePart(pos, end + 1, element => element.TextRunProperties.SetForegroundBrush( 69 | brushes[(int)KV_STYLES.STYLE_KVBLOCK])); 70 | pos = end; 71 | } 72 | else 73 | { 74 | string str = tempText.Substring(pos + 1, end - (pos + 1)); 75 | int style = 0; 76 | if (SomeUtils.StringUtils.IsDigit(str)) 77 | style = (int)KV_STYLES.STYLE_VALUE_NUMBER; 78 | else 79 | style = key ? (int)KV_STYLES.STYLE_KEY : (int)KV_STYLES.STYLE_VALUE_STRING; 80 | 81 | if (end > endPos) end = endPos; 82 | ChangeLinePart(pos, end + 1, element => element.TextRunProperties.SetForegroundBrush( 83 | brushes[style])); 84 | pos = end; 85 | key = !key; 86 | } 87 | break; 88 | 89 | case '/': 90 | if (pos + 1 >= tempText.Length) 91 | return; 92 | if (tempText[pos + 1] != '/') 93 | break; 94 | 95 | ChangeLinePart(pos, endPos, element => element.TextRunProperties.SetForegroundBrush( 96 | brushes[(int)KV_STYLES.STYLE_COMMENT])); 97 | return; 98 | break; 99 | 100 | case '{': 101 | case '}': 102 | ChangeLinePart(pos, pos + 1, element => element.TextRunProperties.SetForegroundBrush( 103 | brushes[(int)KV_STYLES.STYLE_DEFAULT])); 104 | break; 105 | } 106 | 107 | pos++; 108 | } 109 | } 110 | catch (Exception ex) 111 | { 112 | //Console.WriteLine(@"Error - " + ex.Message); 113 | 114 | } 115 | } 116 | 117 | private void colorizeSelectedWordInLine(string line, int offset) 118 | { 119 | if (String.IsNullOrWhiteSpace(selectedText) || String.IsNullOrWhiteSpace(line)) 120 | return; 121 | 122 | int i = line.IndexOf(selectedText, StringComparison.Ordinal); 123 | int end = 0; 124 | while (i != -1) 125 | { 126 | end = i + selectedText.Length; 127 | i += offset; 128 | 129 | ChangeLinePart(i, end + offset, element => element.TextRunProperties.SetBackgroundBrush( 130 | sameSelectionsBrush)); 131 | 132 | if (line.Length <= end) 133 | return; 134 | 135 | line = line.Substring(end); 136 | 137 | offset += end; 138 | i = line.IndexOf(selectedText, StringComparison.Ordinal); 139 | } 140 | 141 | } 142 | 143 | [SuppressMessage("ReSharper", "InconsistentNaming")] 144 | public enum KV_STYLES 145 | { 146 | STYLE_DEFAULT, 147 | STYLE_KEY, 148 | STYLE_KVBLOCK, 149 | STYLE_VALUE_NUMBER, 150 | STYLE_VALUE_STRING, 151 | STYLE_COMMENT, 152 | } 153 | 154 | private int nextCharThroughIs(string str, int pos, char target) 155 | { 156 | int n = pos; 157 | while (n < str.Length) 158 | { 159 | switch (str[n]) 160 | { 161 | case '{': 162 | if (target == '{') 163 | return n; 164 | break; 165 | 166 | case '/': 167 | while (str[n] != '\n') 168 | { 169 | n++; 170 | } 171 | break; 172 | 173 | case '\"': 174 | if (target == '{') 175 | return -1; 176 | n++; 177 | if (n >= str.Length) 178 | return -1; 179 | 180 | while (str[n] != '\"') 181 | { 182 | n++; 183 | if (n >= str.Length) 184 | return -1; 185 | } 186 | if (target == '\"') 187 | return n; 188 | break; 189 | } 190 | 191 | n++; 192 | } 193 | 194 | return -1; 195 | } 196 | 197 | 198 | } 199 | } -------------------------------------------------------------------------------- /KVGridUIWPF/Items/KVGridBlock.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Windows; 5 | using System.Windows.Controls; 6 | using System.Windows.Media; 7 | 8 | namespace KVGridUIWPF 9 | { 10 | /// 11 | /// Логика взаимодействия для KVGridBlock.xaml 12 | /// 13 | public partial class KVGridBlock : UserControl, KVGridItemInterface 14 | { 15 | public KVGridBlock() 16 | { 17 | InitConstructor(-1); 18 | } 19 | 20 | public KVGridBlock(int id = -1) 21 | { 22 | InitConstructor(id); 23 | } 24 | 25 | private void InitConstructor(int id) 26 | { 27 | this.Id = id; 28 | kvItems = new List(); 29 | ItemType = ItemTypes.Block; 30 | 31 | InitializeComponent(); 32 | 33 | kvsfiTextBoxKey.OnActivateClick += select_Click; 34 | kvsfiTextBoxKey.OnTextChanged += KeyTextChanged; 35 | } 36 | 37 | private void KeyTextChanged(string oldText, string newText) 38 | { 39 | OnTextChanged?.Invoke(this, oldText, newText, KVType.Key); 40 | } 41 | 42 | /// 43 | /// Hides Plus/Minus and Main key controls 44 | /// 45 | public void HideKVBlockControls(bool hide) 46 | { 47 | if (hide) 48 | { 49 | Grid1.ColumnDefinitions[0].Width = new GridLength(0); 50 | Grid1.RowDefinitions[0].Height = new GridLength(0); 51 | } 52 | else 53 | { 54 | Grid1.ColumnDefinitions[0].Width = new GridLength(1, GridUnitType.Star); 55 | Grid1.RowDefinitions[0].Height = new GridLength(1, GridUnitType.Star); 56 | } 57 | } 58 | 59 | public KVGridItemInterface AddItem(KVGrid owner, KVGridItemInterface item, int position) 60 | { 61 | if (item == null) return null; 62 | 63 | if (item.Id == -1) 64 | item.Id = owner.GetMyId(); 65 | item.ParentBlock = this; 66 | item.GridOwner = owner; 67 | if (position == -1) 68 | { 69 | kvItems.Add(item); 70 | position = kvItems.Count - 1; 71 | Grid2.RowDefinitions.Add(new RowDefinition()); 72 | } 73 | else 74 | { 75 | kvItems.Insert(position, item); 76 | Grid2.RowDefinitions.Add(new RowDefinition()); 77 | for (int i = position; i < Grid2.Children.Count; i++) 78 | { 79 | Grid2.Children[i].SetValue(Grid.RowProperty, i + 1); 80 | //Grid2.RowDefinitions[i].Height = GridLength.Auto; 81 | } 82 | } 83 | var ctrl = ((UserControl)item); 84 | 85 | 86 | ctrl.HorizontalAlignment = HorizontalAlignment.Stretch; 87 | ctrl.VerticalAlignment = VerticalAlignment.Top; 88 | ctrl.SetValue(Grid.ColumnProperty, 1); 89 | ctrl.SetValue(Grid.RowProperty, position); 90 | Grid2.Children.Insert(position, ctrl); 91 | Grid2.RowDefinitions[position].Height = GridLength.Auto; 92 | 93 | return item; 94 | } 95 | 96 | public void RemoveItem(KVGridItemInterface item, bool disposeItem) 97 | { 98 | if (item == null) return; 99 | 100 | if (GridOwner.SelectedItem == item) 101 | GridOwner.SelectedItem = null; 102 | 103 | int id = Items.IndexOf(item); 104 | Items.Remove(item); 105 | Grid2.Children.Remove((UserControl)item); 106 | 107 | for (int i = id; i < Grid2.Children.Count; i++) 108 | { 109 | Grid2.Children[i].SetValue(Grid.RowProperty, i); 110 | } 111 | Grid2.RowDefinitions.RemoveAt(Grid2.RowDefinitions.Count - 1); 112 | } 113 | 114 | public void MoveItemTo(KVGridItemInterface item, int index) 115 | { 116 | //todo Oplkill wpf 117 | if (!Equals(item.ParentBlock, this)) return; 118 | 119 | bool selectedItem = GridOwner.SelectedItem == item; 120 | RemoveItem(item, false); 121 | if (index >= Items.Count) 122 | Items.Add(item); 123 | else 124 | Items.Insert(index, item); 125 | 126 | if (selectedItem) 127 | GridOwner.SelectedItem = item; 128 | } 129 | 130 | public KVGridItemInterface FindItem(string key, string value) 131 | { 132 | return Items.FirstOrDefault(item => item.KeyText == key && item.ValueText == value); 133 | } 134 | 135 | public KVGridItemInterface FindItemId(int id) 136 | { 137 | if (this.Id == id) return this; 138 | 139 | foreach (var item in Items) 140 | { 141 | if (item.Id == id) return item; 142 | 143 | if (item is KVGridBlock) 144 | { 145 | var itemTemp = ((KVGridBlock)item).FindItemId(id); 146 | if (itemTemp != null) 147 | return itemTemp; 148 | } 149 | } 150 | 151 | return null; 152 | } 153 | 154 | /// 155 | /// Swapping items only if they both in this block 156 | /// 157 | public void SwapItems(KVGridItemInterface item1, KVGridItemInterface item2) 158 | { 159 | if (!Items.Contains(item1) || !Items.Contains(item2)) return; 160 | 161 | int index1 = Items.IndexOf(item1); 162 | int index2 = Items.IndexOf(item2); 163 | 164 | Items[index1] = item2; 165 | Items[index2] = item1; 166 | 167 | Grid2.Children[index1].SetValue(Grid.RowProperty, index2); 168 | Grid2.Children[index2].SetValue(Grid.RowProperty, index1); 169 | } 170 | 171 | private void buttonCollapse_Click(object sender, EventArgs e) 172 | { 173 | select_Click(sender, e); 174 | 175 | if (collapsed) 176 | { 177 | collapsed = false; 178 | Grid1.RowDefinitions[1].Height = new GridLength(1, GridUnitType.Star); 179 | buttonCollapse.Content = @"-"; 180 | } 181 | else 182 | { 183 | collapsed = true; 184 | Grid1.RowDefinitions[1].Height = new GridLength(0); 185 | buttonCollapse.Content = @"+"; 186 | } 187 | } 188 | 189 | private void select_Click(object sender, EventArgs e) 190 | { 191 | GridOwner.SelectedItem = this; 192 | } 193 | 194 | 195 | #region variables 196 | 197 | 198 | 199 | public bool Selected 200 | { 201 | get 202 | { 203 | //todo Oplkill wpf 204 | //return splitContainer1.BackColor != Control.DefaultBackColor; 205 | return false; 206 | } 207 | set 208 | { 209 | //todo Oplkill wpf 210 | //if (this.Selected == value) return; 211 | 212 | //if (value) 213 | //{ 214 | // splitContainer1.BackColor = Color.DarkBlue; 215 | // //GridOwner.SelectedItem = this; 216 | //} 217 | //else 218 | //{ 219 | // splitContainer1.BackColor = Control.DefaultBackColor; 220 | // //GridOwner.SelectedItem = null; 221 | //} 222 | } 223 | } 224 | 225 | public int Id { get; set; } 226 | public KVGrid.TextChangedFunc OnTextChanged { get; set; } 227 | 228 | public int ItemHeight { get; private set; } 229 | public KVGridBlock ParentBlock { get; set; } 230 | public ItemTypes ItemType { get; private set; } 231 | /// 232 | /// KVgrid owner 233 | /// 234 | public KVGrid GridOwner { get; set; } 235 | 236 | public string KeyText 237 | { 238 | get { return kvsfiTextBoxKey.Text; } 239 | set { kvsfiTextBoxKey.Text = value; } 240 | } 241 | public string ValueText { get { return null; } set { } } 242 | public List Items => kvItems; 243 | 244 | private List kvItems; 245 | private bool collapsed; 246 | 247 | #endregion 248 | } 249 | } 250 | --------------------------------------------------------------------------------