From 28ccf83dbdf3eeadf8d016bd768327ee844478fe Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jean-Philippe=20Bruy=C3=A8re?= Date: Fri, 12 Jun 2020 13:23:04 +0200 Subject: [PATCH] Crow.Coding library --- .gitignore | 1 + Crow.Coding/Crow.Coding.csproj | 20 + Crow.Coding/Properties/AssemblyInfo.cs | 5 + Crow.Coding/icons/blank-file.svg | 6 + Crow.Coding/icons/compile.svg | 9 + Crow.Coding/icons/copy-file.svg | 6 + Crow.Coding/icons/curly-brackets.svg | 7 + Crow.Coding/icons/edit.svg | 6 + Crow.Coding/icons/eraser.svg | 6 + Crow.Coding/icons/file.svg | 6 + Crow.Coding/icons/folder.svg | 11 + Crow.Coding/icons/light-bulb.svg | 7 + Crow.Coding/icons/move-arrows.svg | 6 + Crow.Coding/icons/open.svg | 7 + Crow.Coding/icons/paint-brush.svg | 8 + Crow.Coding/icons/palette.svg | 6 + Crow.Coding/icons/paste-on-document.svg | 6 + Crow.Coding/icons/pin.svg | 6 + Crow.Coding/icons/question.svg | 7 + Crow.Coding/icons/redo.svg | 6 + Crow.Coding/icons/save.svg | 7 + Crow.Coding/icons/scissors.svg | 6 + Crow.Coding/icons/search.svg | 6 + Crow.Coding/icons/text-file.svg | 9 + Crow.Coding/icons/toolbox/Crow.Border.svg | 6 + Crow.Coding/icons/toolbox/Crow.Button.svg | 6 + Crow.Coding/icons/toolbox/Crow.CheckBox.svg | 6 + .../icons/toolbox/Crow.ColorPicker.svg | 6 + Crow.Coding/icons/toolbox/Crow.ComboBox.svg | 7 + Crow.Coding/icons/toolbox/Crow.Container.svg | 6 + .../icons/toolbox/Crow.DirectoryView.svg | 6 + Crow.Coding/icons/toolbox/Crow.Docker.svg | 6 + Crow.Coding/icons/toolbox/Crow.Expandable.svg | 6 + Crow.Coding/icons/toolbox/Crow.FileDialog.svg | 8 + Crow.Coding/icons/toolbox/Crow.Grid.svg | 6 + Crow.Coding/icons/toolbox/Crow.Group.svg | 9 + Crow.Coding/icons/toolbox/Crow.GroupBox.svg | 10 + .../icons/toolbox/Crow.HorizontalStack.svg | 6 + .../icons/toolbox/Crow.IMLContainer.svg | 8 + Crow.Coding/icons/toolbox/Crow.Image.svg | 8 + Crow.Coding/icons/toolbox/Crow.Label.svg | 7 + Crow.Coding/icons/toolbox/Crow.ListBox.svg | 11 + Crow.Coding/icons/toolbox/Crow.Menu.svg | 11 + Crow.Coding/icons/toolbox/Crow.MenuItem.svg | 7 + Crow.Coding/icons/toolbox/Crow.MessageBox.svg | 8 + .../icons/toolbox/Crow.ProgressBar.svg | 7 + .../icons/toolbox/Crow.RadioButton.svg | 7 + Crow.Coding/icons/toolbox/Crow.ScrollBar.svg | 7 + Crow.Coding/icons/toolbox/Crow.Scroller.svg | 6 + Crow.Coding/icons/toolbox/Crow.Shape.svg | 6 + Crow.Coding/icons/toolbox/Crow.Slider.svg | 6 + Crow.Coding/icons/toolbox/Crow.Spinner.svg | 7 + Crow.Coding/icons/toolbox/Crow.Splitter.svg | 8 + Crow.Coding/icons/toolbox/Crow.TabItem.svg | 6 + Crow.Coding/icons/toolbox/Crow.TabView.svg | 6 + .../icons/toolbox/Crow.TemplatedContainer.svg | 6 + .../icons/toolbox/Crow.TemplatedGroup.svg | 6 + Crow.Coding/icons/toolbox/Crow.TextBox.svg | 7 + Crow.Coding/icons/toolbox/Crow.TreeView.svg | 6 + .../icons/toolbox/Crow.VerticalStack.svg | 6 + Crow.Coding/icons/toolbox/Crow.Window.svg | 6 + Crow.Coding/icons/toolbox/Crow.Wrapper.svg | 8 + Crow.Coding/icons/toolbox/bar-chart.svg | 10 + Crow.Coding/icons/toolbox/bar-menu.svg | 8 + Crow.Coding/icons/toolbox/bullets.svg | 11 + Crow.Coding/icons/toolbox/calendar.svg | 8 + Crow.Coding/icons/toolbox/check-square-1.svg | 7 + Crow.Coding/icons/toolbox/database.svg | 9 + Crow.Coding/icons/toolbox/ellipsis.svg | 8 + Crow.Coding/icons/toolbox/file-code.svg | 9 + Crow.Coding/icons/toolbox/grab.svg | 6 + Crow.Coding/icons/toolbox/hash.svg | 6 + Crow.Coding/icons/toolbox/line-list.svg | 13 + Crow.Coding/icons/toolbox/list.svg | 11 + Crow.Coding/icons/toolbox/modal-list.svg | 12 + Crow.Coding/icons/toolbox/options.svg | 10 + Crow.Coding/icons/toolbox/package.svg | 6 + Crow.Coding/icons/toolbox/padding.svg | 47 + Crow.Coding/icons/toolbox/picture-file.svg | 8 + Crow.Coding/icons/toolbox/pointer.svg | 6 + Crow.Coding/icons/toolbox/puzzle-piece.svg | 6 + Crow.Coding/icons/toolbox/refresh-file.svg | 8 + Crow.Coding/icons/toolbox/sliders.svg | 11 + Crow.Coding/icons/toolbox/split-browser-1.svg | 6 + Crow.Coding/icons/toolbox/table.svg | 6 + Crow.Coding/icons/toolbox/tasks.svg | 11 + Crow.Coding/icons/toolbox/warning.svg | 6 + Crow.Coding/icons/tools.svg | 8 + Crow.Coding/icons/trash.svg | 7 + Crow.Coding/icons/undo.svg | 6 + Crow.Coding/icons/zoom-in.svg | 7 + Crow.Coding/icons/zoom-out.svg | 7 + Crow.Coding/images/save.svg | 3421 +++++++++++++++++ .../src/CodeBuffer}/CodeBuffer.cs | 255 +- .../src/CodeBuffer/CodeBufferEventArgs.cs | 0 .../src/CodeBuffer}/CodeLine.cs | 16 +- {src => Crow.Coding/src/CodeBuffer}/Node.cs | 4 + Crow.Coding/src/CodeBuffer/TextBuffer.cs | 527 +++ .../src/CodeBuffer/TextBufferEventArgs.cs | 20 + Crow.Coding/src/CodeBuffer/TextEditor.cs | 697 ++++ .../src/CodeBuffer}/TextFormatting.cs | 0 {src => Crow.Coding/src/CodeBuffer}/Token.cs | 6 +- .../src/Parsers/BufferParser.cs | 262 +- Crow.Coding/src/Parsers/CSharpParser.cs | 386 ++ Crow.Coding/src/Parsers/StyleParser.cs | 179 + {src => Crow.Coding/src/Parsers}/XMLParser.cs | 113 +- Crow.Coding/src/Parsers2/Tokenizer.cs | 67 + {src => Crow.Coding/src}/SourceEditor.cs | 864 +++-- Crow.Coding/ui/CategoryExp.template | 21 + Crow.Coding/ui/ContextMenu.template | 42 + Crow.Coding/ui/IDE.style | 29 + Crow.Coding/ui/IcoBut.template | 7 + Crow.Coding/ui/ItemTemplates/Enum.template | 47 + Crow.Coding/ui/ItemTemplates/Fill.template | 19 + Crow.Coding/ui/MenuItem.template | 29 + Crow.Coding/ui/icons/basic_floppydisk.svg | 15 + Crow.Coding/ui/icons/blank-file.svg | 6 + Crow.Coding/ui/icons/center-align.svg | 9 + Crow.Coding/ui/icons/cogwheel.svg | 7 + Crow.Coding/ui/icons/edit.svg | 6 + Crow.Coding/ui/icons/file-code.svg | 9 + Crow.Coding/ui/icons/folder.svg | 6 + Crow.Coding/ui/icons/font-file.svg | 7 + Crow.Coding/ui/icons/light-bulb.svg | 7 + Crow.Coding/ui/icons/paragraph.svg | 6 + Crow.Coding/ui/icons/previous.svg | 6 + Crow.Coding/ui/icons/question.svg | 7 + Crow.Coding/ui/icons/reply.svg | 6 + Crow.Coding/ui/icons/search.svg | 6 + Crow.Coding/ui/icons/share-arrow.svg | 6 + Crow.Coding/ui/icons/sign-out.svg | 7 + Crow.Coding/ui/icons/text-file.svg | 9 + Crow.Coding/ui/icons/text-label.svg | 7 + Crow.Coding/ui/icons/tools.svg | 8 + Crow.Coding/ui/icons/zoom-in.svg | 7 + Crow.Coding/ui/icons/zoom-out.svg | 7 + CrowEdit.csproj | 146 +- CrowEdit.sln | 12 + CrowWindow.cs | 1 - Directory.Build.props | 9 + OpenGL/Extensions.cs | 41 - OpenGL/Shader.cs | 336 -- OpenGL/Texture.cs | 94 - OpenGL/vaoMesh.cs | 221 -- ParsingException.cs | 22 - src/CSharpParser.cs | 45 - src/CrowEdit.cs | 162 +- src/CrowEditExtentions.cs | 41 - ui/EditorOptions.crow | 2 +- ui/icons/basic_floppydisk.svg | 18 +- ui/main.crow | 106 +- 151 files changed, 7481 insertions(+), 1659 deletions(-) create mode 100644 Crow.Coding/Crow.Coding.csproj create mode 100644 Crow.Coding/Properties/AssemblyInfo.cs create mode 100644 Crow.Coding/icons/blank-file.svg create mode 100644 Crow.Coding/icons/compile.svg create mode 100644 Crow.Coding/icons/copy-file.svg create mode 100644 Crow.Coding/icons/curly-brackets.svg create mode 100644 Crow.Coding/icons/edit.svg create mode 100644 Crow.Coding/icons/eraser.svg create mode 100644 Crow.Coding/icons/file.svg create mode 100644 Crow.Coding/icons/folder.svg create mode 100644 Crow.Coding/icons/light-bulb.svg create mode 100644 Crow.Coding/icons/move-arrows.svg create mode 100644 Crow.Coding/icons/open.svg create mode 100644 Crow.Coding/icons/paint-brush.svg create mode 100644 Crow.Coding/icons/palette.svg create mode 100644 Crow.Coding/icons/paste-on-document.svg create mode 100644 Crow.Coding/icons/pin.svg create mode 100644 Crow.Coding/icons/question.svg create mode 100644 Crow.Coding/icons/redo.svg create mode 100644 Crow.Coding/icons/save.svg create mode 100644 Crow.Coding/icons/scissors.svg create mode 100644 Crow.Coding/icons/search.svg create mode 100644 Crow.Coding/icons/text-file.svg create mode 100644 Crow.Coding/icons/toolbox/Crow.Border.svg create mode 100644 Crow.Coding/icons/toolbox/Crow.Button.svg create mode 100644 Crow.Coding/icons/toolbox/Crow.CheckBox.svg create mode 100644 Crow.Coding/icons/toolbox/Crow.ColorPicker.svg create mode 100644 Crow.Coding/icons/toolbox/Crow.ComboBox.svg create mode 100644 Crow.Coding/icons/toolbox/Crow.Container.svg create mode 100644 Crow.Coding/icons/toolbox/Crow.DirectoryView.svg create mode 100644 Crow.Coding/icons/toolbox/Crow.Docker.svg create mode 100644 Crow.Coding/icons/toolbox/Crow.Expandable.svg create mode 100644 Crow.Coding/icons/toolbox/Crow.FileDialog.svg create mode 100644 Crow.Coding/icons/toolbox/Crow.Grid.svg create mode 100644 Crow.Coding/icons/toolbox/Crow.Group.svg create mode 100644 Crow.Coding/icons/toolbox/Crow.GroupBox.svg create mode 100644 Crow.Coding/icons/toolbox/Crow.HorizontalStack.svg create mode 100644 Crow.Coding/icons/toolbox/Crow.IMLContainer.svg create mode 100644 Crow.Coding/icons/toolbox/Crow.Image.svg create mode 100644 Crow.Coding/icons/toolbox/Crow.Label.svg create mode 100644 Crow.Coding/icons/toolbox/Crow.ListBox.svg create mode 100644 Crow.Coding/icons/toolbox/Crow.Menu.svg create mode 100644 Crow.Coding/icons/toolbox/Crow.MenuItem.svg create mode 100644 Crow.Coding/icons/toolbox/Crow.MessageBox.svg create mode 100644 Crow.Coding/icons/toolbox/Crow.ProgressBar.svg create mode 100644 Crow.Coding/icons/toolbox/Crow.RadioButton.svg create mode 100644 Crow.Coding/icons/toolbox/Crow.ScrollBar.svg create mode 100644 Crow.Coding/icons/toolbox/Crow.Scroller.svg create mode 100644 Crow.Coding/icons/toolbox/Crow.Shape.svg create mode 100644 Crow.Coding/icons/toolbox/Crow.Slider.svg create mode 100644 Crow.Coding/icons/toolbox/Crow.Spinner.svg create mode 100644 Crow.Coding/icons/toolbox/Crow.Splitter.svg create mode 100644 Crow.Coding/icons/toolbox/Crow.TabItem.svg create mode 100644 Crow.Coding/icons/toolbox/Crow.TabView.svg create mode 100644 Crow.Coding/icons/toolbox/Crow.TemplatedContainer.svg create mode 100644 Crow.Coding/icons/toolbox/Crow.TemplatedGroup.svg create mode 100644 Crow.Coding/icons/toolbox/Crow.TextBox.svg create mode 100644 Crow.Coding/icons/toolbox/Crow.TreeView.svg create mode 100644 Crow.Coding/icons/toolbox/Crow.VerticalStack.svg create mode 100644 Crow.Coding/icons/toolbox/Crow.Window.svg create mode 100644 Crow.Coding/icons/toolbox/Crow.Wrapper.svg create mode 100644 Crow.Coding/icons/toolbox/bar-chart.svg create mode 100644 Crow.Coding/icons/toolbox/bar-menu.svg create mode 100644 Crow.Coding/icons/toolbox/bullets.svg create mode 100644 Crow.Coding/icons/toolbox/calendar.svg create mode 100644 Crow.Coding/icons/toolbox/check-square-1.svg create mode 100644 Crow.Coding/icons/toolbox/database.svg create mode 100644 Crow.Coding/icons/toolbox/ellipsis.svg create mode 100644 Crow.Coding/icons/toolbox/file-code.svg create mode 100644 Crow.Coding/icons/toolbox/grab.svg create mode 100644 Crow.Coding/icons/toolbox/hash.svg create mode 100644 Crow.Coding/icons/toolbox/line-list.svg create mode 100644 Crow.Coding/icons/toolbox/list.svg create mode 100644 Crow.Coding/icons/toolbox/modal-list.svg create mode 100644 Crow.Coding/icons/toolbox/options.svg create mode 100644 Crow.Coding/icons/toolbox/package.svg create mode 100644 Crow.Coding/icons/toolbox/padding.svg create mode 100644 Crow.Coding/icons/toolbox/picture-file.svg create mode 100644 Crow.Coding/icons/toolbox/pointer.svg create mode 100644 Crow.Coding/icons/toolbox/puzzle-piece.svg create mode 100644 Crow.Coding/icons/toolbox/refresh-file.svg create mode 100644 Crow.Coding/icons/toolbox/sliders.svg create mode 100644 Crow.Coding/icons/toolbox/split-browser-1.svg create mode 100644 Crow.Coding/icons/toolbox/table.svg create mode 100644 Crow.Coding/icons/toolbox/tasks.svg create mode 100644 Crow.Coding/icons/toolbox/warning.svg create mode 100644 Crow.Coding/icons/tools.svg create mode 100644 Crow.Coding/icons/trash.svg create mode 100644 Crow.Coding/icons/undo.svg create mode 100644 Crow.Coding/icons/zoom-in.svg create mode 100644 Crow.Coding/icons/zoom-out.svg create mode 100644 Crow.Coding/images/save.svg rename {src => Crow.Coding/src/CodeBuffer}/CodeBuffer.cs (66%) rename CodeBufferEventArgs.cs => Crow.Coding/src/CodeBuffer/CodeBufferEventArgs.cs (100%) rename {src => Crow.Coding/src/CodeBuffer}/CodeLine.cs (72%) rename {src => Crow.Coding/src/CodeBuffer}/Node.cs (87%) create mode 100644 Crow.Coding/src/CodeBuffer/TextBuffer.cs create mode 100644 Crow.Coding/src/CodeBuffer/TextBufferEventArgs.cs create mode 100644 Crow.Coding/src/CodeBuffer/TextEditor.cs rename {src => Crow.Coding/src/CodeBuffer}/TextFormatting.cs (100%) rename {src => Crow.Coding/src/CodeBuffer}/Token.cs (91%) rename src/Parser.cs => Crow.Coding/src/Parsers/BufferParser.cs (68%) create mode 100644 Crow.Coding/src/Parsers/CSharpParser.cs create mode 100644 Crow.Coding/src/Parsers/StyleParser.cs rename {src => Crow.Coding/src/Parsers}/XMLParser.cs (66%) create mode 100644 Crow.Coding/src/Parsers2/Tokenizer.cs rename {src => Crow.Coding/src}/SourceEditor.cs (56%) create mode 100755 Crow.Coding/ui/CategoryExp.template create mode 100644 Crow.Coding/ui/ContextMenu.template create mode 100644 Crow.Coding/ui/IDE.style create mode 100644 Crow.Coding/ui/IcoBut.template create mode 100755 Crow.Coding/ui/ItemTemplates/Enum.template create mode 100755 Crow.Coding/ui/ItemTemplates/Fill.template create mode 100644 Crow.Coding/ui/MenuItem.template create mode 100644 Crow.Coding/ui/icons/basic_floppydisk.svg create mode 100644 Crow.Coding/ui/icons/blank-file.svg create mode 100644 Crow.Coding/ui/icons/center-align.svg create mode 100644 Crow.Coding/ui/icons/cogwheel.svg create mode 100644 Crow.Coding/ui/icons/edit.svg create mode 100644 Crow.Coding/ui/icons/file-code.svg create mode 100644 Crow.Coding/ui/icons/folder.svg create mode 100644 Crow.Coding/ui/icons/font-file.svg create mode 100644 Crow.Coding/ui/icons/light-bulb.svg create mode 100644 Crow.Coding/ui/icons/paragraph.svg create mode 100644 Crow.Coding/ui/icons/previous.svg create mode 100644 Crow.Coding/ui/icons/question.svg create mode 100644 Crow.Coding/ui/icons/reply.svg create mode 100644 Crow.Coding/ui/icons/search.svg create mode 100644 Crow.Coding/ui/icons/share-arrow.svg create mode 100644 Crow.Coding/ui/icons/sign-out.svg create mode 100644 Crow.Coding/ui/icons/text-file.svg create mode 100644 Crow.Coding/ui/icons/text-label.svg create mode 100644 Crow.Coding/ui/icons/tools.svg create mode 100644 Crow.Coding/ui/icons/zoom-in.svg create mode 100644 Crow.Coding/ui/icons/zoom-out.svg create mode 100644 Directory.Build.props delete mode 100644 OpenGL/Extensions.cs delete mode 100644 OpenGL/Shader.cs delete mode 100644 OpenGL/Texture.cs delete mode 100644 OpenGL/vaoMesh.cs delete mode 100644 ParsingException.cs delete mode 100644 src/CSharpParser.cs delete mode 100644 src/CrowEditExtentions.cs diff --git a/.gitignore b/.gitignore index 88e1fca..a9f5d34 100644 --- a/.gitignore +++ b/.gitignore @@ -39,3 +39,4 @@ Thumbs.db #dotCover *.dotCover +.vs diff --git a/Crow.Coding/Crow.Coding.csproj b/Crow.Coding/Crow.Coding.csproj new file mode 100644 index 0000000..48dc4ec --- /dev/null +++ b/Crow.Coding/Crow.Coding.csproj @@ -0,0 +1,20 @@ + + + + netstandard2.0 + false + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Crow.Coding/Properties/AssemblyInfo.cs b/Crow.Coding/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..d864652 --- /dev/null +++ b/Crow.Coding/Properties/AssemblyInfo.cs @@ -0,0 +1,5 @@ +// Copyright (c) 2013-2020 Jean-Philippe Bruyère +// +// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) +[assembly: Crow.Crow ] + diff --git a/Crow.Coding/icons/blank-file.svg b/Crow.Coding/icons/blank-file.svg new file mode 100644 index 0000000..8136979 --- /dev/null +++ b/Crow.Coding/icons/blank-file.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/Crow.Coding/icons/compile.svg b/Crow.Coding/icons/compile.svg new file mode 100644 index 0000000..c1a14e7 --- /dev/null +++ b/Crow.Coding/icons/compile.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/Crow.Coding/icons/copy-file.svg b/Crow.Coding/icons/copy-file.svg new file mode 100644 index 0000000..63c2dd3 --- /dev/null +++ b/Crow.Coding/icons/copy-file.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/Crow.Coding/icons/curly-brackets.svg b/Crow.Coding/icons/curly-brackets.svg new file mode 100644 index 0000000..89ef798 --- /dev/null +++ b/Crow.Coding/icons/curly-brackets.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Crow.Coding/icons/edit.svg b/Crow.Coding/icons/edit.svg new file mode 100644 index 0000000..366862c --- /dev/null +++ b/Crow.Coding/icons/edit.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/Crow.Coding/icons/eraser.svg b/Crow.Coding/icons/eraser.svg new file mode 100644 index 0000000..5dd73ba --- /dev/null +++ b/Crow.Coding/icons/eraser.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/Crow.Coding/icons/file.svg b/Crow.Coding/icons/file.svg new file mode 100644 index 0000000..9d06b00 --- /dev/null +++ b/Crow.Coding/icons/file.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/Crow.Coding/icons/folder.svg b/Crow.Coding/icons/folder.svg new file mode 100644 index 0000000..f59e2da --- /dev/null +++ b/Crow.Coding/icons/folder.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/Crow.Coding/icons/light-bulb.svg b/Crow.Coding/icons/light-bulb.svg new file mode 100644 index 0000000..89ff236 --- /dev/null +++ b/Crow.Coding/icons/light-bulb.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Crow.Coding/icons/move-arrows.svg b/Crow.Coding/icons/move-arrows.svg new file mode 100644 index 0000000..ecbb2f9 --- /dev/null +++ b/Crow.Coding/icons/move-arrows.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/Crow.Coding/icons/open.svg b/Crow.Coding/icons/open.svg new file mode 100644 index 0000000..bd8d7d9 --- /dev/null +++ b/Crow.Coding/icons/open.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Crow.Coding/icons/paint-brush.svg b/Crow.Coding/icons/paint-brush.svg new file mode 100644 index 0000000..2bdd5be --- /dev/null +++ b/Crow.Coding/icons/paint-brush.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/Crow.Coding/icons/palette.svg b/Crow.Coding/icons/palette.svg new file mode 100644 index 0000000..8e425f7 --- /dev/null +++ b/Crow.Coding/icons/palette.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/Crow.Coding/icons/paste-on-document.svg b/Crow.Coding/icons/paste-on-document.svg new file mode 100644 index 0000000..b0a705e --- /dev/null +++ b/Crow.Coding/icons/paste-on-document.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/Crow.Coding/icons/pin.svg b/Crow.Coding/icons/pin.svg new file mode 100644 index 0000000..b36340b --- /dev/null +++ b/Crow.Coding/icons/pin.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/Crow.Coding/icons/question.svg b/Crow.Coding/icons/question.svg new file mode 100644 index 0000000..fb8e3d3 --- /dev/null +++ b/Crow.Coding/icons/question.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Crow.Coding/icons/redo.svg b/Crow.Coding/icons/redo.svg new file mode 100644 index 0000000..59fcc90 --- /dev/null +++ b/Crow.Coding/icons/redo.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/Crow.Coding/icons/save.svg b/Crow.Coding/icons/save.svg new file mode 100644 index 0000000..6aa6714 --- /dev/null +++ b/Crow.Coding/icons/save.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Crow.Coding/icons/scissors.svg b/Crow.Coding/icons/scissors.svg new file mode 100644 index 0000000..4b5a225 --- /dev/null +++ b/Crow.Coding/icons/scissors.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/Crow.Coding/icons/search.svg b/Crow.Coding/icons/search.svg new file mode 100644 index 0000000..f3eb368 --- /dev/null +++ b/Crow.Coding/icons/search.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/Crow.Coding/icons/text-file.svg b/Crow.Coding/icons/text-file.svg new file mode 100644 index 0000000..826bc32 --- /dev/null +++ b/Crow.Coding/icons/text-file.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/Crow.Coding/icons/toolbox/Crow.Border.svg b/Crow.Coding/icons/toolbox/Crow.Border.svg new file mode 100644 index 0000000..09eb7ac --- /dev/null +++ b/Crow.Coding/icons/toolbox/Crow.Border.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/Crow.Coding/icons/toolbox/Crow.Button.svg b/Crow.Coding/icons/toolbox/Crow.Button.svg new file mode 100644 index 0000000..01f5c6c --- /dev/null +++ b/Crow.Coding/icons/toolbox/Crow.Button.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/Crow.Coding/icons/toolbox/Crow.CheckBox.svg b/Crow.Coding/icons/toolbox/Crow.CheckBox.svg new file mode 100644 index 0000000..2f0b083 --- /dev/null +++ b/Crow.Coding/icons/toolbox/Crow.CheckBox.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/Crow.Coding/icons/toolbox/Crow.ColorPicker.svg b/Crow.Coding/icons/toolbox/Crow.ColorPicker.svg new file mode 100644 index 0000000..517a26a --- /dev/null +++ b/Crow.Coding/icons/toolbox/Crow.ColorPicker.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/Crow.Coding/icons/toolbox/Crow.ComboBox.svg b/Crow.Coding/icons/toolbox/Crow.ComboBox.svg new file mode 100644 index 0000000..1cb88fa --- /dev/null +++ b/Crow.Coding/icons/toolbox/Crow.ComboBox.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Crow.Coding/icons/toolbox/Crow.Container.svg b/Crow.Coding/icons/toolbox/Crow.Container.svg new file mode 100644 index 0000000..d7d1dc8 --- /dev/null +++ b/Crow.Coding/icons/toolbox/Crow.Container.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/Crow.Coding/icons/toolbox/Crow.DirectoryView.svg b/Crow.Coding/icons/toolbox/Crow.DirectoryView.svg new file mode 100644 index 0000000..9029469 --- /dev/null +++ b/Crow.Coding/icons/toolbox/Crow.DirectoryView.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/Crow.Coding/icons/toolbox/Crow.Docker.svg b/Crow.Coding/icons/toolbox/Crow.Docker.svg new file mode 100644 index 0000000..e38a283 --- /dev/null +++ b/Crow.Coding/icons/toolbox/Crow.Docker.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/Crow.Coding/icons/toolbox/Crow.Expandable.svg b/Crow.Coding/icons/toolbox/Crow.Expandable.svg new file mode 100644 index 0000000..1c56d56 --- /dev/null +++ b/Crow.Coding/icons/toolbox/Crow.Expandable.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/Crow.Coding/icons/toolbox/Crow.FileDialog.svg b/Crow.Coding/icons/toolbox/Crow.FileDialog.svg new file mode 100644 index 0000000..25142ea --- /dev/null +++ b/Crow.Coding/icons/toolbox/Crow.FileDialog.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/Crow.Coding/icons/toolbox/Crow.Grid.svg b/Crow.Coding/icons/toolbox/Crow.Grid.svg new file mode 100644 index 0000000..6151f97 --- /dev/null +++ b/Crow.Coding/icons/toolbox/Crow.Grid.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/Crow.Coding/icons/toolbox/Crow.Group.svg b/Crow.Coding/icons/toolbox/Crow.Group.svg new file mode 100644 index 0000000..eae67f6 --- /dev/null +++ b/Crow.Coding/icons/toolbox/Crow.Group.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/Crow.Coding/icons/toolbox/Crow.GroupBox.svg b/Crow.Coding/icons/toolbox/Crow.GroupBox.svg new file mode 100644 index 0000000..e469779 --- /dev/null +++ b/Crow.Coding/icons/toolbox/Crow.GroupBox.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/Crow.Coding/icons/toolbox/Crow.HorizontalStack.svg b/Crow.Coding/icons/toolbox/Crow.HorizontalStack.svg new file mode 100644 index 0000000..f8e7025 --- /dev/null +++ b/Crow.Coding/icons/toolbox/Crow.HorizontalStack.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/Crow.Coding/icons/toolbox/Crow.IMLContainer.svg b/Crow.Coding/icons/toolbox/Crow.IMLContainer.svg new file mode 100644 index 0000000..b5687ba --- /dev/null +++ b/Crow.Coding/icons/toolbox/Crow.IMLContainer.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/Crow.Coding/icons/toolbox/Crow.Image.svg b/Crow.Coding/icons/toolbox/Crow.Image.svg new file mode 100644 index 0000000..11356c0 --- /dev/null +++ b/Crow.Coding/icons/toolbox/Crow.Image.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/Crow.Coding/icons/toolbox/Crow.Label.svg b/Crow.Coding/icons/toolbox/Crow.Label.svg new file mode 100644 index 0000000..65bb85b --- /dev/null +++ b/Crow.Coding/icons/toolbox/Crow.Label.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Crow.Coding/icons/toolbox/Crow.ListBox.svg b/Crow.Coding/icons/toolbox/Crow.ListBox.svg new file mode 100644 index 0000000..40d1673 --- /dev/null +++ b/Crow.Coding/icons/toolbox/Crow.ListBox.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/Crow.Coding/icons/toolbox/Crow.Menu.svg b/Crow.Coding/icons/toolbox/Crow.Menu.svg new file mode 100644 index 0000000..b6b2111 --- /dev/null +++ b/Crow.Coding/icons/toolbox/Crow.Menu.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/Crow.Coding/icons/toolbox/Crow.MenuItem.svg b/Crow.Coding/icons/toolbox/Crow.MenuItem.svg new file mode 100644 index 0000000..c8bd847 --- /dev/null +++ b/Crow.Coding/icons/toolbox/Crow.MenuItem.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Crow.Coding/icons/toolbox/Crow.MessageBox.svg b/Crow.Coding/icons/toolbox/Crow.MessageBox.svg new file mode 100644 index 0000000..16ebd72 --- /dev/null +++ b/Crow.Coding/icons/toolbox/Crow.MessageBox.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/Crow.Coding/icons/toolbox/Crow.ProgressBar.svg b/Crow.Coding/icons/toolbox/Crow.ProgressBar.svg new file mode 100644 index 0000000..884f185 --- /dev/null +++ b/Crow.Coding/icons/toolbox/Crow.ProgressBar.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Crow.Coding/icons/toolbox/Crow.RadioButton.svg b/Crow.Coding/icons/toolbox/Crow.RadioButton.svg new file mode 100644 index 0000000..6c33e84 --- /dev/null +++ b/Crow.Coding/icons/toolbox/Crow.RadioButton.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Crow.Coding/icons/toolbox/Crow.ScrollBar.svg b/Crow.Coding/icons/toolbox/Crow.ScrollBar.svg new file mode 100644 index 0000000..91a1f84 --- /dev/null +++ b/Crow.Coding/icons/toolbox/Crow.ScrollBar.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Crow.Coding/icons/toolbox/Crow.Scroller.svg b/Crow.Coding/icons/toolbox/Crow.Scroller.svg new file mode 100644 index 0000000..bbc9719 --- /dev/null +++ b/Crow.Coding/icons/toolbox/Crow.Scroller.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/Crow.Coding/icons/toolbox/Crow.Shape.svg b/Crow.Coding/icons/toolbox/Crow.Shape.svg new file mode 100644 index 0000000..de5dd37 --- /dev/null +++ b/Crow.Coding/icons/toolbox/Crow.Shape.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/Crow.Coding/icons/toolbox/Crow.Slider.svg b/Crow.Coding/icons/toolbox/Crow.Slider.svg new file mode 100644 index 0000000..fe41c2b --- /dev/null +++ b/Crow.Coding/icons/toolbox/Crow.Slider.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/Crow.Coding/icons/toolbox/Crow.Spinner.svg b/Crow.Coding/icons/toolbox/Crow.Spinner.svg new file mode 100644 index 0000000..5fa848a --- /dev/null +++ b/Crow.Coding/icons/toolbox/Crow.Spinner.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Crow.Coding/icons/toolbox/Crow.Splitter.svg b/Crow.Coding/icons/toolbox/Crow.Splitter.svg new file mode 100644 index 0000000..9fcd9dd --- /dev/null +++ b/Crow.Coding/icons/toolbox/Crow.Splitter.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/Crow.Coding/icons/toolbox/Crow.TabItem.svg b/Crow.Coding/icons/toolbox/Crow.TabItem.svg new file mode 100644 index 0000000..a9aaed3 --- /dev/null +++ b/Crow.Coding/icons/toolbox/Crow.TabItem.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/Crow.Coding/icons/toolbox/Crow.TabView.svg b/Crow.Coding/icons/toolbox/Crow.TabView.svg new file mode 100644 index 0000000..942358b --- /dev/null +++ b/Crow.Coding/icons/toolbox/Crow.TabView.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/Crow.Coding/icons/toolbox/Crow.TemplatedContainer.svg b/Crow.Coding/icons/toolbox/Crow.TemplatedContainer.svg new file mode 100644 index 0000000..34a0aa2 --- /dev/null +++ b/Crow.Coding/icons/toolbox/Crow.TemplatedContainer.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/Crow.Coding/icons/toolbox/Crow.TemplatedGroup.svg b/Crow.Coding/icons/toolbox/Crow.TemplatedGroup.svg new file mode 100644 index 0000000..14ea6f3 --- /dev/null +++ b/Crow.Coding/icons/toolbox/Crow.TemplatedGroup.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/Crow.Coding/icons/toolbox/Crow.TextBox.svg b/Crow.Coding/icons/toolbox/Crow.TextBox.svg new file mode 100644 index 0000000..c1fc2bb --- /dev/null +++ b/Crow.Coding/icons/toolbox/Crow.TextBox.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Crow.Coding/icons/toolbox/Crow.TreeView.svg b/Crow.Coding/icons/toolbox/Crow.TreeView.svg new file mode 100644 index 0000000..b863291 --- /dev/null +++ b/Crow.Coding/icons/toolbox/Crow.TreeView.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/Crow.Coding/icons/toolbox/Crow.VerticalStack.svg b/Crow.Coding/icons/toolbox/Crow.VerticalStack.svg new file mode 100644 index 0000000..c3c3ec9 --- /dev/null +++ b/Crow.Coding/icons/toolbox/Crow.VerticalStack.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/Crow.Coding/icons/toolbox/Crow.Window.svg b/Crow.Coding/icons/toolbox/Crow.Window.svg new file mode 100644 index 0000000..74b0a24 --- /dev/null +++ b/Crow.Coding/icons/toolbox/Crow.Window.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/Crow.Coding/icons/toolbox/Crow.Wrapper.svg b/Crow.Coding/icons/toolbox/Crow.Wrapper.svg new file mode 100644 index 0000000..9e69e41 --- /dev/null +++ b/Crow.Coding/icons/toolbox/Crow.Wrapper.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/Crow.Coding/icons/toolbox/bar-chart.svg b/Crow.Coding/icons/toolbox/bar-chart.svg new file mode 100644 index 0000000..ff86c96 --- /dev/null +++ b/Crow.Coding/icons/toolbox/bar-chart.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/Crow.Coding/icons/toolbox/bar-menu.svg b/Crow.Coding/icons/toolbox/bar-menu.svg new file mode 100644 index 0000000..87ec061 --- /dev/null +++ b/Crow.Coding/icons/toolbox/bar-menu.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/Crow.Coding/icons/toolbox/bullets.svg b/Crow.Coding/icons/toolbox/bullets.svg new file mode 100644 index 0000000..81fb1f0 --- /dev/null +++ b/Crow.Coding/icons/toolbox/bullets.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/Crow.Coding/icons/toolbox/calendar.svg b/Crow.Coding/icons/toolbox/calendar.svg new file mode 100644 index 0000000..9ceaa1e --- /dev/null +++ b/Crow.Coding/icons/toolbox/calendar.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/Crow.Coding/icons/toolbox/check-square-1.svg b/Crow.Coding/icons/toolbox/check-square-1.svg new file mode 100644 index 0000000..e198007 --- /dev/null +++ b/Crow.Coding/icons/toolbox/check-square-1.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Crow.Coding/icons/toolbox/database.svg b/Crow.Coding/icons/toolbox/database.svg new file mode 100644 index 0000000..65a8f06 --- /dev/null +++ b/Crow.Coding/icons/toolbox/database.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/Crow.Coding/icons/toolbox/ellipsis.svg b/Crow.Coding/icons/toolbox/ellipsis.svg new file mode 100644 index 0000000..cff94cc --- /dev/null +++ b/Crow.Coding/icons/toolbox/ellipsis.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/Crow.Coding/icons/toolbox/file-code.svg b/Crow.Coding/icons/toolbox/file-code.svg new file mode 100644 index 0000000..a2fd2d1 --- /dev/null +++ b/Crow.Coding/icons/toolbox/file-code.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/Crow.Coding/icons/toolbox/grab.svg b/Crow.Coding/icons/toolbox/grab.svg new file mode 100644 index 0000000..25bc571 --- /dev/null +++ b/Crow.Coding/icons/toolbox/grab.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/Crow.Coding/icons/toolbox/hash.svg b/Crow.Coding/icons/toolbox/hash.svg new file mode 100644 index 0000000..82196fb --- /dev/null +++ b/Crow.Coding/icons/toolbox/hash.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/Crow.Coding/icons/toolbox/line-list.svg b/Crow.Coding/icons/toolbox/line-list.svg new file mode 100644 index 0000000..ec15f7b --- /dev/null +++ b/Crow.Coding/icons/toolbox/line-list.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/Crow.Coding/icons/toolbox/list.svg b/Crow.Coding/icons/toolbox/list.svg new file mode 100644 index 0000000..9aad88f --- /dev/null +++ b/Crow.Coding/icons/toolbox/list.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/Crow.Coding/icons/toolbox/modal-list.svg b/Crow.Coding/icons/toolbox/modal-list.svg new file mode 100644 index 0000000..f1d8f70 --- /dev/null +++ b/Crow.Coding/icons/toolbox/modal-list.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/Crow.Coding/icons/toolbox/options.svg b/Crow.Coding/icons/toolbox/options.svg new file mode 100644 index 0000000..a56f6be --- /dev/null +++ b/Crow.Coding/icons/toolbox/options.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/Crow.Coding/icons/toolbox/package.svg b/Crow.Coding/icons/toolbox/package.svg new file mode 100644 index 0000000..07f8b37 --- /dev/null +++ b/Crow.Coding/icons/toolbox/package.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/Crow.Coding/icons/toolbox/padding.svg b/Crow.Coding/icons/toolbox/padding.svg new file mode 100644 index 0000000..d93b246 --- /dev/null +++ b/Crow.Coding/icons/toolbox/padding.svg @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Crow.Coding/icons/toolbox/picture-file.svg b/Crow.Coding/icons/toolbox/picture-file.svg new file mode 100644 index 0000000..c45a6ad --- /dev/null +++ b/Crow.Coding/icons/toolbox/picture-file.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/Crow.Coding/icons/toolbox/pointer.svg b/Crow.Coding/icons/toolbox/pointer.svg new file mode 100644 index 0000000..605c0e2 --- /dev/null +++ b/Crow.Coding/icons/toolbox/pointer.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/Crow.Coding/icons/toolbox/puzzle-piece.svg b/Crow.Coding/icons/toolbox/puzzle-piece.svg new file mode 100644 index 0000000..b09c47e --- /dev/null +++ b/Crow.Coding/icons/toolbox/puzzle-piece.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/Crow.Coding/icons/toolbox/refresh-file.svg b/Crow.Coding/icons/toolbox/refresh-file.svg new file mode 100644 index 0000000..248e420 --- /dev/null +++ b/Crow.Coding/icons/toolbox/refresh-file.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/Crow.Coding/icons/toolbox/sliders.svg b/Crow.Coding/icons/toolbox/sliders.svg new file mode 100644 index 0000000..81f72d1 --- /dev/null +++ b/Crow.Coding/icons/toolbox/sliders.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/Crow.Coding/icons/toolbox/split-browser-1.svg b/Crow.Coding/icons/toolbox/split-browser-1.svg new file mode 100644 index 0000000..4dfd93a --- /dev/null +++ b/Crow.Coding/icons/toolbox/split-browser-1.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/Crow.Coding/icons/toolbox/table.svg b/Crow.Coding/icons/toolbox/table.svg new file mode 100644 index 0000000..0b42122 --- /dev/null +++ b/Crow.Coding/icons/toolbox/table.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/Crow.Coding/icons/toolbox/tasks.svg b/Crow.Coding/icons/toolbox/tasks.svg new file mode 100644 index 0000000..8793c88 --- /dev/null +++ b/Crow.Coding/icons/toolbox/tasks.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/Crow.Coding/icons/toolbox/warning.svg b/Crow.Coding/icons/toolbox/warning.svg new file mode 100644 index 0000000..f5a2573 --- /dev/null +++ b/Crow.Coding/icons/toolbox/warning.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/Crow.Coding/icons/tools.svg b/Crow.Coding/icons/tools.svg new file mode 100644 index 0000000..5ad8a8d --- /dev/null +++ b/Crow.Coding/icons/tools.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/Crow.Coding/icons/trash.svg b/Crow.Coding/icons/trash.svg new file mode 100644 index 0000000..e73a5e3 --- /dev/null +++ b/Crow.Coding/icons/trash.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Crow.Coding/icons/undo.svg b/Crow.Coding/icons/undo.svg new file mode 100644 index 0000000..f78f134 --- /dev/null +++ b/Crow.Coding/icons/undo.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/Crow.Coding/icons/zoom-in.svg b/Crow.Coding/icons/zoom-in.svg new file mode 100644 index 0000000..540a93b --- /dev/null +++ b/Crow.Coding/icons/zoom-in.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Crow.Coding/icons/zoom-out.svg b/Crow.Coding/icons/zoom-out.svg new file mode 100644 index 0000000..6bd256f --- /dev/null +++ b/Crow.Coding/icons/zoom-out.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Crow.Coding/images/save.svg b/Crow.Coding/images/save.svg new file mode 100644 index 0000000..7bdc551 --- /dev/null +++ b/Crow.Coding/images/save.svg @@ -0,0 +1,3421 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/CodeBuffer.cs b/Crow.Coding/src/CodeBuffer/CodeBuffer.cs similarity index 66% rename from src/CodeBuffer.cs rename to Crow.Coding/src/CodeBuffer/CodeBuffer.cs index 399d10a..48e00b6 100644 --- a/src/CodeBuffer.cs +++ b/Crow.Coding/src/CodeBuffer/CodeBuffer.cs @@ -23,15 +23,17 @@ using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; using System.Diagnostics; +using System.Threading; namespace Crow.Coding { /// - /// Code buffer, lines are arranged in a List, new line chars are removed during string.split on '\n...', + /// Code buffer, lines are arranged in a List'string', new line chars are removed during string.split on '\n...', /// public class CodeBuffer { - public object EditMutex = new object(); + public ReaderWriterLockSlim editMutex = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion); + //those events are handled in SourceEditor to help keeping sync between textbuffer,parser and editor. //modified lines are marked for reparse #region Events @@ -44,12 +46,6 @@ namespace Crow.Coding public event EventHandler PositionChanged; #endregion - #region CTOR - public CodeBuffer () { - - } - #endregion - string lineBreak = Interface.LineBreak; List lines = new List(); public int longestLineIdx = 0; @@ -67,86 +63,103 @@ namespace Crow.Coding public CodeLine this[int i] { - get { return lines[i]; } + get { return i < LineCount ? lines[i] : null; } set { if (lines [i] == value) return; - lock (EditMutex) { - lines [i] = value; - LineUpadateEvent.Raise (this, new CodeBufferEventArgs (i)); - } + editMutex.EnterWriteLock (); + lines [i] = value; + editMutex.ExitWriteLock (); + LineUpadateEvent.Raise (this, new CodeBufferEventArgs (i)); } } public void RemoveAt(int i){ - lock (EditMutex) { - lines.RemoveAt (i); - LineRemoveEvent.Raise (this, new CodeBufferEventArgs (i)); - } + editMutex.EnterWriteLock (); + lines.RemoveAt (i); + editMutex.ExitWriteLock (); + LineRemoveEvent.Raise (this, new CodeBufferEventArgs (i)); } public void Insert(int i, string item){ - lock (EditMutex) { - lines.Insert (i, item); - LineAdditionEvent.Raise (this, new CodeBufferEventArgs (i)); - } + editMutex.EnterWriteLock (); + lines.Insert (i, item); + editMutex.ExitWriteLock (); + LineAdditionEvent.Raise (this, new CodeBufferEventArgs (i)); } public void Add(CodeLine item){ - lock (EditMutex) { - lines.Add (item); - LineAdditionEvent.Raise (this, new CodeBufferEventArgs (lines.Count - 1)); - } + editMutex.EnterWriteLock (); + lines.Add (item); + editMutex.ExitWriteLock (); + LineAdditionEvent.Raise (this, new CodeBufferEventArgs (lines.Count - 1)); } public void AddRange (string[] items){ int start = lines.Count; - lock (EditMutex) { - for (int i = 0; i < items.Length; i++) - lines.Add (items [i]); - LineAdditionEvent.Raise (this, new CodeBufferEventArgs (start, items.Length)); - } + editMutex.EnterWriteLock (); + for (int i = 0; i < items.Length; i++) + lines.Add (items [i]); + editMutex.ExitWriteLock (); + LineAdditionEvent.Raise (this, new CodeBufferEventArgs (start, items.Length)); } public void AddRange (CodeLine[] items){ int start = lines.Count; - lock (EditMutex) { - lines.AddRange (items); - LineAdditionEvent.Raise (this, new CodeBufferEventArgs (start, items.Length)); - } + editMutex.EnterWriteLock (); + lines.AddRange (items); + editMutex.ExitWriteLock (); + LineAdditionEvent.Raise (this, new CodeBufferEventArgs (start, items.Length)); } public void Clear () { - lock (EditMutex) { - longestLineCharCount = 0; - lines.Clear (); - BufferCleared.Raise (this, null); - } + editMutex.EnterWriteLock (); + longestLineCharCount = 0; + lines.Clear (); + editMutex.ExitWriteLock (); + BufferCleared.Raise (this, null); } public void UpdateLine(int i, string newContent){ - lock (EditMutex) { - this [i].Content = newContent; - LineUpadateEvent.Raise (this, new CodeBufferEventArgs (i)); - } + editMutex.EnterWriteLock (); + this [i].Content = newContent; + editMutex.ExitWriteLock (); + LineUpadateEvent.Raise (this, new CodeBufferEventArgs (i)); } public void AppenedLine(int i, string newContent){ - lock (EditMutex) { - this [i].Content += newContent; - LineUpadateEvent.Raise (this, new CodeBufferEventArgs (i)); + editMutex.EnterWriteLock (); + this [i].Content += newContent; + editMutex.ExitWriteLock (); + LineUpadateEvent.Raise (this, new CodeBufferEventArgs (i)); + } + public void RemoveLeadingTab (int l) { + if (this [l] [0] == '\t') { + UpdateLine (l, this [l].Content.Substring (1)); + return; + } + int i = 0; + while (i < Interface.TAB_SIZE) { + if (this [l] [i] != ' ') + break; + i++; } + if (i > 0) + UpdateLine (l, this [l].Content.Substring (i)); } public void ToogleFolding (int line) { if (!this [line].IsFoldable) return; - lock (EditMutex) { - this [line].IsFolded = !this [line].IsFolded; - FoldingEvent.Raise (this, new CodeBufferEventArgs (line)); - } + editMutex.EnterWriteLock (); + this [line].IsFolded = !this [line].IsFolded; + editMutex.ExitWriteLock (); + FoldingEvent.Raise (this, new CodeBufferEventArgs (line)); } - public void Load(string rawSource) { + public void Load(string rawSource, string lineBrkRegex = @"\r\n|\r|\n|\\\n") { this.Clear(); - if (string.IsNullOrEmpty (rawSource)) return; - AddRange (Regex.Split (rawSource, "\r\n|\r|\n|\\\\n")); + AddRange (Regex.Split (rawSource, lineBrkRegex)); lineBreak = detectLineBreakKind (rawSource); + + /*for (int i = 0; i < LineCount; i++) { + ToogleFolding (i); + }*/ } /// @@ -154,13 +167,15 @@ namespace Crow.Coding /// public void FindLongestVisualLine(){ longestLineCharCount = 0; + editMutex.EnterReadLock (); for (int i = 0; i < this.LineCount; i++) { if (lines[i].PrintableLength > longestLineCharCount) { longestLineCharCount = lines[i].PrintableLength; longestLineIdx = i; } } - Debug.WriteLine ("Longest line: {0}->{1}", longestLineIdx, longestLineCharCount); + editMutex.ExitReadLock (); + //Debug.WriteLine ("Longest line: {0}->{1}", longestLineIdx, longestLineCharCount); } /// line break could be '\r' or '\n' or '\r\n' static string detectLineBreakKind(string buffer){ @@ -194,9 +209,11 @@ namespace Crow.Coding if (lines.Count == 0) return ""; string tmp = ""; + editMutex.EnterReadLock (); for (int i = 0; i < lines.Count -1; i++) tmp += lines [i].Content + this.lineBreak; tmp += lines [lines.Count - 1].Content; + editMutex.ExitReadLock (); return tmp; } } @@ -207,12 +224,19 @@ namespace Crow.Coding public int UnfoldedLines { get { int i = 0, vl = 0; + editMutex.EnterReadLock (); while (i < LineCount) { - if (this [i].IsFolded) + if (this [i].IsFolded) { i = GetEndNodeIndex (i); + if (i < 0) { + Console.WriteLine ("error folding"); + break; + } + } i++; vl++; } + editMutex.ExitReadLock (); //Debug.WriteLine ("unfolded lines: " + vl); return vl; } @@ -226,7 +250,7 @@ namespace Crow.Coding int buffCol = 0; while (i < visualPos.X) { if (this [visualPos.Y] [buffCol] == '\t') - i += Interface.TabSize; + i += Interface.TAB_SIZE; else i++; buffCol++; @@ -237,6 +261,28 @@ namespace Crow.Coding public int GetEndNodeIndex (int line) { return IndexOf (this [line].SyntacticNode.EndLine); } + + int ConverteTabulatedPosOfCurLine (int column) { + int tmp = 0; + int i = 0; + while (i < lines [_currentLine].Content.Length){ + if (lines [_currentLine].Content [i] == '\t') + tmp += 4; + else + tmp++; + if (tmp > column) + break; + i++; + } + return i; + } + + public int CurrentTabulatedColumn { + get { + return lines [_currentLine].Content.Substring (0, _currentCol). + Replace ("\t", new String (' ', Interface.TAB_SIZE)).Length; + } + } /// /// Gets visual position computed from actual buffer position /// @@ -263,6 +309,15 @@ namespace Crow.Coding selEndPos = CurrentPosition; SelectionChanged.Raise (this, null); } + public void SetSelectionOnFullLines () { + if (!SelectionInProgress) + return; + Point s = new Point (0, SelectionStart.Y); + Point e = new Point (this [SelectionEnd.Y].Length, SelectionEnd.Y); + selStartPos = s; + selEndPos = e; + SelectionChanged.Raise (this, null); + } /// /// Set selection in buffer to -1, empty selection /// @@ -303,6 +358,7 @@ namespace Crow.Coding } public bool SelectionIsEmpty { get { return selEndPos == selStartPos; } } + int requestedColumn = -1; /// /// Current column in buffer coordinate, tabulation = 1 char /// @@ -311,13 +367,20 @@ namespace Crow.Coding set { if (value == _currentCol) return; + + editMutex.EnterReadLock (); + if (value < 0) _currentCol = 0; - else if (value > lines [_currentLine].Length) + else if (value > lines [_currentLine].Length) _currentCol = lines [_currentLine].Length; else _currentCol = value; + requestedColumn = CurrentTabulatedColumn; + + editMutex.ExitReadLock (); + PositionChanged.Raise (this, null); } } @@ -329,16 +392,29 @@ namespace Crow.Coding set { if (value == _currentLine) return; - if (value >= lines.Count) + + editMutex.EnterReadLock (); + + if (LineCount == 0) + _currentLine = 0; + else if (value >= lines.Count) _currentLine = lines.Count-1; else if (value < 0) _currentLine = 0; else _currentLine = value; - - if (_currentCol > lines [_currentLine].Length) +// if (_currentCol < 0) +// requestedColumn = tabu _currentCol; + int tabulatedRequestedCol = ConverteTabulatedPosOfCurLine(requestedColumn); + if (requestedColumn > lines [_currentLine].PrintableLength) _currentCol = lines [_currentLine].Length; - Debug.WriteLine ("buff cur line: " + _currentLine); + else + //_currentCol = requestedColumn; + _currentCol = tabulatedRequestedCol; + //Debug.WriteLine ("buff cur line: " + _currentLine); + + editMutex.ExitReadLock(); + PositionChanged.Raise (this, null); } } @@ -385,37 +461,40 @@ namespace Crow.Coding } public void DeleteChar() { - lock (EditMutex) { - if (SelectionIsEmpty) { - if (CurrentColumn == 0) { - if (CurrentLine == 0) - return; - CurrentLine--; - CurrentColumn = this [CurrentLine].Length; - AppenedLine (CurrentLine, this [CurrentLine + 1].Content); - RemoveAt (CurrentLine + 1); + editMutex.EnterWriteLock (); + if (SelectionIsEmpty) { + if (CurrentColumn == 0) { + if (CurrentLine == 0) { + editMutex.ExitWriteLock (); return; } - CurrentColumn--; - UpdateLine (CurrentLine, this [CurrentLine].Content.Remove (CurrentColumn, 1)); - } else { - int linesToRemove = SelectionEnd.Y - SelectionStart.Y + 1; - int l = SelectionStart.Y; - - if (linesToRemove > 0) { - UpdateLine (l, this [l].Content.Remove (SelectionStart.X, this [l].Length - SelectionStart.X) + - this [SelectionEnd.Y].Content.Substring (SelectionEnd.X, this [SelectionEnd.Y].Length - SelectionEnd.X)); - l++; - for (int c = 0; c < linesToRemove - 1; c++) - RemoveAt (l); - CurrentLine = SelectionStart.Y; - CurrentColumn = SelectionStart.X; - } else - UpdateLine (l, this [l].Content.Remove (SelectionStart.X, SelectionEnd.X - SelectionStart.X)); - CurrentColumn = SelectionStart.X; - ResetSelection (); + CurrentLine--; + CurrentColumn = this [CurrentLine].Length; + AppenedLine (CurrentLine, this [CurrentLine + 1].Content); + RemoveAt (CurrentLine + 1); + editMutex.ExitWriteLock (); + return; } + CurrentColumn--; + UpdateLine (CurrentLine, this [CurrentLine].Content.Remove (CurrentColumn, 1)); + } else { + int linesToRemove = SelectionEnd.Y - SelectionStart.Y + 1; + int l = SelectionStart.Y; + + if (linesToRemove > 0) { + UpdateLine (l, this [l].Content.Remove (SelectionStart.X, this [l].Length - SelectionStart.X) + + this [SelectionEnd.Y].Content.Substring (SelectionEnd.X, this [SelectionEnd.Y].Length - SelectionEnd.X)); + l++; + for (int c = 0; c < linesToRemove - 1; c++) + RemoveAt (l); + CurrentLine = SelectionStart.Y; + CurrentColumn = SelectionStart.X; + } else + UpdateLine (l, this [l].Content.Remove (SelectionStart.X, SelectionEnd.X - SelectionStart.X)); + CurrentColumn = SelectionStart.X; + ResetSelection (); } + editMutex.ExitWriteLock (); } /// /// Insert new string at caret position, should be sure no line break is inside. diff --git a/CodeBufferEventArgs.cs b/Crow.Coding/src/CodeBuffer/CodeBufferEventArgs.cs similarity index 100% rename from CodeBufferEventArgs.cs rename to Crow.Coding/src/CodeBuffer/CodeBufferEventArgs.cs diff --git a/src/CodeLine.cs b/Crow.Coding/src/CodeBuffer/CodeLine.cs similarity index 72% rename from src/CodeLine.cs rename to Crow.Coding/src/CodeBuffer/CodeLine.cs index 622584c..70c6be2 100644 --- a/src/CodeLine.cs +++ b/Crow.Coding/src/CodeBuffer/CodeLine.cs @@ -1,6 +1,7 @@ using System; using System.Text; using System.Collections.Generic; +using System.Linq; namespace Crow.Coding { @@ -10,7 +11,7 @@ namespace Crow.Coding public List Tokens; public int EndingState = 0; public Node SyntacticNode; - public ParsingException exception; + public ParserException exception; public CodeLine (string _content){ Content = _content; @@ -31,14 +32,16 @@ namespace Crow.Coding //LineUpadateEvent.Raise (this, new CodeBufferEventArgs (i)); } } - public bool IsFoldable { get { return SyntacticNode != null; } } + public bool IsFoldable { get { return SyntacticNode != null && SyntacticNode.EndLine != SyntacticNode.StartLine + && SyntacticNode.EndLine != null; } } + public int FoldingLevel { get { return IsFoldable ? SyntacticNode.Level : 0; } } public bool IsFolded = false; public bool IsParsed { get { return Tokens != null; } } public string PrintableContent { get { - return string.IsNullOrEmpty (Content) ? "" : Content.Replace ("\t", new String (' ', Interface.TabSize)); + return string.IsNullOrEmpty (Content) ? "" : Content.Replace ("\t", new String (' ', Interface.TAB_SIZE)); } } public int PrintableLength { @@ -51,9 +54,12 @@ namespace Crow.Coding return string.IsNullOrEmpty (Content) ? 0 : Content.Length; } } + public int FirstNonBlankTokIndex { + get { return Tokens == null ? -1 : Tokens.FindIndex (tk=>tk.Type != BufferParser.TokenType.WhiteSpace); } + } - public void SetLineInError (ParsingException ex) { - Tokens = null; + public void SetLineInError (ParserException ex) { + Tokens = null; exception = ex; } diff --git a/src/Node.cs b/Crow.Coding/src/CodeBuffer/Node.cs similarity index 87% rename from src/Node.cs rename to Crow.Coding/src/CodeBuffer/Node.cs index 24818e0..9db5542 100644 --- a/src/Node.cs +++ b/Crow.Coding/src/CodeBuffer/Node.cs @@ -23,6 +23,10 @@ namespace Crow.Coding Children.Add (child); } + public int Level { + get { return Parent == null ? 1 : Parent.Level + 1; } + } + public override string ToString () { return string.Format ("Name:{0}, Type:{1}\n\tparent:{2}", Name, Type, Parent); diff --git a/Crow.Coding/src/CodeBuffer/TextBuffer.cs b/Crow.Coding/src/CodeBuffer/TextBuffer.cs new file mode 100644 index 0000000..e8c8718 --- /dev/null +++ b/Crow.Coding/src/CodeBuffer/TextBuffer.cs @@ -0,0 +1,527 @@ +// +// CodeTextBuffer.cs +// +// Author: +// Jean-Philippe Bruyère +// +// Copyright (c) 2017 jp +// +// This program 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. +// +// This program 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 this program. If not, see . +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.RegularExpressions; +using System.Diagnostics; +using System.Threading; +using System.Text; + +namespace Crow.Text +{ + /// + /// Code buffer, lines are arranged in a List, new line chars are removed during string.split on '\n...', + /// + public class TextBuffer + { + public ReaderWriterLockSlim editMutex = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion); + static Regex slb = new Regex ("\\n");//single char line break used internaly + Regex reghexLineBrk = new Regex(@"\r\n|\r|\n|\\\n");//original text line break regex + + #region Events + public event EventHandler LineUpadateEvent; + public event EventHandler LineRemoveEvent; + public event EventHandler LineAdditionEvent; + public event EventHandler BufferCleared; + public event EventHandler SelectionChanged; + public event EventHandler PositionChanged; + #endregion + + StringBuilder buffer = new StringBuilder(); + string lineBreak = Interface.LineBreak;//detected linebreak kind in original source + List lineLength = new List();//line length table + /// + /// real position in char arrays, tab = 1 char + /// + int _currentLine = 0; + int _currentCol = 0; + + /// + /// Gets the total line count. + /// + public int LineCount { get { return lineLength.Count;}} + + /// + /// get a substring in the buffer + /// + /// a new string + /// absolute index in the buffer + /// length of the substring + public string GetSubString (int idx, int length){ + return buffer.ToString (idx, length); + } + /// + /// Gets length of a line. + /// + /// length of line + /// line nuber + public int GetLineLength (int lineIdx) { + return lineLength [lineIdx]; + } + /// + /// get a single charactere in the buffer + /// + /// a single char + /// absolute index in the buffer + public char GetCharAt (int idx){ + return buffer [idx]; + } + /// + /// return full text with original line breaks + /// + /// a string containing the full text + public string FullText { + get { return buffer.Replace("\n", lineBreak).ToString (); } + set { + Load (value); + } + } + /// + /// Gets the buffer pointer of a line + /// + /// absolute index of the line in the buffer + /// line number + public int GetBufferIndexOfLine (int i) { + int ptr = 0; + editMutex.EnterReadLock (); + for (int j = 0; j < i; j++) { + ptr += lineLength [j]; + } + editMutex.ExitReadLock (); + return ptr; + } + /// + /// Gets the buffer pointer for the current position + /// + /// absolute index in the buffer of current position + public int BufferIndexOfCurrentPosition { + get {return GetBufferIndexOfLine (_currentLine) + _currentCol;} + } + public int this[int i] + { + get { + int ptr = 0; + editMutex.EnterReadLock (); + for (int j = 0; j < i; j++) { + ptr += lineLength [j]; + } + editMutex.ExitReadLock (); + return ptr; + } + } + /// + /// remove line number i + /// + /// index of the line + public void RemoveLine(int i){ + editMutex.EnterWriteLock (); + buffer.Remove (GetBufferIndexOfLine (i), lineLength [i]); + lineLength.RemoveAt (i); + editMutex.ExitWriteLock (); + LineRemoveEvent.Raise (this, new TextBufferEventArgs (i)); + } + /// + /// insert string without linebreaks at position i in buff + /// + /// absolute index in the buffer + /// linebreak free string + public void InsertAt(int i, string str){ + editMutex.EnterWriteLock (); + buffer.Insert (this [i], str); + lineLength.Insert (i, str.Length); + editMutex.ExitWriteLock (); + LineAdditionEvent.Raise (this, new TextBufferEventArgs (i)); + } + public void AddLine(string str){ + editMutex.EnterWriteLock (); + if (lineLength.LastOrDefault() == 0) { + buffer.Append (str); + lineLength [lineLength.Count - 1] = str.Length; + lineLength.Add (0); + } + editMutex.ExitWriteLock (); + LineAdditionEvent.Raise (this, new TextBufferEventArgs (lineLength.Count - 1)); + } + public void AddRange (string[] items){ + int start = lineLength.Count; + editMutex.EnterWriteLock (); + for (int i = 0; i < items.Length; i++) + AddLine (items [i]); + editMutex.ExitWriteLock (); + LineAdditionEvent.Raise (this, new TextBufferEventArgs (start, items.Length)); + } + public void Clear () { + editMutex.EnterWriteLock (); + lineLength.Clear (); + buffer.Clear (); + editMutex.ExitWriteLock (); + BufferCleared.Raise (this, null); + } + public void UpdateLine(int i, string newContent){ + editMutex.EnterWriteLock (); + int ptrL = this [i]; + buffer.Remove (ptrL, lineLength [i]); + buffer.Insert (ptrL, newContent); + lineLength [i] = newContent.Length; + editMutex.ExitWriteLock (); + LineUpadateEvent.Raise (this, new TextBufferEventArgs (i)); + } + public void AppenedLine(int i, string newContent){ + editMutex.EnterWriteLock (); + int ptr = this [i] + lineLength [i]; + if (i < LineCount - 1) + ptr--; + buffer.Insert(ptr, newContent); + lineLength [i] += newContent.Length; + editMutex.ExitWriteLock (); + LineUpadateEvent.Raise (this, new TextBufferEventArgs (i)); + } + /// + /// Insert new string at caret position, should be sure no line break is inside. + /// + /// String. + public void InsertAt(string str) + { + if (!SelectionIsEmpty) + this.Delete (); + + editMutex.EnterWriteLock (); + + string tmp = reghexLineBrk.Replace (str, "\n");//use single char line break in buffer + int buffPtr = this [CurrentLine] + CurrentColumn; + buffer.Insert (buffPtr, tmp); + + int lPtr = CurrentLine, strPtr = 0; + int remainingLength = lineLength [lPtr] - CurrentColumn; + lineLength [lPtr] = CurrentColumn; + foreach (Match match in slb.Matches(tmp)) + { + lineLength [lPtr] += match.Index + 1 - strPtr; + lPtr++; + lineLength.Insert (lPtr, 0); + strPtr = match.Index + 1; + //CurrentLine++; + } + remainingLength += tmp.Length - strPtr; + lineLength [lPtr] += remainingLength; + + CurrentLine = lPtr; + if (strPtr == 0) + CurrentColumn += tmp.Length; + else + CurrentColumn = tmp.Length - strPtr; + + editMutex.ExitWriteLock (); + if (strPtr>0) + LineAdditionEvent.Raise (this, null); + else + LineUpadateEvent.Raise (this, null); + } + /// + /// Insert a line break. + /// + public void InsertLineBreak() + { + editMutex.EnterWriteLock (); + buffer.Insert (this [CurrentLine] + CurrentColumn, '\n'); + int lgdiff = lineLength [CurrentLine] - CurrentColumn; + lineLength.Insert (CurrentLine + 1, lineLength [CurrentLine] - CurrentColumn); + lineLength [CurrentLine] = CurrentColumn + 1; + editMutex.ExitWriteLock (); + LineAdditionEvent.Raise (this, null); + CurrentColumn = 0; + CurrentLine++; + } + public void Delete() + { + editMutex.EnterWriteLock (); + if (SelectionIsEmpty) { + if (CurrentColumn == 0) { + if (CurrentLine == 0) { + editMutex.ExitWriteLock (); + return; + } + + buffer.Remove (this [CurrentLine] - 1, 1); + + int col = lineLength [CurrentLine - 1] - 1; + lineLength [CurrentLine - 1] += lineLength [CurrentLine] - 1; + lineLength.RemoveAt (CurrentLine); + + CurrentLine--; + CurrentColumn = col; + + editMutex.ExitWriteLock (); + LineRemoveEvent.Raise (this, null); + return; + } + CurrentColumn--; + buffer.Remove (this [CurrentLine] + CurrentColumn, 1); + lineLength [CurrentLine]--; + } else { + int linesToRemove = SelectionEnd.Y - SelectionStart.Y; + int ptr = this [SelectionStart.Y] + SelectionStart.X; + int length = lineLength [SelectionStart.Y] - SelectionStart.X; + int l = 1; + while (l <= linesToRemove ) { + length += lineLength [SelectionStart.Y + l]; + l++; + } + length -= lineLength [SelectionEnd.Y] - SelectionEnd.X; + buffer.Remove (ptr, length); + lineLength [SelectionStart.Y] = SelectionStart.X + lineLength [SelectionEnd.Y] - SelectionEnd.X; + lineLength.RemoveRange (SelectionStart.Y + 1, linesToRemove); + + CurrentLine = SelectionStart.Y; + CurrentColumn = SelectionStart.X; + ResetSelection (); + + if (linesToRemove > 0) + LineRemoveEvent.Raise (this, null); + else + LineUpadateEvent.Raise (this, null); + } + editMutex.ExitWriteLock (); + } + public void Load(string rawSource) { + this.Clear(); + + if (string.IsNullOrEmpty (rawSource)) + return; + + lineBreak = reghexLineBrk.Match (rawSource).Value;//store original line break + string tmp = reghexLineBrk.Replace (rawSource, "\n");//use single char line break in buffer + int ptr = 0; + foreach (Match match in slb.Matches(tmp)) + { + int l = match.Index + 1; + int lg = l - ptr; + lineLength.Add (lg); + ptr = l; + } + lineLength.Add (0); + + buffer = new StringBuilder (tmp); + } + +// public int CurrentTabulatedColumn { +// get { +//// return lines [_currentLine].Content.Substring (0, _currentCol). +//// Replace ("\t", new String (' ', Interface.TabSize)).Length; +// } +// } + + #region moving cursor an selection + Point selStartPos = -1; //selection start (row,column) + Point selEndPos = -1; //selection end (row,column) + + public bool SelectionInProgress { get { return selStartPos >= 0; }} + public void SetSelStartPos () { + selStartPos = selEndPos = CurrentPosition; + SelectionChanged.Raise (this, null); + } + public void SetSelEndPos () { + selEndPos = CurrentPosition; + SelectionChanged.Raise (this, null); + } + /// + /// Set selection in buffer to -1, empty selection + /// + public void ResetSelection () { + selStartPos = selEndPos = -1; + SelectionChanged.Raise (this, null); + } + /// + /// ordered selection start and end positions in char units + /// + public Point SelectionStart { + get { return selEndPos < 0 || selStartPos.Y < selEndPos.Y ? selStartPos : + selStartPos.Y > selEndPos.Y ? selEndPos : + selStartPos.X < selEndPos.X ? selStartPos : selEndPos; } + } + public Point SelectionEnd { + get { return selEndPos < 0 || selStartPos.Y > selEndPos.Y ? selStartPos : + selStartPos.Y < selEndPos.Y ? selEndPos : + selStartPos.X > selEndPos.X ? selStartPos : selEndPos; } + } + public bool SelectionIsEmpty + { get { return selEndPos == selStartPos; } } + /// + /// Current column in buffer coordinate, tabulation = 1 char + /// + public int CurrentColumn{ + get { return _currentCol; } + set { + if (value == _currentCol) + return; + + editMutex.EnterWriteLock (); + + if (value < 0) + _currentCol = 0; + else if (value >= lineLength [_currentLine]) { + if (_currentLine < LineCount -1 && value > lineLength [_currentLine] - 1) + _currentCol = lineLength [_currentLine] - 1; + else + _currentCol = lineLength [_currentLine]; + }else + _currentCol = value; + + editMutex.ExitWriteLock (); + + PositionChanged.Raise (this, null); + } + } + /// + /// Current row in buffer coordinate, tabulation = 1 char + /// + public int CurrentLine{ + get { return _currentLine; } + set { + if (value == _currentLine) + return; + + editMutex.EnterWriteLock (); + + if (value >= lineLength.Count) + _currentLine = lineLength.Count-1; + else if (value < 0) + _currentLine = 0; + else + _currentLine = value; + + int c = _currentCol; + _currentCol = 0; + CurrentColumn = c; + + editMutex.ExitWriteLock(); + + PositionChanged.Raise (this, null); + } + } + /// + /// Current position in buffer coordinate, tabulation = 1 char + /// + public Point CurrentPosition { + get { return new Point(CurrentColumn, CurrentLine); } + } + /// + /// get char at current position in buffer + /// + protected Char CurrentChar { get { return buffer[this [CurrentLine]]; } } + public string SelectedText { + get { + if (SelectionIsEmpty) + return ""; + Point selStart = SelectionStart; + Point selEnd = SelectionEnd; + + int ptr = this [selStart.Y] + selStart.X; + int length = lineLength[selStart.Y] - selStart.X; + for (int i = selStart.Y+1; i <= selEnd.Y; i++) + length += lineLength [i]; + length -= lineLength[selEnd.Y] - selEnd.X; + + return buffer.ToString (ptr, length); + } + } + + public void GotoWordStart(){ + if (_currentCol == 0) + MoveLeft (); + if (_currentCol == 0) + return; + int ptrStart = BufferIndexOfCurrentPosition; + int ptr = ptrStart; + char c; + //skip white spaces + do { + ptr--; + c = this.GetCharAt (ptr); + } while (!char.IsLetterOrDigit (c) && c != '\n' && ptr > 1); + + do { + ptr--; + c = this.GetCharAt (ptr); + } while (char.IsLetterOrDigit (c) && c != '\n' && ptr > 1); + + if (ptr == 0) + CurrentColumn = 0; + else + CurrentColumn -= ptrStart - ptr - 1; + } + public void GotoWordEnd(){ + int limx = GetLineLength (_currentLine); + if (_currentLine < lineLength.Count - 1) + limx--; + + if (_currentCol == limx) { + MoveRight (); + limx = GetLineLength (_currentLine); + if (_currentLine < lineLength.Count - 1) + limx--; + } + + int ptrLine = GetBufferIndexOfLine(_currentLine); + int ptrCol = _currentCol; + + char c; + //skip white spaces + do { + c = GetCharAt (ptrLine+ptrCol); + ptrCol++; + } while (!char.IsLetterOrDigit (c) && ptrCol < limx); + + do { + c = GetCharAt (ptrLine + ptrCol); + ptrCol++; + } while (char.IsLetterOrDigit (c) && ptrCol < limx); + CurrentColumn = ptrCol - 1; + } + /// + /// Moves cursor one char to the left, move up if cursor reaches start of line + /// + public void MoveLeft(){ + if (CurrentColumn == 0) { + CurrentLine--; + CurrentColumn = int.MaxValue; + } else + CurrentColumn--; + } + /// + /// Moves cursor one char to the right, move down if cursor reaches end of line + /// + public void MoveRight(){ + if (_currentLine < LineCount -1){ + if (CurrentColumn >= lineLength [CurrentLine] - 1) { + CurrentColumn = 0; + CurrentLine++; + return; + } + } + CurrentColumn++; + } + + #endregion + } +} + diff --git a/Crow.Coding/src/CodeBuffer/TextBufferEventArgs.cs b/Crow.Coding/src/CodeBuffer/TextBufferEventArgs.cs new file mode 100644 index 0000000..3b67bb1 --- /dev/null +++ b/Crow.Coding/src/CodeBuffer/TextBufferEventArgs.cs @@ -0,0 +1,20 @@ +using System; + +namespace Crow.Text +{ + public class TextBufferEventArgs : EventArgs { + public int LineStart; + public int LineCount; + + public TextBufferEventArgs(int lineNumber) { + LineStart = lineNumber; + LineCount = 1; + } + public TextBufferEventArgs(int lineStart, int lineCount) { + LineStart = lineStart; + LineCount = lineCount; + } + } + +} + diff --git a/Crow.Coding/src/CodeBuffer/TextEditor.cs b/Crow.Coding/src/CodeBuffer/TextEditor.cs new file mode 100644 index 0000000..7006798 --- /dev/null +++ b/Crow.Coding/src/CodeBuffer/TextEditor.cs @@ -0,0 +1,697 @@ +// +// ScrollingTextBox.cs +// +// Author: +// Jean-Philippe Bruyère +// +// Copyright (c) 2013-2017 Jean-Philippe Bruyère +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.ComponentModel; +using Crow.Cairo; +using Glfw; + +namespace Crow.Text +{ + /// + /// Scrolling text box optimized for monospace fonts, for coding + /// + public class TextEditor : ScrollingObject { + #region CTOR + public TextEditor (): base() + { + buffer = new TextBuffer (); + buffer.LineUpadateEvent += Buffer_LineUpadateEvent; + buffer.LineAdditionEvent += Buffer_LineAdditionEvent;; + buffer.LineRemoveEvent += Buffer_LineRemoveEvent; + buffer.BufferCleared += Buffer_BufferCleared; + buffer.SelectionChanged += Buffer_SelectionChanged; + buffer.PositionChanged += Buffer_PositionChanged; + //buffer.Add (""); + } + #endregion + + string oldSource = ""; + volatile bool isDirty = false; + + #region private and protected fields + int visibleLines = 1; + int visibleColumns = 1; + + TextBuffer buffer; + + Color selBackground; + Color selForeground; + int selStartCol; + int selEndCol; + + protected Rectangle rText; + protected FontExtents fe; + protected TextExtents te; + + Point mouseLocalPos; + bool doubleClicked = false; + #endregion + + /// + /// Updates visible line in widget, adapt max scroll y and updatePrintedLines + /// + void updateVisibleLines(){ + visibleLines = (int)Math.Floor ((double)ClientRectangle.Height / (fe.Ascent+fe.Descent)); + NotifyValueChanged ("VisibleLines", visibleLines); + updateMaxScrollY (); + RegisterForGraphicUpdate (); +// System.Diagnostics.Debug.WriteLine ("update visible lines: " + visibleLines); +// System.Diagnostics.Debug.WriteLine ("update MaxScrollY: " + MaxScrollY); + } + void updateVisibleColumns(){ + visibleColumns = (int)Math.Floor ((double)(ClientRectangle.Width)/ fe.MaxXAdvance); + NotifyValueChanged ("VisibleColumns", visibleColumns); + RegisterForGraphicUpdate (); +// System.Diagnostics.Debug.WriteLine ("update visible columns: {0} leftMargin:{1}",visibleColumns, leftMargin); +// System.Diagnostics.Debug.WriteLine ("update MaxScrollX: " + MaxScrollX); + } + void updateMaxScrollX (int longestTabulatedLineLength) { + MaxScrollX = Math.Max (0, longestTabulatedLineLength - visibleColumns); + if (longestTabulatedLineLength > 0) + NotifyValueChanged ("ChildWidthRatio", Slot.Width * visibleColumns / longestTabulatedLineLength); + } + void updateMaxScrollY () { + int lc = buffer.LineCount; + MaxScrollY = Math.Max (0, lc - visibleLines); + if (lc > 0) + NotifyValueChanged ("ChildHeightRatio", Slot.Height * visibleLines / lc); + + } + + + + #region Editor overrides + /*protected override void updateEditorFromProjFile () + { + buffer.editMutex.EnterWriteLock (); + loadSource (); + buffer.editMutex.ExitWriteLock (); + + isDirty = false; + oldSource = projFile.Source; + projFile.RegisteredEditors [this] = true; + } + protected override void updateProjFileFromEditor () + { + buffer.editMutex.EnterWriteLock (); + string newsrc = buffer.FullText; + buffer.editMutex.ExitWriteLock (); + projFile.UpdateSource (this, newsrc); + } + protected override bool EditorIsDirty { + get { return isDirty; } + set { isDirty = value; } + } + protected override bool IsReady { + get { return projFile != null && buffer != null; } + }*/ + #endregion + + #region Buffer events handlers + void Buffer_BufferCleared (object sender, EventArgs e) + { + //editorMutex.EnterWriteLock (); + + MaxScrollX = MaxScrollY = 0; + RegisterForGraphicUpdate (); + notifyPositionChanged (); + isDirty = true; + + //editorMutex.ExitWriteLock (); + } + void Buffer_LineAdditionEvent (object sender, TextBufferEventArgs e) + { + updateMaxScrollY (); + RegisterForGraphicUpdate (); + isDirty = true; + } + void Buffer_LineRemoveEvent (object sender, TextBufferEventArgs e) + { + updateMaxScrollY (); + RegisterForGraphicUpdate (); + notifyPositionChanged (); + isDirty = true; + } + void Buffer_LineUpadateEvent (object sender, TextBufferEventArgs e) + { + RegisterForGraphicUpdate (); + notifyPositionChanged (); + isDirty = true; + } + void Buffer_PositionChanged (object sender, EventArgs e) + { + int cc = getTabulatedColumn (buffer.CurrentPosition); + + if (cc > visibleColumns + ScrollX) { + ScrollX = cc - visibleColumns; + } else if (cc < ScrollX) + ScrollX = cc; + + if (buffer.CurrentLine >= visibleLines + ScrollY - 1) + ScrollY = buffer.CurrentLine - visibleLines + 1; + else if (buffer.CurrentLine < ScrollY) + ScrollY = buffer.CurrentLine; + + RegisterForGraphicUpdate (); + notifyPositionChanged (); + } + + void Buffer_SelectionChanged (object sender, EventArgs e) + { + RegisterForGraphicUpdate (); + } + #endregion + + void notifyPositionChanged (){ + try { + NotifyValueChanged ("CurrentLine", buffer.CurrentLine+1); + NotifyValueChanged ("CurrentColumn", buffer.CurrentColumn+1); + } catch (Exception ex) { + Console.WriteLine (ex.ToString ()); + } + } + + #region Public Crow Properties + public int CurrentLine{ + get { return buffer == null ? 0 : buffer.CurrentLine+1; } + set { + try { + int l = value - 1; + if (l == buffer.CurrentLine) + return; + buffer.CurrentLine = l; + } catch (Exception ex) { + Console.WriteLine ("Error cur column: " + ex.ToString ()); + } + } + } + public int CurrentColumn{ + get { return buffer == null ? 0 : buffer.CurrentColumn+1; } + set { + try { + if (value - 1 == buffer.CurrentColumn) + return; + buffer.CurrentColumn = value - 1; + } catch (Exception ex) { + Console.WriteLine ("Error cur column: " + ex.ToString ()); + } + } + } + [DefaultValue("Blue")] + public virtual Color SelectionBackground { + get { return selBackground; } + set { + if (value == selBackground) + return; + selBackground = value; + NotifyValueChanged ("SelectionBackground", selBackground); + RegisterForRedraw (); + } + } + [DefaultValue("White")] + public virtual Color SelectionForeground { + get { return selForeground; } + set { + if (value == selForeground) + return; + selForeground = value; + NotifyValueChanged ("SelectionForeground", selForeground); + RegisterForRedraw (); + } + } + public override int ScrollY { + get { + return base.ScrollY; + } + set { + if (value == base.ScrollY) + return; + //editorMutex.EnterWriteLock (); + base.ScrollY = value; + //editorMutex.ExitWriteLock (); + RegisterForGraphicUpdate (); + } + } + #endregion + + + void loadSource () { + /*buffer.Load (projFile.Source); + projFile.RegisteredEditors [this] = true;*/ + updateMaxScrollY (); + RegisterForGraphicUpdate (); + } + + int getTabulatedColumn (int col, int line) { + return buffer.GetSubString (buffer [line], + buffer.GetLineLength (line)).Substring(0,col).Replace ("\t", new String (' ', Interface.TAB_SIZE)).Length; + } + int getTabulatedColumn (Point pos) { + return getTabulatedColumn (pos.X,pos.Y); + } + + #region Drawing + void drawLines(Context gr, Rectangle cb) { + int longestTabulatedLine = 0; + for (int i = 0; i < visibleLines; i++) { + int lineIndex = i + ScrollY; + if (lineIndex >= buffer.LineCount)//TODO:need optimize + break; + + double y = cb.Y + (fe.Ascent+fe.Descent) * i, x = cb.X; + + int lineLength = buffer.GetLineLength (lineIndex); + if (lineIndex < buffer.LineCount - 1)//dont print line break + lineLength--; + string lstr = buffer.GetSubString (buffer [lineIndex], + lineLength).Replace ("\t", new String (' ', Interface.TAB_SIZE)); + + int lstrLength = lstr.Length; + if (lstrLength > longestTabulatedLine) + longestTabulatedLine = lstrLength; + + if (ScrollX < lstrLength) + lstr = lstr.Substring (ScrollX); + else + lstr = ""; + + gr.MoveTo (x, y + fe.Ascent); + gr.ShowText (lstr); + gr.Fill (); + + if (!buffer.SelectionIsEmpty && lineIndex >= buffer.SelectionStart.Y && lineIndex <= buffer.SelectionEnd.Y) { + double rLineX = x, + rLineY = y, + rLineW = lstr.Length * fe.MaxXAdvance; + + if (lineIndex == buffer.SelectionStart.Y) { + rLineX += (selStartCol - ScrollX) * fe.MaxXAdvance; + rLineW -= (selStartCol - ScrollX) * fe.MaxXAdvance; + } + if (lineIndex == buffer.SelectionEnd.Y) + rLineW -= (lstr.Length - selEndCol + ScrollX) * fe.MaxXAdvance; + + gr.Save (); + gr.Operator = Operator.Source; + gr.Rectangle (rLineX, rLineY, rLineW, (fe.Ascent+fe.Descent)); + gr.SetSource (SelectionBackground); + gr.FillPreserve (); + gr.Clip (); + gr.Operator = Operator.Over; + gr.SetSource (SelectionForeground); + gr.MoveTo (x, y + fe.Ascent); + gr.ShowText (lstr); + gr.Fill (); + gr.Restore (); + } + + + } + + updateMaxScrollX(longestTabulatedLine); + } + #endregion + + #region GraphicObject overrides + public override Font Font { + get { return base.Font; } + set { + base.Font = value; + + using (ImageSurface img = new ImageSurface (Format.Argb32, 1, 1)) { + using (Context gr = new Context (img)) { + gr.SelectFontFace (Font.Name, Font.Slant, Font.Wheight); + gr.SetFontSize (Font.Size); + + fe = gr.FontExtents; + } + } + MaxScrollY = 0; + RegisterForGraphicUpdate (); + } + } + public override int measureRawSize(LayoutingType lt) + { + if (lt == LayoutingType.Height) + return (int)Math.Ceiling((fe.Ascent+fe.Descent) * buffer.LineCount) + Margin * 2; + + return 0;// (int)(fe.MaxXAdvance * buffer.GetLineLength(buffer.longestLineIdx)) + Margin * 2; + } + public override void OnLayoutChanges (LayoutingType layoutType) + { + base.OnLayoutChanges (layoutType); + + if (layoutType == LayoutingType.Height) + updateVisibleLines (); + else if (layoutType == LayoutingType.Width) + updateVisibleColumns (); + } + + protected override void onDraw (Context gr) + { + base.onDraw (gr); + + gr.SelectFontFace (Font.Name, Font.Slant, Font.Wheight); + gr.SetFontSize (Font.Size); + gr.FontOptions = Interface.FontRenderingOptions; + gr.Antialias = Interface.Antialias; + + Rectangle cb = ClientRectangle; + + Foreground.SetAsSource (gr); + + buffer.editMutex.EnterReadLock (); + //editorMutex.EnterReadLock (); + + #region draw text cursor + if (buffer.SelectionInProgress){ + selStartCol = getTabulatedColumn (buffer.SelectionStart); + selEndCol = getTabulatedColumn (buffer.SelectionEnd); + }else if (HasFocus && CurrentLine >= 0){ + gr.LineWidth = 1.0; + double cursorX = cb.X + (getTabulatedColumn(buffer.CurrentPosition) - ScrollX) * fe.MaxXAdvance ; + double cursorY = cb.Y + (buffer.CurrentLine - ScrollY) * (fe.Ascent+fe.Descent); + gr.MoveTo (0.5 + cursorX, cursorY); + gr.LineTo (0.5 + cursorX, cursorY + fe.Ascent+fe.Descent); + gr.Stroke(); + } + #endregion + + drawLines (gr, cb); + + //editorMutex.ExitReadLock (); + + buffer.editMutex.ExitReadLock (); + + } + #endregion + + int getBufferColFromVisualCol (int line, int column) { + int i = 0; + int buffCol = 0; + int buffPtr = buffer [line]; + while (i < column && buffCol < buffer.GetLineLength(line)) { + if (buffer.GetCharAt(buffPtr + buffCol) == '\t') + i += Interface.TAB_SIZE; + else + i++; + buffCol++; + } + return buffCol; + } + + + #region Mouse handling + + int hoverLine = -1; + public int HoverLine { + get { return hoverLine; } + set { + if (hoverLine == value) + return; + hoverLine = value; + NotifyValueChanged ("HoverLine", hoverLine); + } + } + void updateHoverLine () { +// int hvl = (int)Math.Max (0, Math.Floor (mouseLocalPos.Y / (fe.Ascent+fe.Descent))); +// hvl = Math.Min (PrintedLines.Count, hvl); +// HoverLine = buffer.IndexOf (PrintedLines[hvl]); + } + void updateCurrentPosFromMouseLocalPos(){ + + buffer.CurrentLine = ScrollY + (int)Math.Max (0, Math.Floor (mouseLocalPos.Y / (fe.Ascent+fe.Descent))); + int curVisualCol = ScrollX + (int)Math.Round ((mouseLocalPos.X) / fe.MaxXAdvance); + buffer.CurrentColumn = getBufferColFromVisualCol (buffer.CurrentLine, curVisualCol); + } + + public override void onMouseEnter (object sender, MouseMoveEventArgs e) + { + base.onMouseEnter (sender, e); + IFace.MouseCursor = MouseCursor.ibeam; + } + public override void onMouseLeave (object sender, MouseMoveEventArgs e) + { + base.onMouseLeave (sender, e); + IFace.MouseCursor = MouseCursor.arrow; + } + public override void onMouseMove (object sender, MouseMoveEventArgs e) + { + base.onMouseMove (sender, e); + + mouseLocalPos = e.Position - ScreenCoordinates(Slot).TopLeft - ClientRectangle.TopLeft; + + updateHoverLine (); + + if (!IFace.IsDown(MouseButton.Left) || !buffer.SelectionInProgress) + return; + + //mouse is down + updateCurrentPosFromMouseLocalPos(); + buffer.SetSelEndPos (); + } + public override void onMouseDown (object sender, MouseButtonEventArgs e) + { + if (!Focusable) + return; + + base.onMouseDown (sender, e); + + if (doubleClicked) { + doubleClicked = false; + return; + } + + updateCurrentPosFromMouseLocalPos (); + buffer.SetSelStartPos (); + } + public override void onMouseUp (object sender, MouseButtonEventArgs e) + { + base.onMouseUp (sender, e); + + if (buffer.SelectionIsEmpty) + buffer.ResetSelection (); + } + + public override void onMouseDoubleClick (object sender, MouseButtonEventArgs e) + { + //doubleClicked = true; + base.onMouseDoubleClick (sender, e); + + buffer.GotoWordStart (); + buffer.SetSelStartPos (); + buffer.GotoWordEnd (); + buffer.SetSelEndPos (); + } + + public override void onMouseWheel (object sender, MouseWheelEventArgs e) + { + base.onMouseWheel (sender, e); + } + #endregion + + #region Keyboard handling + public override void onKeyDown (object sender, KeyEventArgs e) + { + //base.onKeyDown (sender, e); + + Key key = e.Key; + + /*if (IFace.Ctrl) { + switch (key) { + case Key.S: + projFile.Save (); + break; + case Key.W: + editorMutex.EnterWriteLock (); + if (IFace.Shift) + projFile.Redo (null); + else + projFile.Undo (null); + editorMutex.ExitWriteLock (); + break; + default: + Console.WriteLine (""); + break; + } + }*/ + + switch (key) + { + case Key.Backspace: + buffer.Delete (); + break; + case Key.Delete: + if (buffer.SelectionIsEmpty) + buffer.MoveRight (); +// else if (e.Shift) +// IFace.Clipboard = buffer.SelectedText; + buffer.Delete (); + break; + case Key.Enter: + case Key.KeypadEnter: + if (!buffer.SelectionIsEmpty) + buffer.Delete (); + buffer.InsertLineBreak (); + break; + case Key.Escape: + buffer.ResetSelection (); + break; + case Key.Home: + if (IFace.Shift) { + if (buffer.SelectionIsEmpty) + buffer.SetSelStartPos (); + if (IFace.Ctrl) + buffer.CurrentLine = 0; + buffer.CurrentColumn = 0; + buffer.SetSelEndPos (); + break; + } + buffer.ResetSelection (); + if (IFace.Ctrl) + buffer.CurrentLine = 0; + buffer.CurrentColumn = 0; + break; + case Key.End: + if (IFace.Shift) { + if (buffer.SelectionIsEmpty) + buffer.SetSelStartPos (); + if (IFace.Ctrl) + buffer.CurrentLine = int.MaxValue; + buffer.CurrentColumn = int.MaxValue; + buffer.SetSelEndPos (); + break; + } + buffer.ResetSelection (); + if (IFace.Ctrl) + buffer.CurrentLine = int.MaxValue; + buffer.CurrentColumn = int.MaxValue; + break; + case Key.Insert: + if (IFace.Shift) + buffer.InsertAt (IFace.Clipboard); + else if (IFace.Ctrl && !buffer.SelectionIsEmpty) + IFace.Clipboard = buffer.SelectedText; + break; + case Key.Left: + if (IFace.Shift) { + if (buffer.SelectionIsEmpty) + buffer.SetSelStartPos (); + if (IFace.Ctrl) + buffer.GotoWordStart (); + else + buffer.MoveLeft (); + buffer.SetSelEndPos (); + break; + } + buffer.ResetSelection (); + if (IFace.Ctrl) + buffer.GotoWordStart (); + else + buffer.MoveLeft(); + break; + case Key.Right: + if (IFace.Shift) { + if (buffer.SelectionIsEmpty) + buffer.SetSelStartPos (); + if (IFace.Ctrl) + buffer.GotoWordEnd (); + else + buffer.MoveRight (); + buffer.SetSelEndPos (); + break; + } + buffer.ResetSelection (); + if (IFace.Ctrl) + buffer.GotoWordEnd (); + else + buffer.MoveRight (); + break; + case Key.Up: + if (IFace.Shift) { + if (buffer.SelectionIsEmpty) + buffer.SetSelStartPos (); + CurrentLine--; + buffer.SetSelEndPos (); + break; + } + buffer.ResetSelection (); + CurrentLine--; + break; + case Key.Down: + if (IFace.Shift) { + if (buffer.SelectionIsEmpty) + buffer.SetSelStartPos (); + CurrentLine++; + buffer.SetSelEndPos (); + break; + } + buffer.ResetSelection (); + CurrentLine++; + break; + case Key.Menu: + break; + case Key.PageDown: + if (IFace.Shift) { + if (buffer.SelectionIsEmpty) + buffer.SetSelStartPos (); + CurrentLine += visibleLines; + buffer.SetSelEndPos (); + break; + } + buffer.ResetSelection (); + CurrentLine += visibleLines; + break; + case Key.PageUp: + if (IFace.Shift) { + if (buffer.SelectionIsEmpty) + buffer.SetSelStartPos (); + CurrentLine -= visibleLines; + buffer.SetSelEndPos (); + break; + } + buffer.ResetSelection (); + CurrentLine -= visibleLines; + break; + case Key.Tab: + buffer.InsertAt ("\t"); + break; + default: + break; + } + RegisterForGraphicUpdate(); + } + public override void onKeyPress (object sender, KeyPressEventArgs e) + { + base.onKeyPress (sender, e); + + buffer.InsertAt (e.KeyChar.ToString()); + buffer.ResetSelection (); + } + #endregion + } +} \ No newline at end of file diff --git a/src/TextFormatting.cs b/Crow.Coding/src/CodeBuffer/TextFormatting.cs similarity index 100% rename from src/TextFormatting.cs rename to Crow.Coding/src/CodeBuffer/TextFormatting.cs diff --git a/src/Token.cs b/Crow.Coding/src/CodeBuffer/Token.cs similarity index 91% rename from src/Token.cs rename to Crow.Coding/src/CodeBuffer/Token.cs index e0cb7e0..5896d75 100644 --- a/src/Token.cs +++ b/Crow.Coding/src/CodeBuffer/Token.cs @@ -19,19 +19,18 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . using System; -using CrowEdit; namespace Crow.Coding { public struct Token { - public Parser.TokenType Type; + public BufferParser.TokenType Type; public string Content; public Point Start; public Point End; public string PrintableContent { - get { return string.IsNullOrEmpty(Content) ? "" : Content.Replace("\t", new String(' ', Interface.TabSize)); } + get { return string.IsNullOrEmpty(Content) ? "" : Content.Replace("\t", new String(' ', Interface.TAB_SIZE)); } } // public Token (TokenType tokType, string content = ""){ @@ -39,6 +38,7 @@ namespace Crow.Coding // Content = content; // } + public bool IsNull { get { return IsEmpty && Type == BufferParser.TokenType.Unknown; }} public bool IsEmpty { get { return string.IsNullOrEmpty(Content); }} public static bool operator == (Token t, System.Enum tt){ diff --git a/src/Parser.cs b/Crow.Coding/src/Parsers/BufferParser.cs similarity index 68% rename from src/Parser.cs rename to Crow.Coding/src/Parsers/BufferParser.cs index 79dc086..8458e6e 100644 --- a/src/Parser.cs +++ b/Crow.Coding/src/Parsers/BufferParser.cs @@ -3,44 +3,49 @@ using System.IO; using Crow; using System.Collections.Generic; using System.Diagnostics; +using System.Text; namespace Crow.Coding { /// /// base class for tokenizing sources /// - public abstract class Parser + public abstract class BufferParser { /// /// Default tokens, this enum may be overriden in derived parser with the new keyword, /// see XMLParser for example. /// public enum TokenType { - Unknown, - WhiteSpace, - NewLine, - LineComment, - BlockCommentStart, - BlockComment, - BlockCommentEnd, - Type, - Identifier, - Indexer, - OpenBlock, - CloseBlock, - StatementEnding, - UnaryOp, - BinaryOp, - Affectation, - StringLitteralOpening, - StringLitteralClosing, - StringLitteral, - NumericLitteral, - Preprocessor, + Unknown = 0, + WhiteSpace = 1, + NewLine = 2, + LineComment = 3, + BlockCommentStart = 4, + BlockComment = 5, + BlockCommentEnd = 6, + Preprocessor = 7, + Identifier = 8, + Keyword = 9, + OpenBlock = 10, + CloseBlock = 11, + StatementEnding = 12, + OperatorOrPunctuation = 13, + IntegerLitteral = 14, + RealLitteral = 15, + StringLitteralOpening = 16, + StringLitteralClosing = 17, + StringLitteral = 18, + CharLitteralOpening = 19, + CharLitteralClosing = 20, + CharLitteral = 21, + BoolLitteral = 22, + NullLitteral = 23, + Type = 24, } #region CTOR - public Parser (CodeBuffer _buffer) + public BufferParser (CodeBuffer _buffer) { buffer = _buffer; @@ -68,11 +73,81 @@ namespace Crow.Coding void Buffer_LineUpadateEvent (object sender, CodeBufferEventArgs e) { for (int i = 0; i < e.LineCount; i++) - tryParseBufferLine (e.LineStart + i); + TryParseBufferLine (e.LineStart + i); reparseSource (); } #endregion + internal int currentLine = 0; + internal int currentColumn = 0; + + int syntTreeDepth = 0; + public int SyntacticTreeDepth { + get { return syntTreeDepth;} + set { + syntTreeDepth = value; + if (syntTreeDepth > SyntacticTreeMaxDepth) + SyntacticTreeMaxDepth = syntTreeDepth; + } + } + public int SyntacticTreeMaxDepth = 0; + + protected CodeBuffer buffer; + protected Token currentTok; + protected bool eol = true; + protected Point CurrentPosition { + get { return new Point (currentLine, currentColumn); } + set { + currentLine = value.Y; + currentColumn = value.X; + } + } + + public Node RootNode; + + public abstract void ParseCurrentLine(); + public abstract void SyntaxAnalysis (); + public void reparseSource () { + for (int i = 0; i < buffer.LineCount; i++) { + if (!buffer[i].IsParsed) + TryParseBufferLine (i); + } + try { + SyntaxAnalysis (); + } catch (Exception ex) { + Debug.WriteLine ("Syntax Error: " + ex.ToString ()); + if (ex is ParserException) + SetLineInError (ex as ParserException); + } + } + public void TryParseBufferLine(int lPtr) { + Console.WriteLine ($"TryParseBufferLine: {lPtr}"); + buffer [lPtr].exception = null; + currentLine = lPtr; + currentColumn = 0; + eol = false; + + try { + ParseCurrentLine (); + } catch (Exception ex) { + Debug.WriteLine (ex.ToString ()); + if (ex is ParserException) + SetLineInError (ex as ParserException); + } + + } + + public virtual void SetLineInError(ParserException ex) { + currentTok = default(Token); + if (ex.Line >= buffer.LineCount) + ex.Line = buffer.LineCount - 1; + if (buffer [ex.Line].IsFolded) + buffer.ToogleFolding (ex.Line); + buffer [ex.Line].SetLineInError (ex); + } + public virtual string LineBrkRegex { + get { return @"\r\n|\r|\n|\\\\n"; } + } void updateFolding () { // Stack foldings = new Stack(); // bool inStartTag = false; @@ -106,71 +181,18 @@ namespace Crow.Coding // continue; // } // parser.CurrentPosition = tls [fstTK + 1].Start; - // parser.SetLineInError(new ParsingException(parser, "closing tag not corresponding")); + // parser.SetLineInError(new ParserException(parser, "closing tag not corresponding")); // } // // } // } } - public void reparseSource () { - for (int i = 0; i < buffer.LineCount; i++) { - if (!buffer[i].IsParsed) - tryParseBufferLine (i); - } - try { - SyntaxAnalysis (); - } catch (Exception ex) { - Debug.WriteLine ("Syntax Error: " + ex.ToString ()); - if (ex is ParsingException) - SetLineInError (ex as ParsingException); - } - } - public void tryParseBufferLine(int lPtr) { - buffer [lPtr].exception = null; - currentLine = lPtr; - currentColumn = 0; - eol = false; - - try { - ParseCurrentLine (); - } catch (Exception ex) { - Debug.WriteLine (ex.ToString ()); - if (ex is ParsingException) - SetLineInError (ex as ParsingException); - } - - } - - protected CodeBuffer buffer; - - internal int currentLine = 0; - internal int currentColumn = 0; - protected Token currentTok; - protected bool eol = true; - - public Node RootNode; - - protected Point CurrentPosition { - get { return new Point (currentLine, currentColumn); } - set { - currentLine = value.Y; - currentColumn = value.X; - } - } - - public abstract void ParseCurrentLine(); - public abstract void SyntaxAnalysis (); - - public virtual void SetLineInError(ParsingException ex) { - currentTok = default(Token); - if (ex.Line >= buffer.LineCount) - ex.Line = buffer.LineCount - 1; - if (buffer [ex.Line].IsFolded) - buffer.ToogleFolding (ex.Line); - buffer [ex.Line].SetLineInError (ex); - } #region low level parsing + protected void addCharToCurTok(char c, Point position){ + currentTok.Start = position; + currentTok += c; + } /// /// Read one char from current position in buffer and store it into the current token /// @@ -212,13 +234,27 @@ namespace Crow.Coding currentTok.Type = (TokenType)type; saveAndResetCurrentTok (); } + protected void setPreviousTokOfTypeTo (TokenType inType, TokenType newType) { + for (int i = currentLine; i >= 0; i--) { + int j = buffer [i].Tokens.Count - 1; + while (j >= 0) { + if (buffer [i].Tokens [j].Type == inType) { + Token t = buffer [i].Tokens [j]; + t.Type = newType; + buffer [i].Tokens [j] = t; + return; + } + j--; + } + } + } /// /// Peek next char, emit '\n' if current column > buffer's line length /// Throw error if eof is true /// protected virtual char Peek() { if (eol) - throw new ParsingException (this, "Unexpected End of line"); + throw new ParserException (currentLine, currentColumn, "Unexpected End of line"); return currentColumn < buffer [currentLine].Length ? buffer [currentLine] [currentColumn] : '\n'; } @@ -231,7 +267,7 @@ namespace Crow.Coding /// Length. protected virtual string Peek(int length) { if (eol) - throw new ParsingException (this, "Unexpected End of Line"); + return "";//throw new ParserException (currentLine, currentColumn, "Unexpected End of Line"); int lg = Math.Min(length, Math.Max (buffer [currentLine].Length - currentColumn, buffer [currentLine].Length - currentColumn - length)); if (lg == 0) return ""; @@ -248,15 +284,27 @@ namespace Crow.Coding currentColumn++; return c; } + protected virtual string Read(int charCount){ + string tmp = ""; + for (int i = 0; i < charCount; i++) { + if (eol) + break; + tmp += Read (); + } + return tmp; + } /// /// read until end of line is reached /// /// string read protected virtual string ReadLine () { - string tmp = ""; - while (!eol) - tmp += Read (); - return tmp; + StringBuilder tmp = new StringBuilder(); + char c = Read (); + while (!eol) { + tmp.Append (c); + c = Read (); + } + return tmp.ToString(); } /// /// read until end expression is reached or end of line. @@ -282,7 +330,7 @@ namespace Crow.Coding /// protected void SkipWhiteSpaces () { if (currentTok.Type != TokenType.Unknown) - throw new ParsingException (this, "current token should be reset to unknown (0) before skiping white spaces"); + throw new ParserException (currentLine, currentColumn, "current token should be reset to unknown (0) before skiping white spaces"); while (!eol) { if (!char.IsWhiteSpace (Peek ())||Peek()=='\n') break; @@ -293,5 +341,41 @@ namespace Crow.Coding saveAndResetCurrentTok (); } #endregion + + protected Node addChildNode (Node curNode, CodeLine cl, int tokPtr, string type = "") { + Node n = new Node () { Name = cl.Tokens [tokPtr].Content, StartLine = cl, Type = type }; + curNode.AddChild (n); + if (cl.SyntacticNode == null) + cl.SyntacticNode = n; + SyntacticTreeDepth++; + return n; + } + protected void closeNodeAndGoUp (ref Node n, CodeLine cl, string type = ""){ + while (n != null) { + if (n.Type == type) { + n.EndLine = cl; + n = n.Parent; + SyntacticTreeDepth--; + break; + } + n = n.Parent; + SyntacticTreeDepth--; + } + } + protected void closeNodeAndGoUp (ref Node n, CodeLine cl){ + SyntacticTreeDepth--; + n.EndLine = cl; + n = n.Parent; + } + + protected void initSyntaxAnalysis () { + RootNode = new Node () { Name = "RootNode", Type="Root" }; + SyntacticTreeDepth = SyntacticTreeMaxDepth = 0; + } + + + protected void throwParserException(string msg){ + throw new ParserException (currentLine, currentColumn, msg); + } } } \ No newline at end of file diff --git a/Crow.Coding/src/Parsers/CSharpParser.cs b/Crow.Coding/src/Parsers/CSharpParser.cs new file mode 100644 index 0000000..23655aa --- /dev/null +++ b/Crow.Coding/src/Parsers/CSharpParser.cs @@ -0,0 +1,386 @@ +using System; +using Crow; +using System.Collections.Generic; +using System.Diagnostics; +using System.Text.RegularExpressions; +using System.Linq; + +namespace Crow.Coding +{ + public class CSharpParser : BufferParser + { + #region keywords + string[] keywords = new string[] { + "abstract", + "as", + "ascending", + "async", + "await", + "base", + "bool", + "break", + "byte", + "case", + "catch", + "char", + "checked", + "class", + "const", + "continue", + "decimal", + "default", + "delegate", + "descending", + "do", + "double", + "dynamic", + "else", + "enum", + "equals", + "event", + "explicit", + "extern", + "false", + "finally", + "fixed", + "float", + "for", + "foreach", + "from", + "get", + "goto", + "group", + "if", + "implicit", + "in", + "int", + "interface", + "internal", + "is", + "join", + "let", + "lock", + "long", + "nameof", + "namespace", + "new", + "null", + "object", + "operator", + "orderby", + "out", + "override", + "params", + "partial", + "private", + "protected", + "public", + "readonly", + "ref", + "return", + "sbyte", + "sealed", + "select", + "set", + "short", + "sizeof", + "stackalloc", + "static", + "string", + "struct", + "switch", + "this", + "throw", + "true", + "try", + "typeof", + "uint", + "ulong", + "unchecked", + "unsafe", + "ushort", + "using", + "value", + "var", + "virtual", + "void", + "volatile", + "when", + "where", + "while", + "yield " + }; + #endregion + + public enum States + { + init, + BlockComment, + InNameSpace, + InClass, + InMember, + Unknown, + } + + public CSharpParser (CodeBuffer _buffer) : base(_buffer) + { + } + + #region Regular Expression for validity checks + static Regex rxValidChar = new Regex(@"\p{Lu}|\p{Ll}|\p{Lt}|\p{Lm}|\p{Lo}|\p{Nl}|\p{Mn}|\p{Mc}|\p{Nd}|\p{Pc}|\p{Cf}"); + static Regex rxNameStartChar = new Regex(@"_|\p{Lu}|\p{Ll}|\p{Lt}|\p{Lm}|\p{Lo}|\p{Nl}"); + static Regex rxNameChar = new Regex(@"\p{Lu}|\p{Ll}|\p{Lt}|\p{Lm}|\p{Lo}|\p{Nl}|\p{Mn}|\p{Mc}|\p{Nd}|\p{Pc}|\p{Cf}"); + static Regex rxNewLineChar = new Regex(@"\u000D|\u000A|\u0085|\u2028|\u2029"); + static Regex rxWhiteSpaceChar = new Regex(@"\p{Zs}|\u0009|\u000B|\u000C"); + static Regex rxDecimal = new Regex(@"[0-9]+"); + static Regex rxHexadecimal = new Regex(@"[0-9a-fA-F]+"); + + public static bool CharIsValidCharStartName (char c) { + return rxNameStartChar.IsMatch(new string(new char[]{c})); + } + public static bool CharIsValidCharName (char c) { + return rxNameChar.IsMatch(new string(new char[]{c})); + } + + public bool nextCharIsValidCharStartName + { + get { return CharIsValidCharStartName(Peek()); } + } + public bool nextCharIsValidCharName + { + get { return CharIsValidCharName(Peek()); } + } + #endregion + + States curState = States.init; + States savedState = States.init; + + public override void ParseCurrentLine () + { + //Debug.WriteLine (string.Format("parsing line:{0}", currentLine)); + CodeLine cl = buffer [currentLine]; + cl.Tokens = new List (); + + + //retrieve current parser state from previous line + if (currentLine > 0) + curState = (States)buffer[currentLine - 1].EndingState; + else + curState = States.init; + + States previousEndingState = (States)cl.EndingState; + + while (! eol) { + if (currentTok.IsNull) + SkipWhiteSpaces (); + + if (curState == States.BlockComment) { + currentTok.Start = CurrentPosition; + currentTok.Type = (BufferParser.TokenType)TokenType.BlockComment; + currentTok += ReadLineUntil ("*/"); + if (Peek (2) == "*/") { + readToCurrTok (2); + curState = savedState; + } + saveAndResetCurrentTok (); + continue; + } + + switch (Peek()) { + case '\n': + eol = true; + if (!currentTok.IsNull) + saveAndResetCurrentTok (); + break; + case '#': + readToCurrTok (true); + currentTok += ReadLine (); + saveAndResetCurrentTok (TokenType.Preprocessor); + break; + case '/': + readToCurrTok (true); + switch (Peek ()) { + case '*': + readToCurrTok (); + currentTok += ReadLine (); + //currentTok.Type = (Parser.TokenType)TokenType.BlockComment; + savedState = curState; + curState = States.BlockComment; + saveAndResetCurrentTok (TokenType.BlockComment); + break; + case '/': + //readToCurrTok (); + currentTok += ReadLine (); + saveAndResetCurrentTok (TokenType.LineComment); + //currentTok.Type = (Parser.TokenType)TokenType.LineComment; + break; + default: + currentTok += ReadLine (); + saveAndResetCurrentTok (TokenType.Unknown); + break; + } + break; + case '{': + if (currentTok.IsNull) + readAndResetCurrentTok (TokenType.OpenBlock, true); + else + readToCurrTok (); + break; + case '}': + if (currentTok.IsNull) + readAndResetCurrentTok (TokenType.CloseBlock, true); + else + readToCurrTok (); + break; + case '\\'://unicode escape sequence + if (!(currentTok.Type == TokenType.Identifier || + currentTok.IsEmpty || currentTok.Type == TokenType.StringLitteral || currentTok.Type == TokenType.CharLitteral)) { + saveAndResetCurrentTok (); + } + Point pos = CurrentPosition; + Read (); + char escChar = Read (); + + if (escChar == 'u') { + char c = char.ConvertFromUtf32 (int.Parse (Read (4), System.Globalization.NumberStyles.HexNumber))[0]; + if (currentTok.IsEmpty) { + if (!CharIsValidCharStartName (c)) + throwParserException ("expecting identifier start"); + currentTok.Start = pos; + currentTok.Type = TokenType.Identifier; + } else if (currentTok.Type == TokenType.Identifier) { + if (!CharIsValidCharName (c)) + throwParserException ("expecting identifier valid char"); + } + currentTok += c; + break; + } + currentTok += new String (new char[] { '\\', escChar }); + break; + case '\'': + if (currentTok.IsNull) { + readAndResetCurrentTok (TokenType.CharLitteralOpening, true); + currentTok.Type = TokenType.CharLitteral; + } else if (currentTok.Type == TokenType.CharLitteral) { + saveAndResetCurrentTok (); + readAndResetCurrentTok (TokenType.CharLitteralClosing, true); + } else if (currentTok.Type == TokenType.StringLitteral){ + readToCurrTok (); + } else + throwParserException ("unexpected character: (\')"); + break; + case '"': + if (currentTok.IsNull) { + readAndResetCurrentTok (TokenType.StringLitteralOpening, true); + currentTok.Type = TokenType.StringLitteral; + } else if (currentTok.Type == TokenType.StringLitteral) { + saveAndResetCurrentTok (); + readAndResetCurrentTok (TokenType.StringLitteralClosing, true); + } else + throwParserException ("unexpected character: (\")"); + break; + default: + if (currentTok.Type == TokenType.StringLitteral || currentTok.Type == TokenType.CharLitteral) { + readToCurrTok (currentTok.IsEmpty); + } else if (currentTok.IsNull) { + if (nextCharIsValidCharStartName) { + readToCurrTok (true); + while (nextCharIsValidCharName) + readToCurrTok (); + + if (keywords.Contains (currentTok.Content)) + saveAndResetCurrentTok (TokenType.Keyword); + else + saveAndResetCurrentTok (TokenType.Identifier); + continue; + } else + readAndResetCurrentTok(TokenType.Unknown, true); + } else + readAndResetCurrentTok(TokenType.Unknown, true); + break; + } + } + + if (cl.EndingState != (int)curState && currentLine < buffer.LineCount - 1) + buffer [currentLine + 1].Tokens = null; + + cl.EndingState = (int)curState; + } + + public override void SyntaxAnalysis () + { + initSyntaxAnalysis (); + Node currentNode = RootNode; + + int ptrLine = 0; + while (ptrLine < buffer.LineCount) { + CodeLine cl = buffer [ptrLine]; + if (cl.Tokens == null){ + ptrLine++; + continue; + } + cl.SyntacticNode = null; + + int tokPtr = 0; + bool onlyWhiteSpace = true; + while (tokPtr < cl.Tokens.Count) { + if (cl.Tokens [tokPtr].Type == TokenType.WhiteSpace) { + tokPtr++; + continue; + } + + if (cl.Tokens [tokPtr].Type == TokenType.LineComment && onlyWhiteSpace) { + int startLine = ptrLine; + ptrLine++; + while (ptrLine < buffer.LineCount) { + int idx = buffer [ptrLine].FirstNonBlankTokIndex; + if (idx < 0) + break; + if (buffer [ptrLine].Tokens [idx].Type != TokenType.LineComment) + break; + ptrLine++; + } + ptrLine--; + if (ptrLine - startLine > 0) { + currentNode = addChildNode (currentNode, cl, tokPtr, "comment"); + closeNodeAndGoUp (ref currentNode, buffer [ptrLine], "comment"); + } + break; + } + + switch (cl.Tokens [tokPtr].Type) { + case TokenType.BlockCommentStart: + case TokenType.OpenBlock: + currentNode = addChildNode (currentNode, cl, tokPtr); + break; + case TokenType.CloseBlock: + case TokenType.BlockCommentEnd: + closeNodeAndGoUp (ref currentNode, cl); + break; + case TokenType.Preprocessor: + if (cl.Tokens [tokPtr].Content.StartsWith ("#region", StringComparison.Ordinal)) { + currentNode = addChildNode (currentNode, cl, tokPtr, "region"); + } else if (cl.Tokens [tokPtr].Content.StartsWith ("#endregion", StringComparison.Ordinal)) { + + closeNodeAndGoUp (ref currentNode, cl,"region"); + } + break; + } + onlyWhiteSpace = false; + tokPtr++; + } + ptrLine++; + } + /*ptrLine = 0; + while (ptrLine < buffer.LineCount) { + CodeLine cl = buffer [ptrLine]; + if (cl.IsFoldable) { + if (cl.SyntacticNode.Type == "comment" || cl.SyntacticNode.Type == "region") + cl.IsFolded = true; + } + ptrLine++; + }*/ + } + } +} + diff --git a/Crow.Coding/src/Parsers/StyleParser.cs b/Crow.Coding/src/Parsers/StyleParser.cs new file mode 100644 index 0000000..9a1e74c --- /dev/null +++ b/Crow.Coding/src/Parsers/StyleParser.cs @@ -0,0 +1,179 @@ +using System; +using Crow; +using System.Collections.Generic; +using System.Diagnostics; +using System.Text.RegularExpressions; +using System.Linq; + +namespace Crow.Coding +{ + public class StyleParser : BufferParser + { + enum States { init, classNames, members, value, endOfStatement } + + public StyleParser (CodeBuffer _buffer) : base(_buffer) + { + } + + #region Character ValidityCheck + static Regex rxValidChar = new Regex(@"\p{Lu}|\p{Ll}|\p{Lt}|\p{Lm}|\p{Lo}|\p{Nl}|\p{Mn}|\p{Mc}|\p{Nd}|\p{Pc}|\p{Cf}"); + static Regex rxNameStartChar = new Regex(@"_|\p{Lu}|\p{Ll}|\p{Lt}|\p{Lm}|\p{Lo}"); + static Regex rxNameChar = new Regex(@"\p{Lu}|\p{Ll}|\p{Lt}|\p{Lm}|\p{Lo}|\p{Nl}|\p{Mn}|\p{Mc}|\p{Nd}|\p{Pc}|\p{Cf}"); + static Regex rxDecimal = new Regex(@"[0-9]+"); + static Regex rxHexadecimal = new Regex(@"[0-9a-fA-F]+"); + + public bool nextCharIsValidCharStartName + { + get { return rxNameStartChar.IsMatch(new string(new char[]{Peek()})); } + } + public bool nextCharIsValidCharName + { + get { return rxNameChar.IsMatch(new string(new char[]{Peek()})); } + } + #endregion + + States curState = States.classNames; + + public override void ParseCurrentLine () + { + //Debug.WriteLine (string.Format("parsing line:{0}", currentLine)); + CodeLine cl = buffer [currentLine]; + cl.Tokens = new List (); + + //retrieve current parser state from previous line + if (currentLine > 0) + curState = (States)buffer[currentLine - 1].EndingState; + else + curState = States.init; + + States previousEndingState = (States)cl.EndingState; + + while (! eol) { + SkipWhiteSpaces (); + + if (eol) + break; + + if (Peek () == '\n') { + if (currentTok != TokenType.Unknown) + throw new ParserException (currentLine, currentColumn, "Unexpected end of line"); + Read (); + eol = true; + continue; + } + + switch (Peek()) { + case '/': + readToCurrTok (true); + switch (Peek ()) { + case '/': + currentTok += ReadLine (); + saveAndResetCurrentTok (TokenType.LineComment); + break; + default: + currentTok += ReadLine (); + saveAndResetCurrentTok (TokenType.Unknown); + break; + } + break; + case ',': + if (curState != States.init && curState != States.classNames ) + throw new ParserException (currentLine, currentColumn, "Unexpected char ','"); + readAndResetCurrentTok (TokenType.OperatorOrPunctuation, true); + curState = States.classNames; + break; + case '{': + if (!(curState == States.init || curState == States.classNames)) + throw new ParserException (currentLine, currentColumn, "Unexpected char '{'"); + readAndResetCurrentTok (TokenType.OpenBlock, true); + curState = States.members; + break; + case '}': + if (curState != States.members) + throw new ParserException (currentLine, currentColumn, "Unexpected char '}'"); + readAndResetCurrentTok (TokenType.CloseBlock, true); + curState = States.classNames; + break; + case '=': + if (curState == States.classNames) + throw new ParserException (currentLine, currentColumn, "Unexpected char '='"); + setPreviousTokOfTypeTo (TokenType.Type, TokenType.Identifier); + readAndResetCurrentTok (TokenType.OperatorOrPunctuation, true); + curState = States.value; + break; + case '"': + if (curState != States.value) + throw new ParserException (currentLine, currentColumn, "Unexpected char '\"'"); + readAndResetCurrentTok (TokenType.StringLitteralOpening, true); + + while (!eol) { + currentTok += ReadLineUntil ("\""); + if (currentTok.Content [currentTok.Content.Length - 1] == '\\') + readToCurrTok (); + else + break; + } + if (eol) + throw new ParserException (currentLine, currentColumn, "Unexpected end of line"); + saveAndResetCurrentTok (TokenType.StringLitteral); + + readAndResetCurrentTok (TokenType.StringLitteralClosing, true); + curState = States.endOfStatement; + break; + case ';': + if (curState != States.endOfStatement) + throw new ParserException (currentLine, currentColumn, "Unexpected end of statement"); + readAndResetCurrentTok (TokenType.StatementEnding, true); + curState = States.members; + break; + default: + if (currentTok.Type != TokenType.Unknown) + throw new ParserException (currentLine, currentColumn, "error curtok not null"); + if (curState == States.value) + throw new ParserException (currentLine, currentColumn, "expecting value enclosed in '\"'"); + if (curState == States.endOfStatement) + throw new ParserException (currentLine, currentColumn, "expecting end of statement"); + + if (nextCharIsValidCharStartName) { + readToCurrTok (true); + while (nextCharIsValidCharName) + readToCurrTok (); + } + saveAndResetCurrentTok (TokenType.Type); + break; + } + } + + if (cl.EndingState != (int)curState && currentLine < buffer.LineCount - 1) + buffer [currentLine + 1].Tokens = null; + + cl.EndingState = (int)curState; + } + public override void SyntaxAnalysis () + { + initSyntaxAnalysis (); + Node currentNode = RootNode; + + for (int i = 0; i < buffer.LineCount; i++) { + CodeLine cl = buffer[i]; + if (cl.Tokens == null) + continue; + cl.SyntacticNode = null; + + int tokPtr = 0; + while (tokPtr < cl.Tokens.Count) { + switch (cl.Tokens [tokPtr].Type) { + case TokenType.OpenBlock: + currentNode = addChildNode (currentNode, cl, tokPtr, "style"); + break; + case TokenType.CloseBlock: + closeNodeAndGoUp (ref currentNode, cl, "style"); + break; + } + tokPtr++; + } + } + } + } +} + diff --git a/src/XMLParser.cs b/Crow.Coding/src/Parsers/XMLParser.cs similarity index 66% rename from src/XMLParser.cs rename to Crow.Coding/src/Parsers/XMLParser.cs index 2a8ffeb..e5bfd89 100644 --- a/src/XMLParser.cs +++ b/Crow.Coding/src/Parsers/XMLParser.cs @@ -7,26 +7,28 @@ using System.Linq; namespace Crow.Coding { - public class XMLParser : Parser + public class XMLParser : BufferParser { public new enum TokenType { - Unknown = Parser.TokenType.Unknown, - WhiteSpace = Parser.TokenType.WhiteSpace, - NewLine = Parser.TokenType.NewLine, - LineComment = Parser.TokenType.LineComment, - BlockCommentStart = Parser.TokenType.BlockCommentStart, - BlockComment = Parser.TokenType.BlockComment, - BlockCommentEnd = Parser.TokenType.BlockCommentEnd, - Affectation = Parser.TokenType.Affectation, - XMLDecl = Parser.TokenType.Preprocessor, - ElementStart, - ElementEnd, - ElementClosing = Parser.TokenType.StatementEnding, - ElementName = Parser.TokenType.Type, - AttributeName = Parser.TokenType.Identifier, - AttributeValueOpening = Parser.TokenType.StringLitteralOpening, - AttributeValueClosing = Parser.TokenType.StringLitteralClosing, - AttributeValue = Parser.TokenType.StringLitteral, + Unknown = BufferParser.TokenType.Unknown, + WhiteSpace = BufferParser.TokenType.WhiteSpace, + NewLine = BufferParser.TokenType.NewLine, + LineComment = BufferParser.TokenType.LineComment, + BlockCommentStart = BufferParser.TokenType.BlockCommentStart, + BlockComment = BufferParser.TokenType.BlockComment, + BlockCommentEnd = BufferParser.TokenType.BlockCommentEnd, + ElementName = BufferParser.TokenType.Type, + AttributeName = BufferParser.TokenType.Identifier, + ElementClosing = BufferParser.TokenType.StatementEnding, + Affectation = BufferParser.TokenType.OperatorOrPunctuation, + AttributeValueOpening = BufferParser.TokenType.StringLitteralOpening, + AttributeValueClosing = BufferParser.TokenType.StringLitteralClosing, + AttributeValue = BufferParser.TokenType.StringLitteral, + XMLDecl = BufferParser.TokenType.Preprocessor, + Doctype = BufferParser.TokenType.Keyword, + ElementStart = 50, + ElementEnd = 51, + Content = 60, } public enum States @@ -82,7 +84,7 @@ namespace Crow.Coding } #endregion - public override void SetLineInError (ParsingException ex) + public override void SetLineInError (ParserException ex) { base.SetLineInError (ex); //buffer[ex.Line].Tokens.EndingState = (int)States.init; @@ -90,7 +92,7 @@ namespace Crow.Coding public override void ParseCurrentLine () { - Debug.WriteLine (string.Format("parsing line:{0}", currentLine)); + //Debug.WriteLine (string.Format("parsing line:{0}", currentLine)); CodeLine cl = buffer [currentLine]; cl.Tokens = new List (); @@ -104,14 +106,15 @@ namespace Crow.Coding while (! eol) { - SkipWhiteSpaces (); + if (curState != States.Content) + SkipWhiteSpaces (); if (eol) break; if (Peek () == '\n') { if (currentTok != TokenType.Unknown) - throw new ParsingException (this, "Unexpected end of line"); + throw new ParserException (currentLine, currentColumn, "Unexpected end of line"); Read (); eol = true; continue; @@ -122,7 +125,7 @@ namespace Crow.Coding Debugger.Break (); currentTok.Start = CurrentPosition; - currentTok.Type = (Parser.TokenType)TokenType.BlockComment; + currentTok.Type = (BufferParser.TokenType)TokenType.BlockComment; currentTok += ReadLineUntil ("-->"); if (Peek (3) == "-->") { readToCurrTok (3); @@ -138,11 +141,11 @@ namespace Crow.Coding switch (Peek()) { case '?': if (curState != States.init) - throw new ParsingException (this, "xml decl may appear only on first line"); + throw new ParserException (currentLine, currentColumn, "xml decl may appear only on first line"); readToCurrTok (); currentTok += ReadLineUntil ("?>"); if (Peek (2) != "?>") - throw new ParsingException (this, "expecting '?>'"); + throw new ParserException (currentLine, currentColumn, "expecting '?>'"); readToCurrTok (2); saveAndResetCurrentTok (TokenType.XMLDecl); curState = States.prolog; @@ -153,7 +156,7 @@ namespace Crow.Coding case '-': readToCurrTok (); if (Peek () != '-') - throw new ParsingException (this, "Expecting comment start tag"); + throw new ParserException (currentLine, currentColumn, "Expecting comment start tag"); readToCurrTok (); currentTok += ReadLineUntil ("--"); if (Peek (3) == "-->") { @@ -162,13 +165,21 @@ namespace Crow.Coding curState = States.BlockComment; saveAndResetCurrentTok (TokenType.BlockComment); break; - default: - throw new ParsingException(this, "error"); + case 'D': + case 'd': + string tmp = Read (7); + currentTok += tmp; + if (!string.Equals (tmp, "DOCTYPE", StringComparison.OrdinalIgnoreCase)) + throw new ParserException (currentLine, currentColumn, "Expecting 'doctype'"); + saveAndResetCurrentTok (TokenType.Doctype); + break; + default: + throw new ParserException (currentLine, currentColumn, "error"); } break; default: if (!(curState == States.Content || curState == States.XML || curState == States.init || curState == States.prolog)) - throw new ParsingException (this, "Unexpected char: '<'"); + throw new ParserException (currentLine, currentColumn, "Unexpected char: '<'"); if (Peek () == '/') { curState = States.EndTag; readToCurrTok (); @@ -179,7 +190,7 @@ namespace Crow.Coding } if (!nextCharIsValidCharStartName) - throw new ParsingException (this, "Expected element name"); + throw new ParserException (currentLine, currentColumn, "Expected element name"); readToCurrTok (true); while (nextCharIsValidCharName) @@ -191,10 +202,10 @@ namespace Crow.Coding break; case '/': if (curState != States.StartTag) - throw new ParsingException (this, "Unexpected char: '/'"); + throw new ParserException (currentLine, currentColumn, "Unexpected char: '/'"); readToCurrTok (true); if (Peek () != '>') - throw new ParsingException (this, "Expecting '>'"); + throw new ParserException (currentLine, currentColumn, "Expecting '>'"); readAndResetCurrentTok (TokenType.ElementEnd); curState = States.XML; @@ -209,25 +220,30 @@ namespace Crow.Coding curState = States.Content; break; default: - throw new ParsingException (this, "Unexpected char: '>'"); + throw new ParserException (currentLine, currentColumn, "Unexpected char: '>'"); } break; default: switch (curState) { case States.StartTag: if (!nextCharIsValidCharStartName) - throw new ParsingException (this, "Expected attribute name"); + throw new ParserException (currentLine, currentColumn, "Expected attribute name"); readToCurrTok (true); while (nextCharIsValidCharName) readToCurrTok (); saveAndResetCurrentTok (TokenType.AttributeName); + + SkipWhiteSpaces (); + if (Peek () != '=') - throw new ParsingException (this, "Expecting: '='"); + throw new ParserException (currentLine, currentColumn, "Expecting: '='"); readAndResetCurrentTok (TokenType.Affectation, true); + SkipWhiteSpaces (); + char openAttVal = Peek (); if (openAttVal != '"' && openAttVal != '\'') - throw new ParsingException (this, "Expecting attribute value enclosed either in '\"' or in \"'\""); + throw new ParserException (currentLine, currentColumn, "Expecting attribute value enclosed either in '\"' or in \"'\""); readAndResetCurrentTok (TokenType.AttributeValueOpening, true); currentTok.Start = CurrentPosition; @@ -235,11 +251,16 @@ namespace Crow.Coding saveAndResetCurrentTok (TokenType.AttributeValue); if (Peek () != openAttVal) - throw new ParsingException (this, string.Format ("Expecting {0}", openAttVal)); + throw new ParserException (currentLine, currentColumn, string.Format ("Expecting {0}", openAttVal)); readAndResetCurrentTok (TokenType.AttributeValueClosing, true); break; + case States.Content: + currentTok.Start = CurrentPosition; + currentTok.Content = ReadLineUntil ("<"); + saveAndResetCurrentTok (TokenType.Content); + break; default: - throw new ParsingException (this, "unexpected char: " + Peek ()); + throw new ParserException (currentLine, currentColumn, "unexpected char: " + Peek ()); } break; } @@ -253,8 +274,7 @@ namespace Crow.Coding public override void SyntaxAnalysis () { - RootNode = new Node () { Name = "RootNode", Type="Root" }; - + initSyntaxAnalysis (); Node currentNode = RootNode; for (int i = 0; i < buffer.LineCount; i++) { @@ -268,21 +288,16 @@ namespace Crow.Coding switch ((XMLParser.TokenType)cl.Tokens [tokPtr].Type) { case TokenType.ElementStart: tokPtr++; - Node newElt = new Node () { Name = cl.Tokens [tokPtr].Content, StartLine = cl }; - currentNode.AddChild (newElt); - currentNode = newElt; - if (cl.SyntacticNode == null) - cl.SyntacticNode = newElt; + currentNode = addChildNode (currentNode, cl, tokPtr, "Element"); break; case TokenType.ElementEnd: tokPtr++; if (tokPtr < cl.Tokens.Count) { if ((XMLParser.TokenType)cl.Tokens [tokPtr].Type == TokenType.ElementName && - cl.Tokens [tokPtr].Content != currentNode.Name) - throw new ParsingException (this, "Closing tag mismatch"); + cl.Tokens [tokPtr].Content != currentNode.Name) + throw new ParserException (currentLine, currentColumn, "Closing tag mismatch"); } - currentNode.EndLine = cl; - currentNode = currentNode.Parent; + closeNodeAndGoUp (ref currentNode, cl, "Element"); break; case TokenType.ElementClosing: //currentNode = currentNode.Parent; diff --git a/Crow.Coding/src/Parsers2/Tokenizer.cs b/Crow.Coding/src/Parsers2/Tokenizer.cs new file mode 100644 index 0000000..bcda1ec --- /dev/null +++ b/Crow.Coding/src/Parsers2/Tokenizer.cs @@ -0,0 +1,67 @@ +// +// Tokenizer.cs +// +// Author: +// Jean-Philippe Bruyère +// +// Copyright (c) 2013-2017 Jean-Philippe Bruyère +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using Crow.Text; +using System.Collections.Generic; +using System.Text.RegularExpressions; + +namespace Crow.Coding2 +{ + public static class TokenType { + public const int Undefine = 0; + public const int WhiteSpace = 0; + } + public class Token { + public int ptr; + public int length; + } + + public class Tokenizer + { + #region Regular Expression for validity checks + public Regex rxValidChar = new Regex(@"\p{Lu}|\p{Ll}|\p{Lt}|\p{Lm}|\p{Lo}|\p{Nl}|\p{Mn}|\p{Mc}|\p{Nd}|\p{Pc}|\p{Cf}"); + public Regex rxNameStartChar = new Regex(@"_|\p{Lu}|\p{Ll}|\p{Lt}|\p{Lm}|\p{Lo}|\p{Nl}"); + public Regex rxNameChar = new Regex(@"\p{Lu}|\p{Ll}|\p{Lt}|\p{Lm}|\p{Lo}|\p{Nl}|\p{Mn}|\p{Mc}|\p{Nd}|\p{Pc}|\p{Cf}"); + public Regex rxNewLineChar = new Regex(@"\u000D|\u000A|\u0085|\u2028|\u2029"); + public Regex rxWhiteSpaceChar = new Regex(@"\p{Zs}|\u0009|\u000B|\u000C"); + public Regex rxDecimal = new Regex(@"[0-9]+"); + public Regex rxHexadecimal = new Regex(@"[0-9a-fA-F]+"); + #endregion + + public List Tokens; + + public Tokenizer (TextBuffer buffer) + { + } + + + public void Tokenize () { + + } + + } +} + diff --git a/src/SourceEditor.cs b/Crow.Coding/src/SourceEditor.cs similarity index 56% rename from src/SourceEditor.cs rename to Crow.Coding/src/SourceEditor.cs index 57c5757..e32efd9 100644 --- a/src/SourceEditor.cs +++ b/Crow.Coding/src/SourceEditor.cs @@ -1,66 +1,50 @@ -// -// ScrollingTextBox.cs +// Copyright (c) 2013-2020 Jean-Philippe Bruyère // -// Author: -// Jean-Philippe Bruyère -// -// Copyright (c) 2013-2017 Jean-Philippe Bruyère -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. +// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) using System; -using System.Xml.Serialization; using System.ComponentModel; -using System.Collections; -using Cairo; -using System.Text; +using Crow.Cairo; using System.Collections.Generic; -using System.Text.RegularExpressions; -using System.Linq; using System.Diagnostics; -using CrowEdit; +using Glfw; using System.IO; +using System.Threading; namespace Crow.Coding { /// /// Scrolling text box optimized for monospace fonts, for coding /// - public class SourceEditor : ScrollingObject - { + public class SourceEditor : ScrollingObject { #region CTOR public SourceEditor (): base() { - formatting.Add ((int)XMLParser.TokenType.AttributeName, new TextFormatting (Color.UnitedNationsBlue, Color.Transparent)); - formatting.Add ((int)XMLParser.TokenType.ElementName, new TextFormatting (Color.DarkBlue, Color.Transparent)); - formatting.Add ((int)XMLParser.TokenType.ElementStart, new TextFormatting (Color.Black, Color.Transparent)); - formatting.Add ((int)XMLParser.TokenType.ElementEnd, new TextFormatting (Color.Black, Color.Transparent)); - formatting.Add ((int)XMLParser.TokenType.ElementClosing, new TextFormatting (Color.Black, Color.Transparent)); - formatting.Add ((int)XMLParser.TokenType.Affectation, new TextFormatting (Color.Black, Color.Transparent)); - - formatting.Add ((int)XMLParser.TokenType.AttributeValueOpening, new TextFormatting (Color.Carmine, Color.Transparent)); - formatting.Add ((int)XMLParser.TokenType.AttributeValueClosing, new TextFormatting (Color.Carmine, Color.Transparent)); - formatting.Add ((int)XMLParser.TokenType.AttributeValue, new TextFormatting (Color.OrangeRed, Color.Transparent, false, true)); - formatting.Add ((int)XMLParser.TokenType.XMLDecl, new TextFormatting (Color.GreenCrayola, Color.Transparent)); - formatting.Add ((int)XMLParser.TokenType.BlockComment, new TextFormatting (Color.Gray, Color.Transparent, false, true)); + formatting.Add ((int)XMLParser.TokenType.AttributeName, new TextFormatting (Colors.DarkSlateGrey, Colors.Transparent)); + formatting.Add ((int)XMLParser.TokenType.ElementName, new TextFormatting (Colors.DarkBlue, Colors.Transparent)); + formatting.Add ((int)XMLParser.TokenType.ElementStart, new TextFormatting (Colors.Black, Colors.Transparent)); + formatting.Add ((int)XMLParser.TokenType.ElementEnd, new TextFormatting (Colors.Black, Colors.Transparent)); + formatting.Add ((int)XMLParser.TokenType.ElementClosing, new TextFormatting (Colors.Black, Colors.Transparent)); + + formatting.Add ((int)XMLParser.TokenType.AttributeValueOpening, new TextFormatting (Colors.Crimson, Colors.Transparent)); + formatting.Add ((int)XMLParser.TokenType.AttributeValueClosing, new TextFormatting (Colors.Crimson, Colors.Transparent)); + formatting.Add ((int)XMLParser.TokenType.AttributeValue, new TextFormatting (Colors.FireBrick, Colors.Transparent, false, true)); + formatting.Add ((int)XMLParser.TokenType.XMLDecl, new TextFormatting (Colors.ForestGreen, Colors.Transparent)); + formatting.Add ((int)XMLParser.TokenType.Content, new TextFormatting (Colors.DimGrey, Colors.Transparent, false, true)); + + formatting.Add ((int)BufferParser.TokenType.BlockComment, new TextFormatting (Colors.Grey, Colors.Transparent, false, true)); + formatting.Add ((int)BufferParser.TokenType.LineComment, new TextFormatting (Colors.Grey, Colors.Transparent, false, true)); + formatting.Add ((int)BufferParser.TokenType.OperatorOrPunctuation, new TextFormatting (Colors.Black, Colors.Transparent)); + formatting.Add ((int)BufferParser.TokenType.Keyword, new TextFormatting (Colors.Teal, Colors.Transparent)); + //formatting.Add ((int)BufferParser.TokenType.Keyword, new TextFormatting (Color.DarkCyan, Color.Transparent)); parsing.Add (".crow", "Crow.Coding.XMLParser"); + parsing.Add (".svg", "Crow.Coding.XMLParser"); + parsing.Add (".template", "Crow.Coding.XMLParser"); + parsing.Add (".csproj", "Crow.Coding.XMLParser"); + parsing.Add (".xml", "Crow.Coding.XMLParser"); + parsing.Add (".cs", "Crow.Coding.CSharpParser"); + parsing.Add (".style", "Crow.Coding.StyleParser"); buffer = new CodeBuffer (); buffer.LineUpadateEvent += Buffer_LineUpadateEvent; @@ -74,29 +58,44 @@ namespace Crow.Coding } #endregion + ReaderWriterLockSlim editorMutex = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion); + + string oldSource = ""; + //save requested position on error, and try it on next move + int requestedLine = 0, requestedCol = 0; + volatile bool isDirty = false; + const int leftMarginGap = 3;//gap between items in margin and text const int foldSize = 9;//folding rectangles size + int foldMargin = 9;// { get { return parser == null ? 0 : parser.SyntacticTreeMaxDepth * foldHSpace; }}//folding margin size #region private and protected fields bool foldingEnabled = true; - string filePath = "unamed.txt"; int leftMargin = 0; //margin used to display line numbers, folding errors,etc... int visibleLines = 1; int visibleColumns = 1; - CodeBuffer buffer; - Parser parser; - Color selBackground; - Color selForeground; -// int _currentCol; //0 based cursor position in string -// int _currentLine; + int firstPrintedLine = -1; + int printedCurrentLine = 0;//Index of the currentline in the PrintedLines array + string filePath; + CodeBuffer buffer; + BufferParser parser; + List PrintedLines;//list of lines visible in the Editor depending on scrolling and folding Dictionary formatting = new Dictionary(); Dictionary parsing = new Dictionary(); + Color selBackground; + Color selForeground; + int selStartCol; + int selEndCol; + protected Rectangle rText; protected FontExtents fe; protected TextExtents te; + + Point mouseLocalPos; + bool doubleClicked = false; #endregion void measureLeftMargin () { @@ -104,72 +103,83 @@ namespace Crow.Coding if (PrintLineNumbers) leftMargin += (int)Math.Ceiling((double)buffer.LineCount.ToString().Length * fe.MaxXAdvance) +6; if (foldingEnabled) - leftMargin += foldSize; + leftMargin += foldMargin; if (leftMargin > 0) - leftMargin += leftMarginGap; + leftMargin += leftMarginGap; updateVisibleColumns (); } void findLongestLineAndUpdateMaxScrollX() { buffer.FindLongestVisualLine (); - MaxScrollX = Math.Max (0, buffer.longestLineCharCount - visibleColumns); - Debug.WriteLine ("SourceEditor: Find Longest line and update maxscrollx: {0} visible cols:{1}", MaxScrollX, visibleColumns); + updateMaxScrollX (); +// Debug.WriteLine ("SourceEditor: Find Longest line and update maxscrollx: {0} visible cols:{1}", MaxScrollX, visibleColumns); } /// /// Updates visible line in widget, adapt max scroll y and updatePrintedLines /// void updateVisibleLines(){ - visibleLines = (int)Math.Floor ((double)ClientRectangle.Height / fe.Height); + visibleLines = (int)Math.Floor ((double)ClientRectangle.Height / (fe.Ascent+fe.Descent)); + NotifyValueChanged ("VisibleLines", visibleLines); updateMaxScrollY (); updatePrintedLines (); - System.Diagnostics.Debug.WriteLine ("update visible lines: " + visibleLines); - System.Diagnostics.Debug.WriteLine ("update MaxScrollY: " + MaxScrollY); + RegisterForGraphicUpdate (); +// System.Diagnostics.Debug.WriteLine ("update visible lines: " + visibleLines); +// System.Diagnostics.Debug.WriteLine ("update MaxScrollY: " + MaxScrollY); } void updateVisibleColumns(){ visibleColumns = (int)Math.Floor ((double)(ClientRectangle.Width - leftMargin)/ fe.MaxXAdvance); + NotifyValueChanged ("VisibleColumns", visibleColumns); + updateMaxScrollX (); +// System.Diagnostics.Debug.WriteLine ("update visible columns: {0} leftMargin:{1}",visibleColumns, leftMargin); +// System.Diagnostics.Debug.WriteLine ("update MaxScrollX: " + MaxScrollX); + } + void updateMaxScrollX () { MaxScrollX = Math.Max (0, buffer.longestLineCharCount - visibleColumns); - - System.Diagnostics.Debug.WriteLine ("update visible columns: {0} leftMargin:{1}",visibleColumns, leftMargin); - System.Diagnostics.Debug.WriteLine ("update MaxScrollX: " + MaxScrollX); + if (buffer.longestLineCharCount > 0) + NotifyValueChanged ("ChildWidthRatio", Slot.Width * visibleColumns / buffer.longestLineCharCount); } void updateMaxScrollY () { - if (parser == null || !foldingEnabled) + if (parser == null || !foldingEnabled) { MaxScrollY = Math.Max (0, buffer.LineCount - visibleLines); - else + if (buffer.UnfoldedLines > 0) + NotifyValueChanged ("ChildHeightRatio", Slot.Height * visibleLines / buffer.UnfoldedLines); + } else { MaxScrollY = Math.Max (0, buffer.UnfoldedLines - visibleLines); - } + if (buffer.UnfoldedLines > 0) + NotifyValueChanged ("ChildHeightRatio", Slot.Height * visibleLines / buffer.UnfoldedLines); + } + } + void updatePrintedLines () { + buffer.editMutex.EnterReadLock (); + editorMutex.EnterWriteLock (); - int firstPrintedLine = -1; - /// - /// list of lines visible in the Editor depending on scrolling and folding - /// - List PrintedLines; + PrintedLines = new List (); + int curL = 0; + int i = 0; - void updatePrintedLines () { - lock (buffer.EditMutex) { - PrintedLines = new List (); - int curL = 0; - int i = 0; - - while (curL < buffer.LineCount && i < ScrollY) { - if (buffer [curL].IsFolded) - curL = buffer.GetEndNodeIndex (curL); - curL++; - i++; - } + while (curL < buffer.LineCount && i < ScrollY) { + if (buffer [curL].IsFolded) + curL = buffer.GetEndNodeIndex (curL); + curL++; + i++; + } - firstPrintedLine = curL; - i = 0; - while (i < visibleLines && curL < buffer.LineCount) { - PrintedLines.Add (buffer [curL]); + firstPrintedLine = curL; + i = 0; + while (i < visibleLines && curL < buffer.LineCount) { + PrintedLines.Add (buffer [curL]); - if (buffer [curL].IsFolded) - curL = buffer.GetEndNodeIndex (curL); + if (buffer [curL].IsFolded) + curL = buffer.GetEndNodeIndex (curL); - curL++; - i++; - } + curL++; + i++; } - RegisterForGraphicUpdate (); + + buffer.editMutex.ExitReadLock (); + editorMutex.ExitWriteLock (); + } + void updateOnScreenCurLineFromBuffCurLine(){ + printedCurrentLine = PrintedLines.IndexOf (buffer.CurrentCodeLine); } void toogleFolding (int line) { if (parser == null || !foldingEnabled) @@ -177,15 +187,54 @@ namespace Crow.Coding buffer.ToogleFolding (line); } + #region Editor overrides + /*protected override void updateEditorFromProjFile () + { + Debug.WriteLine("\t\tSourceEditor updateEditorFromProjFile"); + + //buffer.editMutex.EnterWriteLock (); + loadSource (); + //buffer.editMutex.ExitWriteLock (); + + isDirty = false; + oldSource = projFile.Source; + CurrentLine = requestedLine; + CurrentColumn = requestedCol; + projFile.RegisteredEditors [this] = true; + } + protected override void updateProjFileFromEditor () + { + Debug.WriteLine("\t\tSourceEditor updateProjFileFromEditor"); + + buffer.editMutex.EnterWriteLock (); + string newsrc = buffer.FullText; + buffer.editMutex.ExitWriteLock (); + projFile.UpdateSource (this, newsrc); + } + protected override bool EditorIsDirty { + get { return isDirty; } + set { isDirty = value; } + } + protected override bool IsReady { + get { return projFile != null && buffer != null; } + }*/ + #endregion + #region Buffer events handlers void Buffer_BufferCleared (object sender, EventArgs e) { + editorMutex.EnterWriteLock (); + buffer.longestLineCharCount = 0; buffer.longestLineIdx = 0; measureLeftMargin (); MaxScrollX = MaxScrollY = 0; PrintedLines = null; RegisterForGraphicUpdate (); + notifyPositionChanged (); + isDirty = true; + + editorMutex.ExitWriteLock (); } void Buffer_LineAdditionEvent (object sender, CodeBufferEventArgs e) { @@ -199,16 +248,19 @@ namespace Crow.Coding buffer.longestLineIdx++; if (parser == null) continue; - parser.tryParseBufferLine (e.LineStart + i); + parser.TryParseBufferLine (e.LineStart + i); } - measureLeftMargin (); if (parser != null) parser.reparseSource (); + measureLeftMargin (); + updatePrintedLines (); updateMaxScrollY (); RegisterForGraphicUpdate (); + notifyPositionChanged (); + isDirty = true; } void Buffer_LineRemoveEvent (object sender, CodeBufferEventArgs e) { @@ -225,6 +277,8 @@ namespace Crow.Coding updatePrintedLines (); updateMaxScrollY (); RegisterForGraphicUpdate (); + notifyPositionChanged (); + isDirty = true; } void Buffer_LineUpadateEvent (object sender, CodeBufferEventArgs e) { @@ -241,11 +295,24 @@ namespace Crow.Coding } if (trigFindLongestLine) findLongestLineAndUpdateMaxScrollX (); + RegisterForGraphicUpdate (); + notifyPositionChanged (); + isDirty = true; } void Buffer_PositionChanged (object sender, EventArgs e) { + //Console.WriteLine ("Position changes: ({0},{1})", buffer.CurrentLine, buffer.CurrentColumn); + int cc = buffer.CurrentTabulatedColumn; + + if (cc > visibleColumns + ScrollX) { + ScrollX = cc - visibleColumns; + } else if (cc < ScrollX) + ScrollX = cc; + + RegisterForGraphicUpdate (); updateOnScreenCurLineFromBuffCurLine (); + notifyPositionChanged (); } void Buffer_SelectionChanged (object sender, EventArgs e) @@ -255,74 +322,67 @@ namespace Crow.Coding void Buffer_FoldingEvent (object sender, CodeBufferEventArgs e) { updatePrintedLines (); + updateOnScreenCurLineFromBuffCurLine (); updateMaxScrollY (); RegisterForGraphicUpdate (); } #endregion - Parser getParserFromExt (string extension) { - if (string.IsNullOrEmpty(extension)) - return null; - if (!parsing.ContainsKey(extension)) - return null; - Type parserType = Type.GetType (parsing [extension]); - if (parserType == null) - return null; - return (Parser)Activator.CreateInstance (parserType, buffer ); + void notifyPositionChanged (){ + try { + NotifyValueChanged ("CurrentLine", buffer.CurrentLine+1); + NotifyValueChanged ("CurrentColumn", buffer.CurrentColumn+1); + NotifyValueChanged ("CurrentLineHasError", CurrentLineHasError); + NotifyValueChanged ("CurrentLineError", CurrentLineError); + } catch (Exception ex) { + Console.WriteLine (ex.ToString ()); + } } - + #region Public Crow Properties - [XmlAttributeAttribute] + public int CurrentLine{ + get { return buffer == null ? 0 : buffer.CurrentLine+1; } + set { + try { + int l = value - 1; + if (l == buffer.CurrentLine) + return; + buffer.CurrentLine = l; + l = buffer.CurrentLine; //reaffect from buffer where bound check is made + if ((bool)buffer [l]?.IsFolded) + buffer.ToogleFolding (l);//unfold current line + } catch (Exception ex) { + requestedLine = value - 1; + Console.WriteLine ("Error cur column: " + ex); + } + } + } + public int CurrentColumn{ + get { return buffer == null ? 0 : buffer.CurrentColumn+1; } + set { + try { + if (value - 1 == buffer.CurrentColumn) + return; + buffer.CurrentColumn = value - 1; + } catch (Exception ex) { + requestedCol = value - 1; + Console.WriteLine ("Error cur column: " + ex.ToString ()); + } + } + } public bool PrintLineNumbers { - get { return Configuration.Get ("PrintLineNumbers"); - } - set - { + get { return Configuration.Global.Get ("PrintLineNumbers"); } + set { if (PrintLineNumbers == value) return; - Configuration.Set ("PrintLineNumbers", value); + Configuration.Global.Set ("PrintLineNumbers", value); NotifyValueChanged ("PrintLineNumbers", PrintLineNumbers); measureLeftMargin (); RegisterForGraphicUpdate (); } } - [XmlAttributeAttribute] - public string FilePath - { - get { - return buffer == null ? "" : buffer.FullText; - } - set - { - if (filePath == value) - return; - - filePath = value; - NotifyValueChanged ("FilePath", filePath); - - if (!File.Exists (filePath)) - return; - - parser = getParserFromExt (System.IO.Path.GetExtension (filePath)); - - try { - using (StreamReader sr = new StreamReader (filePath)) { - string txt = sr.ReadToEnd (); - buffer.Load (txt); - } - } catch (Exception ex) { - Debug.WriteLine (ex.ToString ()); - } - - updateMaxScrollY (); - MaxScrollX = Math.Max (0, buffer.longestLineCharCount - visibleColumns); - updatePrintedLines (); - - RegisterForGraphicUpdate (); - } - } - [XmlAttributeAttribute][DefaultValue("BlueGray")] + [DefaultValue("SteelBlue")] public virtual Color SelectionBackground { get { return selBackground; } set { @@ -333,7 +393,7 @@ namespace Crow.Coding RegisterForRedraw (); } } - [XmlAttributeAttribute][DefaultValue("White")] + [DefaultValue("White")] public virtual Color SelectionForeground { get { return selForeground; } set { @@ -344,102 +404,6 @@ namespace Crow.Coding RegisterForRedraw (); } } -// [XmlAttributeAttribute][DefaultValue(0)] -// public int CurrentColumn{ -// get { return _currentCol; } -//// set { -//// if (value == _currentCol) -//// return; -//// if (value < 0) -//// _currentCol = 0; -//// else if (value > buffer[_currentLine].PrintableLength) -//// _currentCol = buffer[_currentLine].PrintableLength; -//// else -//// _currentCol = value; -//// -//// buffer.SetBufferPos (CurrentPosition); -//// -//// if (_currentCol < ScrollX) -//// ScrollX = _currentCol; -//// else if (_currentCol >= ScrollX + visibleColumns) -//// ScrollX = _currentCol - visibleColumns + 1; -//// -//// NotifyValueChanged ("CurrentColumn", _currentCol); -//// } -// } -// [XmlAttributeAttribute][DefaultValue(0)] -// public int CurrentLine{ -// get { return _currentLine; } -//// set { -//// if (value == _currentLine) -//// return; -//// if (value >= buffer.LineCount) -//// _currentLine = buffer.LineCount-1; -//// else if (value < 0) -//// _currentLine = 0; -//// else -//// _currentLine = value; -//// -//// if (_currentCol > buffer[_currentLine].PrintableLength) -//// CurrentColumn = buffer[_currentLine].PrintableLength;//buffer.setBufferPos is called inside -//// else -//// buffer.SetBufferPos (CurrentPosition); -//// -////// if (_currentLine < ScrollY) -////// ScrollY = _currentLine; -////// else if (_currentLine >= ScrollY + visibleLines) -////// ScrollY = _currentLine - visibleLines + 1; -//// -//// NotifyValueChanged ("CurrentLine", _currentLine); -//// } -// } -// /// -// /// Current position is in the printed coord system, tabulation chars are replaced with 4 spaces, -// /// while in the buffer, the position holds tabulations as single chars -// /// -// /// The current position. -// [XmlIgnore]public Point CurrentPosition { -// get { return new Point(CurrentColumn, CurrentLine); } -// set { -// _currentCol = value.X; -// _currentLine = value.Y; -// -// if (_currentCol < ScrollX) -// ScrollX = _currentCol; -// else if (_currentCol >= ScrollX + visibleColumns) -// ScrollX = _currentCol - visibleColumns + 1; -//// -//// if (_currentLine < ScrollY) -//// ScrollY = _currentLine; -//// else if (_currentLine >= ScrollY + visibleLines) -//// ScrollY = _currentLine - visibleLines + 1; -// -// NotifyValueChanged ("CurrentColumn", _currentCol); -// NotifyValueChanged ("CurrentLine", _currentLine); -// } -// } - -// [XmlIgnore]public string SelectedText -// { -// get { -// if (!selectionIsEmpty) -// buffer.SetSelection (selectionStart, selectionEnd); -// return buffer.SelectedText; -// } -// } - - #endregion - - - void updateOnScreenCurLineFromBuffCurLine(){ - printedCurrentLine = PrintedLines.IndexOf (buffer.CurrentCodeLine); - } - -// void setCurrentLineFromBuffer () { -// _currentLine = buffer.CurrentLine; -// NotifyValueChanged ("CurrentLine", _currentLine); -// } - public override int ScrollY { get { return base.ScrollY; @@ -449,14 +413,60 @@ namespace Crow.Coding return; base.ScrollY = value; updatePrintedLines (); + updateOnScreenCurLineFromBuffCurLine (); + RegisterForGraphicUpdate (); + } + } + public ParserException CurrentLineError { + get { return buffer?.CurrentCodeLine?.exception; } + } + public bool CurrentLineHasError { + get { return buffer == null ? false : buffer.CurrentCodeLine == null ? false : + buffer.CurrentCodeLine.exception != null; } + } + public string FilePath { + get => filePath; + set { + if (filePath == value) + return; + filePath = value; + if (!string.IsNullOrEmpty (filePath)) { + parser = getParserFromExt (System.IO.Path.GetExtension (filePath)); + loadSource(); + } } } + #endregion + BufferParser getParserFromExt (string extension) { + if (string.IsNullOrEmpty(extension)) + return null; + if (!parsing.ContainsKey(extension)) + return null; + Type parserType = Type.GetType (parsing [extension]); + if (parserType == null) + return null; + return (BufferParser)Activator.CreateInstance (parserType, buffer ); + } + void loadSource () { + + try { + using (StreamReader sr = new StreamReader (filePath)) { + if (parser == null) + buffer.Load (sr.ReadToEnd()); + else//parser may have special linebrk rules + buffer.Load (sr.ReadToEnd (), parser.LineBrkRegex); + } + } catch (Exception ex) { + Debug.WriteLine (ex.ToString ()); + } - /// - /// Index of the currentline in the PrintedLines array - /// - int printedCurrentLine = 0; + updateMaxScrollY (); + MaxScrollX = Math.Max (0, buffer.longestLineCharCount - visibleColumns); + updatePrintedLines (); + + RegisterForGraphicUpdate (); + } /// /// Current editor line, when set, update buffer.CurrentLine @@ -474,13 +484,13 @@ namespace Crow.Coding printedCurrentLine = visibleLines - 1; }else printedCurrentLine = value; - Debug.WriteLine ("printed current line:" + printedCurrentLine.ToString ()); + //Debug.WriteLine ("printed current line:" + printedCurrentLine.ToString ()); //update position in buffer buffer.CurrentLine = buffer.IndexOf (PrintedLines[printedCurrentLine]); } } int getTabulatedColumn (int col, int line) { - return buffer [line].Content.Substring (0, col).Replace ("\t", new String (' ', Interface.TabSize)).Length; + return buffer [line].Content.Substring (0, col).Replace ("\t", new String (' ', Interface.TAB_SIZE)).Length; } int getTabulatedColumn (Point pos) { return getTabulatedColumn (pos.X,pos.Y); @@ -513,32 +523,34 @@ namespace Crow.Coding buffer.CurrentColumn++; return true; } + #region Drawing void drawLine(Context gr, Rectangle cb, int i) { CodeLine cl = PrintedLines[i]; int lineIndex = buffer.IndexOf(cl); - double y = cb.Y + fe.Height * i, x = cb.X; + double y = cb.Y + (fe.Ascent+fe.Descent) * i, x = cb.X; //Draw line numbering - Color mgFg = Color.Gray; - Color mgBg = Color.White; + Color mgFg = Colors.Jet; + Color mgBg = Colors.Grey; if (PrintLineNumbers){ - Rectangle mgR = new Rectangle ((int)x, (int)y, leftMargin - leftMarginGap, (int)Math.Ceiling(fe.Height)); + Rectangle mgR = new Rectangle ((int)x, (int)y, leftMargin - leftMarginGap, (int)Math.Ceiling((fe.Ascent+fe.Descent))); if (cl.exception != null) { - mgBg = Color.Red; + mgBg = Colors.Red; if (buffer.CurrentLine == lineIndex) - mgFg = Color.White; + mgFg = Colors.White; else - mgFg = Color.LightGray; - }else if (buffer.CurrentLine == lineIndex) { - mgFg = Color.Black; + mgFg = Colors.LightGrey; + }else if (buffer.CurrentLine == lineIndex && HasFocus) { + mgFg = Colors.Black; + mgBg = Colors.DarkGrey; } string strLN = (lineIndex+1).ToString (); - gr.SetSourceColor (mgBg); + gr.SetSource (mgBg); gr.Rectangle (mgR); gr.Fill(); - gr.SetSourceColor (mgFg); + gr.SetSource (mgFg); gr.MoveTo (cb.X + (int)(gr.TextExtents (buffer.LineCount.ToString()).Width - gr.TextExtents (strLN).Width), y + fe.Ascent); gr.ShowText (strLN); @@ -548,23 +560,64 @@ namespace Crow.Coding //draw folding if (foldingEnabled){ - if (cl.IsFoldable) { - if (cl.SyntacticNode.StartLine != cl.SyntacticNode.EndLine) { - gr.SetSourceColor (Color.Black); - Rectangle rFld = new Rectangle (cb.X + leftMargin - leftMarginGap - foldSize, (int)(y + fe.Height / 2.0 - foldSize / 2.0), foldSize, foldSize); - gr.Rectangle (rFld, 1.0); - if (cl.IsFolded) { - gr.MoveTo (rFld.Center.X + 0.5, rFld.Y + 2); - gr.LineTo (rFld.Center.X + 0.5, rFld.Bottom - 2); - } - gr.MoveTo (rFld.Left + 2, rFld.Center.Y + 0.5); - gr.LineTo (rFld.Right - 2, rFld.Center.Y + 0.5); - gr.Stroke (); + + Rectangle rFld = new Rectangle (cb.X + leftMargin - leftMarginGap - foldMargin, + (int)(y + (fe.Ascent + fe.Descent) / 2.0 - foldSize / 2.0), foldSize, foldSize); + + gr.SetSource (Colors.Black); + gr.LineWidth = 1.0; + + int level = 0; + bool closingNode = false; + + if (currentNode != null) { + if (cl == currentNode.EndLine) { + currentNode = currentNode.Parent; + closingNode = true; } + if (currentNode != null) + level = currentNode.Level - 1; } + + /*for (int l = 0; l < level; l++) { + gr.MoveTo (rFld.Center.X + 0.5, y); + gr.LineTo (rFld.Center.X + 0.5, y + fe.Ascent + fe.Descent); + rFld.Left += foldHSpace; + }*/ + if (level > 0) { + gr.MoveTo (rFld.Center.X + 0.5, y); + gr.LineTo (rFld.Center.X + 0.5, y + fe.Ascent + fe.Descent); + } + if (closingNode) { + gr.MoveTo (rFld.Center.X + 0.5, y); + gr.LineTo (rFld.Center.X + 0.5, y + fe.Ascent / 2 + 0.5); + gr.LineTo (rFld.Center.X + 0.5 + foldSize / 2, y + fe.Ascent / 2 + 0.5); + closingNode = false; + } + gr.SetDash (new double[]{ 1.5 },0.0); + gr.SetSource (Colors.Grey); + gr.Stroke (); + gr.SetDash (new double[]{}, 0.0); + + if (cl.IsFoldable) { + gr.Rectangle (rFld); + gr.SetSource (Colors.White); + gr.Fill(); + gr.SetSource (Colors.Black); + gr.Rectangle (rFld, 1.0); + if (cl.IsFolded) { + gr.MoveTo (rFld.Center.X + 0.5, rFld.Y + 2); + gr.LineTo (rFld.Center.X + 0.5, rFld.Bottom - 2); + }else + currentNode = cl.SyntacticNode; + + gr.MoveTo (rFld.Left + 2, rFld.Center.Y + 0.5); + gr.LineTo (rFld.Right - 2, rFld.Center.Y + 0.5); + gr.Stroke (); + } } - gr.SetSourceColor (Foreground); + gr.SetSource (Foreground); x += leftMargin; if (cl.Tokens == null) @@ -572,6 +625,7 @@ namespace Crow.Coding else drawParsedCodeLine (gr, x, y, i, lineIndex); } + Node currentNode = null; // void drawParsed(Context gr){ // if (PrintedLines == null) // return; @@ -596,8 +650,8 @@ namespace Crow.Coding // else if (HasFocus){ // gr.LineWidth = 1.0; // double cursorX = + leftMargin + cb.X + (CurrentColumn - ScrollX) * fe.MaxXAdvance; -// gr.MoveTo (0.5 + cursorX, cb.Y + printedCurrentLine * fe.Height); -// gr.LineTo (0.5 + cursorX, cb.Y + (printedCurrentLine + 1) * fe.Height); +// gr.MoveTo (0.5 + cursorX, cb.Y + printedCurrentLine * (fe.Ascent+fe.Descent)); +// gr.LineTo (0.5 + cursorX, cb.Y + (printedCurrentLine + 1) * (fe.Ascent+fe.Descent)); // gr.Stroke(); // } // #endregion @@ -633,12 +687,12 @@ namespace Crow.Coding gr.Save (); gr.Operator = Operator.Source; - gr.Rectangle (rLineX, rLineY, rLineW, fe.Height); - gr.SetSourceColor (SelectionBackground); + gr.Rectangle (rLineX, rLineY, rLineW, (fe.Ascent+fe.Descent)); + gr.SetSource (SelectionBackground); gr.FillPreserve (); gr.Clip (); gr.Operator = Operator.Over; - gr.SetSourceColor (SelectionForeground); + gr.SetSource (SelectionForeground); gr.MoveTo (x, y + fe.Ascent); gr.ShowText (lstr); gr.Fill (); @@ -677,7 +731,7 @@ namespace Crow.Coding } gr.SelectFontFace (Font.Name, fts, ftw); - gr.SetSourceColor (fg); + gr.SetSource (fg); gr.MoveTo (x, y + fe.Ascent); gr.ShowText (lstr); @@ -701,12 +755,12 @@ namespace Crow.Coding gr.Save (); gr.Operator = Operator.Source; - gr.Rectangle (rLineX, rLineY, rLineW, fe.Height); - gr.SetSourceColor (selbg); + gr.Rectangle (rLineX, rLineY, rLineW, (fe.Ascent+fe.Descent)); + gr.SetSource (selbg); gr.FillPreserve (); gr.Clip (); gr.Operator = Operator.Over; - gr.SetSourceColor (selfg); + gr.SetSource (selfg); gr.MoveTo (x, y + fe.Ascent); gr.ShowText (lstr); gr.Fill (); @@ -724,23 +778,20 @@ namespace Crow.Coding get { return base.Font; } set { base.Font = value; + using (Context gr = new Context (IFace.surf)) { + gr.SelectFontFace (Font.Name, Font.Slant, Font.Wheight); + gr.SetFontSize (Font.Size); - using (ImageSurface img = new ImageSurface (Format.Argb32, 1, 1)) { - using (Context gr = new Context (img)) { - gr.SelectFontFace (Font.Name, Font.Slant, Font.Wheight); - gr.SetFontSize (Font.Size); - - fe = gr.FontExtents; - } - } + fe = gr.FontExtents; + } MaxScrollY = 0; RegisterForGraphicUpdate (); } } - protected override int measureRawSize(LayoutingType lt) + public override int measureRawSize(LayoutingType lt) { if (lt == LayoutingType.Height) - return (int)Math.Ceiling(fe.Height * buffer.LineCount) + Margin * 2; + return (int)Math.Ceiling((fe.Ascent+fe.Descent) * buffer.LineCount) + Margin * 2; return (int)(fe.MaxXAdvance * buffer.longestLineCharCount) + Margin * 2 + leftMargin; } @@ -754,16 +805,8 @@ namespace Crow.Coding updateVisibleColumns (); } - int selStartCol; - int selEndCol; - protected override void onDraw (Context gr) { -// if (!System.Threading.Monitor.TryEnter (buffer.EditMutex)) { -// RegisterForGraphicUpdate (); -// return; -// } - base.onDraw (gr); gr.SelectFontFace (Font.Name, Font.Slant, Font.Wheight); @@ -775,69 +818,100 @@ namespace Crow.Coding Foreground.SetAsSource (gr); - lock (buffer.EditMutex) { - #region draw text cursor - if (buffer.SelectionInProgress){ - selStartCol = getTabulatedColumn (buffer.SelectionStart); - selEndCol = getTabulatedColumn (buffer.SelectionEnd); - }else if (HasFocus){ - gr.LineWidth = 1.0; - double cursorX = cb.X + (getTabulatedColumn(buffer.CurrentPosition) - ScrollX) * fe.MaxXAdvance + leftMargin; - gr.MoveTo (0.5 + cursorX, cb.Y + (printedCurrentLine) * fe.Height); - gr.LineTo (0.5 + cursorX, cb.Y + (printedCurrentLine + 1) * fe.Height); - gr.Stroke(); - } - #endregion - - if (PrintedLines != null) { - for (int i = 0; i < visibleLines; i++) { - if (i + ScrollY >= buffer.UnfoldedLines)//TODO:need optimize + buffer.editMutex.EnterReadLock (); + editorMutex.EnterReadLock (); + + #region draw text cursor + if (buffer.SelectionInProgress){ + selStartCol = getTabulatedColumn (buffer.SelectionStart); + selEndCol = getTabulatedColumn (buffer.SelectionEnd); + }else if (HasFocus && printedCurrentLine >= 0){ + gr.LineWidth = 1.0; + double cursorX = cb.X + (getTabulatedColumn(buffer.CurrentPosition) - ScrollX) * fe.MaxXAdvance + leftMargin; + gr.MoveTo (0.5 + cursorX, cb.Y + (printedCurrentLine) * (fe.Ascent+fe.Descent)); + gr.LineTo (0.5 + cursorX, cb.Y + (printedCurrentLine + 1) * (fe.Ascent+fe.Descent)); + gr.Stroke(); + } + #endregion + + if (PrintedLines?.Count > 0) { + int unfoldedLines = buffer.UnfoldedLines; + currentNode = null; + CodeLine cl = PrintedLines[0]; + int idx0 = buffer.IndexOf(cl); + int li = idx0-1; + while (li >= 0) { + if (buffer [li].IsFoldable && !buffer [li].IsFolded) { + if (buffer.IndexOf(buffer [li].SyntacticNode.EndLine) > idx0){ + currentNode = buffer [li].SyntacticNode; break; - drawLine (gr, cb, i); + } } + li--; + } + + for (int i = 0; i < visibleLines; i++) { + if (i + ScrollY >= unfoldedLines)//TODO:need optimize + break; + drawLine (gr, cb, i); } } - //System.Threading.Monitor.Exit (buffer.EditMutex); + + editorMutex.ExitReadLock (); + + buffer.editMutex.ExitReadLock (); + } #endregion #region Mouse handling - Point mouseLocalPos; - bool doubleClicked = false; - void updateCurrentPos(){ -// if (mouseLocalPos.X < 0) -// CurrentColumn--; -// else - PrintedCurrentLine = (int)Math.Max (0, Math.Floor (mouseLocalPos.Y / fe.Height)); + int hoverLine = -1; + public int HoverLine { + get { return hoverLine; } + set { + if (hoverLine == value) + return; + hoverLine = value; + NotifyValueChanged ("HoverLine", hoverLine); + NotifyValueChanged ("HoverError", buffer [hoverLine].exception); + } + } + void updateHoverLine () { + if (PrintedLines.Count > 0) { + int hvl = (int)Math.Max (0, Math.Floor (mouseLocalPos.Y / (fe.Ascent + fe.Descent))); + hvl = Math.Min (PrintedLines.Count - 1, hvl); + HoverLine = buffer.IndexOf (PrintedLines [hvl]); + } else + HoverLine = 0; + } + void updateCurrentPosFromMouseLocalPos(){ + PrintedCurrentLine = (int)Math.Max (0, Math.Floor (mouseLocalPos.Y / (fe.Ascent+fe.Descent))); int curVisualCol = ScrollX + (int)Math.Round ((mouseLocalPos.X - leftMargin) / fe.MaxXAdvance); int i = 0; int buffCol = 0; while (i < curVisualCol && buffCol < buffer.CurrentCodeLine.Length) { if (buffer.CurrentCodeLine[buffCol] == '\t') - i += Interface.TabSize; + i += Interface.TAB_SIZE; else i++; buffCol++; } buffer.CurrentColumn = buffCol; - -// if (mouseLocalPos.Y < 0) -// ScrollY--; } public override void onMouseEnter (object sender, MouseMoveEventArgs e) { base.onMouseEnter (sender, e); if (e.X - ScreenCoordinates(Slot).X < leftMargin + ClientRectangle.X) - CurrentInterface.MouseCursor = XCursor.Default; + IFace.MouseCursor = MouseCursor.arrow; else - CurrentInterface.MouseCursor = XCursor.Text; + IFace.MouseCursor = MouseCursor.ibeam; } public override void onMouseLeave (object sender, MouseMoveEventArgs e) { base.onMouseLeave (sender, e); - CurrentInterface.MouseCursor = XCursor.Default; + IFace.MouseCursor = MouseCursor.arrow; } public override void onMouseMove (object sender, MouseMoveEventArgs e) { @@ -845,11 +919,13 @@ namespace Crow.Coding mouseLocalPos = e.Position - ScreenCoordinates(Slot).TopLeft - ClientRectangle.TopLeft; - if (!e.Mouse.IsButtonDown (MouseButton.Left)) { + updateHoverLine (); + + if (!IFace.IsDown (MouseButton.Left)) { if (mouseLocalPos.X < leftMargin) - CurrentInterface.MouseCursor = XCursor.Default; + IFace.MouseCursor = MouseCursor.arrow; else - CurrentInterface.MouseCursor = XCursor.Text; + IFace.MouseCursor = MouseCursor.ibeam; return; } @@ -857,7 +933,7 @@ namespace Crow.Coding return; //mouse is down - updateCurrentPos(); + updateCurrentPosFromMouseLocalPos(); buffer.SetSelEndPos (); } public override void onMouseDown (object sender, MouseButtonEventArgs e) @@ -874,11 +950,12 @@ namespace Crow.Coding } if (mouseLocalPos.X < leftMargin) { - toogleFolding (buffer.IndexOf (PrintedLines [(int)Math.Max (0, Math.Floor (mouseLocalPos.Y / fe.Height))])); + toogleFolding (hoverLine); + //toogleFolding (buffer.IndexOf (PrintedLines [(int)Math.Max (0, Math.Floor (mouseLocalPos.Y / (fe.Ascent+fe.Descent)))])); return; } - updateCurrentPos (); + updateCurrentPosFromMouseLocalPos (); buffer.SetSelStartPos (); } public override void onMouseUp (object sender, MouseButtonEventArgs e) @@ -899,7 +976,14 @@ namespace Crow.Coding buffer.GotoWordEnd (); buffer.SetSelEndPos (); } - + public void MakeSelection (int lineStart, int colStart, int lineEnd, int colEnd) { + buffer.CurrentLine = lineStart; + buffer.CurrentColumn = colStart; + buffer.SetSelStartPos (); + buffer.CurrentLine = lineEnd; + buffer.CurrentColumn = colEnd; + buffer.SetSelEndPos (); + } public override void onMouseWheel (object sender, MouseWheelEventArgs e) { base.onMouseWheel (sender, e); @@ -907,24 +991,41 @@ namespace Crow.Coding #endregion #region Keyboard handling - public override void onKeyDown (object sender, KeyboardKeyEventArgs e) + public override void onKeyDown (object sender, KeyEventArgs e) { //base.onKeyDown (sender, e); Key key = e.Key; - + /* + if (IFace.Ctrl) { + switch (key) { + case Key.S: + projFile.Save (); + break; + case Key.Z: + editorMutex.EnterWriteLock (); + if (IFace.Shift) + projFile.Redo (null); + else + projFile.Undo (null); + editorMutex.ExitWriteLock (); + break; + default: + Console.WriteLine (""); + break; + } + } + */ switch (key) { - case Key.Back: + case Key.Backspace: buffer.DeleteChar (); break; - case Key.Clear: - break; case Key.Delete: if (buffer.SelectionIsEmpty) MoveRight (); - else if (e.Shift) - CurrentInterface.Clipboard = buffer.SelectedText; + else if (IFace.Shift) + IFace.Clipboard = buffer.SelectedText; buffer.DeleteChar (); break; case Key.Enter: @@ -937,46 +1038,46 @@ namespace Crow.Coding buffer.ResetSelection (); break; case Key.Home: - if (e.Shift) { + if (IFace.Shift) { if (buffer.SelectionIsEmpty) buffer.SetSelStartPos (); - if (e.Control) + if (IFace.Ctrl) buffer.CurrentLine = 0; buffer.CurrentColumn = 0; buffer.SetSelEndPos (); break; } buffer.ResetSelection (); - if (e.Control) + if (IFace.Ctrl) buffer.CurrentLine = 0; buffer.CurrentColumn = 0; break; case Key.End: - if (e.Shift) { + if (IFace.Shift) { if (buffer.SelectionIsEmpty) buffer.SetSelStartPos (); - if (e.Control) + if (IFace.Ctrl) buffer.CurrentLine = int.MaxValue; buffer.CurrentColumn = int.MaxValue; buffer.SetSelEndPos (); break; } buffer.ResetSelection (); - if (e.Control) + if (IFace.Ctrl) buffer.CurrentLine = int.MaxValue; buffer.CurrentColumn = int.MaxValue; break; case Key.Insert: - if (e.Shift) - buffer.Insert (CurrentInterface.Clipboard); - else if (e.Control && !buffer.SelectionIsEmpty) - CurrentInterface.Clipboard = buffer.SelectedText; + if (IFace.Shift) + buffer.Insert (IFace.Clipboard); + else if (IFace.Ctrl && !buffer.SelectionIsEmpty) + IFace.Clipboard = buffer.SelectedText; break; case Key.Left: - if (e.Shift) { + if (IFace.Shift) { if (buffer.SelectionIsEmpty) buffer.SetSelStartPos (); - if (e.Control) + if (IFace.Ctrl) buffer.GotoWordStart (); else MoveLeft (); @@ -984,16 +1085,16 @@ namespace Crow.Coding break; } buffer.ResetSelection (); - if (e.Control) + if (IFace.Ctrl) buffer.GotoWordStart (); else MoveLeft(); break; case Key.Right: - if (e.Shift) { + if (IFace.Shift) { if (buffer.SelectionIsEmpty) buffer.SetSelStartPos (); - if (e.Control) + if (IFace.Ctrl) buffer.GotoWordEnd (); else MoveRight (); @@ -1001,13 +1102,13 @@ namespace Crow.Coding break; } buffer.ResetSelection (); - if (e.Control) + if (IFace.Ctrl) buffer.GotoWordEnd (); else MoveRight (); break; case Key.Up: - if (e.Shift) { + if (IFace.Shift) { if (buffer.SelectionIsEmpty) buffer.SetSelStartPos (); PrintedCurrentLine--; @@ -1018,7 +1119,7 @@ namespace Crow.Coding PrintedCurrentLine--; break; case Key.Down: - if (e.Shift) { + if (IFace.Shift) { if (buffer.SelectionIsEmpty) buffer.SetSelStartPos (); PrintedCurrentLine++; @@ -1030,10 +1131,8 @@ namespace Crow.Coding break; case Key.Menu: break; - case Key.NumLock: - break; case Key.PageDown: - if (e.Shift) { + if (IFace.Shift) { if (buffer.SelectionIsEmpty) buffer.SetSelStartPos (); PrintedCurrentLine += visibleLines; @@ -1044,7 +1143,7 @@ namespace Crow.Coding PrintedCurrentLine += visibleLines; break; case Key.PageUp: - if (e.Shift) { + if (IFace.Shift) { if (buffer.SelectionIsEmpty) buffer.SetSelStartPos (); PrintedCurrentLine -= visibleLines; @@ -1054,15 +1153,30 @@ namespace Crow.Coding buffer.ResetSelection (); PrintedCurrentLine -= visibleLines; break; - case Key.RWin: - break; case Key.Tab: - buffer.Insert ("\t"); + if (IFace.Shift) { + if (buffer.SelectionIsEmpty || + (buffer.SelectionStart.Y == buffer.SelectionEnd.Y)) { + //TODO + break; + } + for (int i = buffer.SelectionStart.Y; i <= buffer.SelectionEnd.Y; i++) + buffer.RemoveLeadingTab (i); + buffer.SetSelectionOnFullLines (); + } else { + if (buffer.SelectionIsEmpty || + (buffer.SelectionStart.Y == buffer.SelectionEnd.Y)) { + buffer.Insert ("\t"); + break; + } + for (int i = buffer.SelectionStart.Y; i <= buffer.SelectionEnd.Y; i++) { + buffer.UpdateLine (i, "\t" + buffer [i].Content); + } + } + break; case Key.F8: toogleFolding (buffer.CurrentLine); -// if (parser != null) -// reparseSource (); break; default: break; @@ -1075,8 +1189,6 @@ namespace Crow.Coding buffer.Insert (e.KeyChar.ToString()); buffer.ResetSelection (); - - //RegisterForGraphicUpdate(); } #endregion } diff --git a/Crow.Coding/ui/CategoryExp.template b/Crow.Coding/ui/CategoryExp.template new file mode 100755 index 0000000..f546492 --- /dev/null +++ b/Crow.Coding/ui/CategoryExp.template @@ -0,0 +1,21 @@ + + + + + \ No newline at end of file diff --git a/Crow.Coding/ui/ContextMenu.template b/Crow.Coding/ui/ContextMenu.template new file mode 100644 index 0000000..38e6b7b --- /dev/null +++ b/Crow.Coding/ui/ContextMenu.template @@ -0,0 +1,42 @@ + + + + + + + + + + diff --git a/Crow.Coding/ui/IDE.style b/Crow.Coding/ui/IDE.style new file mode 100644 index 0000000..7fbe631 --- /dev/null +++ b/Crow.Coding/ui/IDE.style @@ -0,0 +1,29 @@ +icon { + Width="14"; + Height="14"; +} +MemberViewLabel { + Margin="1"; + Height="Fit"; + Width="50%"; + Background="White"; +} +MemberViewHStack { + Focusable="true"; + Height="Fit"; + Spacing="1"; + MouseEnter="{Background=SteelBlue}"; + MouseLeave="{Background=Transparent}"; +} + +IcoBut { + Template = "#Crow.Coding.ui.IcoBut.template"; + MinimumSize = "10,10"; + Width = "8"; + Height = "14"; + Background = "White"; +} + +MenuItem { + Template = "#Crow.Coding.ui.MenuItem.template"; +} \ No newline at end of file diff --git a/Crow.Coding/ui/IcoBut.template b/Crow.Coding/ui/IcoBut.template new file mode 100644 index 0000000..a9fc28a --- /dev/null +++ b/Crow.Coding/ui/IcoBut.template @@ -0,0 +1,7 @@ + + + + diff --git a/Crow.Coding/ui/ItemTemplates/Enum.template b/Crow.Coding/ui/ItemTemplates/Enum.template new file mode 100755 index 0000000..efd9e43 --- /dev/null +++ b/Crow.Coding/ui/ItemTemplates/Enum.template @@ -0,0 +1,47 @@ + + + diff --git a/Crow.Coding/ui/ItemTemplates/Fill.template b/Crow.Coding/ui/ItemTemplates/Fill.template new file mode 100755 index 0000000..56d4a4d --- /dev/null +++ b/Crow.Coding/ui/ItemTemplates/Fill.template @@ -0,0 +1,19 @@ + + + \ No newline at end of file diff --git a/Crow.Coding/ui/MenuItem.template b/Crow.Coding/ui/MenuItem.template new file mode 100644 index 0000000..2fc2936 --- /dev/null +++ b/Crow.Coding/ui/MenuItem.template @@ -0,0 +1,29 @@ + + + + + + + diff --git a/Crow.Coding/ui/icons/basic_floppydisk.svg b/Crow.Coding/ui/icons/basic_floppydisk.svg new file mode 100644 index 0000000..55d901d --- /dev/null +++ b/Crow.Coding/ui/icons/basic_floppydisk.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + diff --git a/Crow.Coding/ui/icons/blank-file.svg b/Crow.Coding/ui/icons/blank-file.svg new file mode 100644 index 0000000..8136979 --- /dev/null +++ b/Crow.Coding/ui/icons/blank-file.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/Crow.Coding/ui/icons/center-align.svg b/Crow.Coding/ui/icons/center-align.svg new file mode 100644 index 0000000..92e3fac --- /dev/null +++ b/Crow.Coding/ui/icons/center-align.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/Crow.Coding/ui/icons/cogwheel.svg b/Crow.Coding/ui/icons/cogwheel.svg new file mode 100644 index 0000000..c104c47 --- /dev/null +++ b/Crow.Coding/ui/icons/cogwheel.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Crow.Coding/ui/icons/edit.svg b/Crow.Coding/ui/icons/edit.svg new file mode 100644 index 0000000..73569d8 --- /dev/null +++ b/Crow.Coding/ui/icons/edit.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/Crow.Coding/ui/icons/file-code.svg b/Crow.Coding/ui/icons/file-code.svg new file mode 100644 index 0000000..2dc00db --- /dev/null +++ b/Crow.Coding/ui/icons/file-code.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/Crow.Coding/ui/icons/folder.svg b/Crow.Coding/ui/icons/folder.svg new file mode 100644 index 0000000..ee1f82b --- /dev/null +++ b/Crow.Coding/ui/icons/folder.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/Crow.Coding/ui/icons/font-file.svg b/Crow.Coding/ui/icons/font-file.svg new file mode 100644 index 0000000..20beac1 --- /dev/null +++ b/Crow.Coding/ui/icons/font-file.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Crow.Coding/ui/icons/light-bulb.svg b/Crow.Coding/ui/icons/light-bulb.svg new file mode 100644 index 0000000..4193a75 --- /dev/null +++ b/Crow.Coding/ui/icons/light-bulb.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Crow.Coding/ui/icons/paragraph.svg b/Crow.Coding/ui/icons/paragraph.svg new file mode 100644 index 0000000..826aa63 --- /dev/null +++ b/Crow.Coding/ui/icons/paragraph.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/Crow.Coding/ui/icons/previous.svg b/Crow.Coding/ui/icons/previous.svg new file mode 100644 index 0000000..566c8a3 --- /dev/null +++ b/Crow.Coding/ui/icons/previous.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/Crow.Coding/ui/icons/question.svg b/Crow.Coding/ui/icons/question.svg new file mode 100644 index 0000000..fb8e3d3 --- /dev/null +++ b/Crow.Coding/ui/icons/question.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Crow.Coding/ui/icons/reply.svg b/Crow.Coding/ui/icons/reply.svg new file mode 100644 index 0000000..d008cb3 --- /dev/null +++ b/Crow.Coding/ui/icons/reply.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/Crow.Coding/ui/icons/search.svg b/Crow.Coding/ui/icons/search.svg new file mode 100644 index 0000000..4a931b3 --- /dev/null +++ b/Crow.Coding/ui/icons/search.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/Crow.Coding/ui/icons/share-arrow.svg b/Crow.Coding/ui/icons/share-arrow.svg new file mode 100644 index 0000000..e0eb246 --- /dev/null +++ b/Crow.Coding/ui/icons/share-arrow.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/Crow.Coding/ui/icons/sign-out.svg b/Crow.Coding/ui/icons/sign-out.svg new file mode 100644 index 0000000..c5951fc --- /dev/null +++ b/Crow.Coding/ui/icons/sign-out.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Crow.Coding/ui/icons/text-file.svg b/Crow.Coding/ui/icons/text-file.svg new file mode 100644 index 0000000..eafca90 --- /dev/null +++ b/Crow.Coding/ui/icons/text-file.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/Crow.Coding/ui/icons/text-label.svg b/Crow.Coding/ui/icons/text-label.svg new file mode 100644 index 0000000..8fa9196 --- /dev/null +++ b/Crow.Coding/ui/icons/text-label.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Crow.Coding/ui/icons/tools.svg b/Crow.Coding/ui/icons/tools.svg new file mode 100644 index 0000000..5326f19 --- /dev/null +++ b/Crow.Coding/ui/icons/tools.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/Crow.Coding/ui/icons/zoom-in.svg b/Crow.Coding/ui/icons/zoom-in.svg new file mode 100644 index 0000000..60c41d1 --- /dev/null +++ b/Crow.Coding/ui/icons/zoom-in.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Crow.Coding/ui/icons/zoom-out.svg b/Crow.Coding/ui/icons/zoom-out.svg new file mode 100644 index 0000000..bd4eec3 --- /dev/null +++ b/Crow.Coding/ui/icons/zoom-out.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/CrowEdit.csproj b/CrowEdit.csproj index f2dad2e..065e4ff 100644 --- a/CrowEdit.csproj +++ b/CrowEdit.csproj @@ -1,125 +1,21 @@ - - - - Debug - AnyCPU - {AAA67D93-458E-4DD7-9CDA-4EC7F73D47FF} - Exe - CrowEdit - CrowEdit - v4.5 - CrowEdit.CrowEdit - $(SolutionDir)build/$(Configuration) - $(SolutionDir)build/obj/$(Configuration) - - - - - - - - true - full - false - prompt - 4 - false - DEBUG;TRACE - $(SolutionDir)build\obj\$(Configuration) - $(SolutionDir)build\$(Configuration) - - - none - true - 0 - false - $(SolutionDir)build\obj\$(Configuration) - $(SolutionDir)build\$(Configuration) - - - Program - %24{TargetName} - %24{SolutionDir}\build\%24{ProjectConfigName} - false - - - - - - - - - - - - - - - - - - - - - - PreserveNewest - - - - - - - - packages\OpenTK.2.0.0\lib\net20\OpenTK.dll - - - packages\Crow.OpenTK.0.6.0\lib\net45\Crow.dll - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Crow.MenuItem.template - - - - - - - - - - - - - - - + + + net472 + Exe + false + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/CrowEdit.sln b/CrowEdit.sln index 6d85afc..2c7ab77 100644 --- a/CrowEdit.sln +++ b/CrowEdit.sln @@ -3,15 +3,27 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 2012 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CrowEdit", "CrowEdit.csproj", "{AAA67D93-458E-4DD7-9CDA-4EC7F73D47FF}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Crow.Coding", "Crow.Coding\Crow.Coding.csproj", "{78842EE4-8A2F-4C75-AEC6-C95F15AD3994}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Crow", "..\crow\Crow\Crow.csproj", "{0D18388D-8DDB-43DE-A608-0C65F0AEC4E0}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Release|Any CPU = Release|Any CPU Debug|Any CPU = Debug|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution + {78842EE4-8A2F-4C75-AEC6-C95F15AD3994}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {78842EE4-8A2F-4C75-AEC6-C95F15AD3994}.Debug|Any CPU.Build.0 = Debug|Any CPU + {78842EE4-8A2F-4C75-AEC6-C95F15AD3994}.Release|Any CPU.ActiveCfg = Release|Any CPU + {78842EE4-8A2F-4C75-AEC6-C95F15AD3994}.Release|Any CPU.Build.0 = Release|Any CPU {AAA67D93-458E-4DD7-9CDA-4EC7F73D47FF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {AAA67D93-458E-4DD7-9CDA-4EC7F73D47FF}.Debug|Any CPU.Build.0 = Debug|Any CPU {AAA67D93-458E-4DD7-9CDA-4EC7F73D47FF}.Release|Any CPU.ActiveCfg = Release|Any CPU {AAA67D93-458E-4DD7-9CDA-4EC7F73D47FF}.Release|Any CPU.Build.0 = Release|Any CPU + {0D18388D-8DDB-43DE-A608-0C65F0AEC4E0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0D18388D-8DDB-43DE-A608-0C65F0AEC4E0}.Release|Any CPU.Build.0 = Release|Any CPU + {0D18388D-8DDB-43DE-A608-0C65F0AEC4E0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0D18388D-8DDB-43DE-A608-0C65F0AEC4E0}.Debug|Any CPU.Build.0 = Debug|Any CPU EndGlobalSection EndGlobal diff --git a/CrowWindow.cs b/CrowWindow.cs index 9a0c4df..f1d644e 100644 --- a/CrowWindow.cs +++ b/CrowWindow.cs @@ -23,7 +23,6 @@ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. - using System; using System.Threading; using OpenTK; diff --git a/Directory.Build.props b/Directory.Build.props new file mode 100644 index 0000000..92af439 --- /dev/null +++ b/Directory.Build.props @@ -0,0 +1,9 @@ + + + $(SolutionDir)build\$(Configuration)\ + $(SolutionDir)build\obj\$(Configuration)\ + MIT + Jean-Philippe Bruyère + 7.2 + + diff --git a/OpenGL/Extensions.cs b/OpenGL/Extensions.cs deleted file mode 100644 index 7b26f76..0000000 --- a/OpenGL/Extensions.cs +++ /dev/null @@ -1,41 +0,0 @@ -// -// Extensions.cs -// -// Author: -// Jean-Philippe Bruyère -// -// Copyright (c) 2017 jp -// -// This program 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. -// -// This program 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 this program. If not, see . -using System; -using OpenTK; -using Crow; - -namespace Crow -{ - public static partial class Extensions { - public static Vector4 ToVector4(this Color c){ - float[] f = c.floatArray; - return new Vector4 (f [0], f [1], f [2], f [3]); - } - public static Vector3 Transform(this Vector3 v, Matrix4 m){ - return Vector4.Transform(new Vector4(v, 1), m).Xyz; - } - public static bool IsInBetween(this int v, int min, int max){ - return v >= min & v <= max; - } - - } -} - diff --git a/OpenGL/Shader.cs b/OpenGL/Shader.cs deleted file mode 100644 index f91a982..0000000 --- a/OpenGL/Shader.cs +++ /dev/null @@ -1,336 +0,0 @@ -// -// Shader.cs -// -// Author: -// Jean-Philippe Bruyère -// -// Copyright (c) 2016 jp -// -// This program 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. -// -// This program 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 this program. If not, see . - -using System; -using System.Diagnostics; -using System.IO; -using OpenTK; -using OpenTK.Graphics.OpenGL; - -namespace Crow -{ - public class Shader : IDisposable - { - #region CTOR - public Shader () - { - Init (); - } - public Shader (string vertResPath, string fragResPath = null, string geomResPath = null) - { - VertSourcePath = vertResPath; - FragSourcePath = fragResPath; - GeomSourcePath = geomResPath; - - loadSourcesFiles (); - - Init (); - } - #endregion - - public string VertSourcePath, - FragSourcePath, - GeomSourcePath; - #region Sources - protected string _vertSource = @" - #version 300 es - precision lowp float; - - uniform mat4 mvp; - - layout(location = 0) in vec3 in_position; - layout(location = 1) in vec2 in_tex; - - out vec2 texCoord; - - void main(void) - { - texCoord = in_tex; - gl_Position = mvp * vec4(in_position, 1.0); - }"; - - protected string _fragSource = @" - #version 300 es - precision lowp float; - - uniform sampler2D tex; - - in vec2 texCoord; - out vec4 out_frag_color; - - void main(void) - { - out_frag_color = texture( tex, texCoord);//vec4(1,0,0,1); - }"; - string _geomSource = @""; -// #version 330 -// layout(triangles) in; -// layout(triangle_strip, max_vertices=3) out; -// void main() -// { -// for(int i=0; i<3; i++) -// { -// gl_Position = gl_in[i].gl_Position; -// EmitVertex(); -// } -// EndPrimitive(); -// }"; - #endregion - - #region Private and protected fields - public int vsId, fsId, gsId, pgmId, mvpLocation; - - Matrix4 mvp = Matrix4.Identity; - #endregion - - - #region Public properties - public virtual string vertSource - { - get { return _vertSource;} - set { _vertSource = value; } - } - public virtual string fragSource - { - get { return _fragSource;} - set { _fragSource = value; } - } - public virtual string geomSource - { - get { return _geomSource; } - set { _geomSource = value; } - } - - public virtual Matrix4 MVP{ - set { mvp = value; } - get { return mvp; } - } - #endregion - - #region Public functions - /// - /// configure sources and compile - /// - public virtual void Init() - { - Compile (); - } - public void Reload(){ - loadSourcesFiles (); - Compile (); - } - public void SetSource(ShaderType shaderType, string _source){ - switch (shaderType) { - case ShaderType.FragmentShader: - fragSource = _source; - return; - case ShaderType.VertexShader: - vertSource = _source; - return; - case ShaderType.GeometryShader: - geomSource = _source; - return; - } - } - public string GetSource(ShaderType shaderType){ - switch (shaderType) { - case ShaderType.FragmentShader: - return fragSource; - case ShaderType.VertexShader: - return vertSource; - case ShaderType.GeometryShader: - return geomSource; - } - return ""; - } - public string GetSourcePath(ShaderType shaderType){ - switch (shaderType) { - case ShaderType.FragmentShader: - return FragSourcePath; - case ShaderType.VertexShader: - return VertSourcePath; - case ShaderType.GeometryShader: - return GeomSourcePath; - } - return ""; - } - public virtual void Compile() - { - Dispose (); - - pgmId = GL.CreateProgram(); - - if (!string.IsNullOrEmpty(vertSource)) - { - vsId = GL.CreateShader(ShaderType.VertexShader); - compileShader(vsId, vertSource); - } - if (!string.IsNullOrEmpty(fragSource)) - { - fsId = GL.CreateShader(ShaderType.FragmentShader); - compileShader(fsId, fragSource); - - } - if (!string.IsNullOrEmpty(geomSource)) - { - gsId = GL.CreateShader(ShaderType.GeometryShader); - compileShader(gsId,geomSource); - } - - if (vsId != 0) - GL.AttachShader(pgmId, vsId); - if (fsId != 0) - GL.AttachShader(pgmId, fsId); - if (gsId != 0) - GL.AttachShader(pgmId, gsId); - - BindVertexAttributes (); - - string info; - GL.LinkProgram(pgmId); - GL.GetProgramInfoLog(pgmId, out info); - - if (!string.IsNullOrEmpty (info)) { - Debug.WriteLine ("Linkage:"); - Debug.WriteLine (info); - } - - info = null; - - GL.ValidateProgram(pgmId); - GL.GetProgramInfoLog(pgmId, out info); - if (!string.IsNullOrEmpty (info)) { - Debug.WriteLine ("Validation:"); - Debug.WriteLine (info); - } - - GL.UseProgram (pgmId); - - GetUniformLocations (); - BindSamplesSlots (); - - Disable (); - } - - protected virtual void BindVertexAttributes() - { - GL.BindAttribLocation(pgmId, 0, "in_position"); - GL.BindAttribLocation(pgmId, 1, "in_tex"); - } - protected virtual void GetUniformLocations() - { - mvpLocation = GL.GetUniformLocation(pgmId, "mvp"); - } - protected virtual void BindSamplesSlots(){ - GL.Uniform1(GL.GetUniformLocation (pgmId, "tex"), 0); - } - public void SetMVP(Matrix4 _mvp){ - GL.UniformMatrix4(mvpLocation, false, ref _mvp); - } - public virtual void Enable(){ - GL.UseProgram (pgmId); - } - public virtual void Disable(){ - GL.UseProgram (0); - } - public static void Enable(Shader s) - { - if (s == null) - return; - s.Enable (); - } - public static void Disable(Shader s) - { - if (s == null) - return; - s.Disable (); - } - #endregion - - void loadSourcesFiles(){ - Stream s; - - if (!string.IsNullOrEmpty (VertSourcePath)) { - s = Crow.Interface.GetStreamFromPath (VertSourcePath); - if (s != null) { - using (StreamReader sr = new StreamReader (s)) { - vertSource = sr.ReadToEnd (); - } - } - } - - if (!string.IsNullOrEmpty (FragSourcePath)) { - s = Crow.Interface.GetStreamFromPath (FragSourcePath); - if (s != null) { - using (StreamReader sr = new StreamReader (s)) { - fragSource = sr.ReadToEnd (); - } - } - } - - if (!string.IsNullOrEmpty (GeomSourcePath)) { - s = Crow.Interface.GetStreamFromPath (GeomSourcePath); - if (s != null) { - using (StreamReader sr = new StreamReader (s)) { - geomSource = sr.ReadToEnd (); - } - } - } - } - void compileShader(int shader, string source) - { - GL.ShaderSource(shader, source); - GL.CompileShader(shader); - - string info; - GL.GetShaderInfoLog(shader, out info); - Debug.WriteLine(info); - - int compileResult; - GL.GetShader(shader, ShaderParameter.CompileStatus, out compileResult); - if (compileResult != 1) - { - Debug.WriteLine("Compile Error!"); - Debug.WriteLine(source); - } - } - public override string ToString () - { - return string.Format ("{0} {1} {2}", VertSourcePath, FragSourcePath, GeomSourcePath); - } - - #region IDisposable implementation - public virtual void Dispose () - { - if (GL.IsProgram (pgmId)) - GL.DeleteProgram (pgmId); - - if (GL.IsShader (vsId)) - GL.DeleteShader (vsId); - if (GL.IsShader (fsId)) - GL.DeleteShader (fsId); - if (GL.IsShader (gsId)) - GL.DeleteShader (gsId); - } - #endregion - } -} - diff --git a/OpenGL/Texture.cs b/OpenGL/Texture.cs deleted file mode 100644 index ce24808..0000000 --- a/OpenGL/Texture.cs +++ /dev/null @@ -1,94 +0,0 @@ -// -// Texture.cs -// -// Author: -// Jean-Philippe Bruyère -// -// Copyright (c) 2016 jp -// -// This program 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. -// -// This program 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 this program. If not, see . - -using System; -using System.Drawing; -using OpenTK.Graphics.OpenGL; -using System.Drawing.Imaging; -using System.IO; -using System.Diagnostics; - -namespace Crow -{ - public class Texture - { - public string Map; - public int texRef; - public int Width; - public int Height; - - public Texture(string _mapPath, bool flipY = true) - { - using (Stream s = Interface.GetStreamFromPath (_mapPath)) { - - try { - Map = _mapPath; - - Bitmap bitmap = new Bitmap (s); - - if (flipY) - bitmap.RotateFlip (RotateFlipType.RotateNoneFlipY); - - BitmapData data = bitmap.LockBits (new System.Drawing.Rectangle (0, 0, bitmap.Width, bitmap.Height), - ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb); - - createTexture (data.Scan0, data.Width, data.Height); - - bitmap.UnlockBits (data); - - GL.TexParameter (TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.LinearMipmapLinear); - GL.TexParameter (TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear); - - GL.GenerateMipmap (GenerateMipmapTarget.Texture2D); - - } catch (Exception ex) { - Debug.WriteLine ("Error loading texture: " + Map + ":" + ex.Message); - } - } - } - - public Texture(int width, int height) - { - createTexture (IntPtr.Zero, width, height); - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear); - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear); - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Clamp); - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Clamp); - } - - void createTexture(IntPtr data, int width, int height) - { - Width = width; - Height = height; - - GL.GenTextures(1, out texRef); - GL.BindTexture(TextureTarget.Texture2D, texRef); - GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, width, height, 0, - OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, data); - } - - public static implicit operator int(Texture t) - { - return t == null ? 0: t.texRef; - } - } - -} diff --git a/OpenGL/vaoMesh.cs b/OpenGL/vaoMesh.cs deleted file mode 100644 index 19acd73..0000000 --- a/OpenGL/vaoMesh.cs +++ /dev/null @@ -1,221 +0,0 @@ -// -// vaoMesh.cs -// -// Author: -// Jean-Philippe Bruyère -// -// Copyright (c) 2016 jp -// -// This program 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. -// -// This program 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 this program. If not, see . - -using System; -using OpenTK; -using OpenTK.Graphics.OpenGL; - -namespace Crow -{ - public class vaoMesh : IDisposable - { - public int vaoHandle, - positionVboHandle, - texVboHandle, - eboHandle; - - public Vector3[] positions; - public Vector2[] texCoords; - public int[] indices; - - public vaoMesh() - { - } - - public vaoMesh (Vector3[] _positions, Vector2[] _texCoord, int[] _indices) - { - positions = _positions; - texCoords = _texCoord; - indices = _indices; - - CreateBuffers (); - } - - public vaoMesh (float x, float y, float z, float width, float height, float TileX = 1f, float TileY = 1f) - { - positions = - new Vector3[] { - new Vector3 (x - width / 2, y + height / 2, z), - new Vector3 (x - width / 2, y - height / 2, z), - new Vector3 (x + width / 2, y + height / 2, z), - new Vector3 (x + width / 2, y - height / 2, z) - }; - texCoords = new Vector2[] { - new Vector2 (0, TileY), - new Vector2 (0, 0), - new Vector2 (TileX, TileY), - new Vector2 (TileX, 0) - }; - indices = new int[] { 0, 1, 2, 3 }; - - CreateBuffers (); - } - public static vaoMesh CreateCube(){ - vaoMesh tmp = new vaoMesh (); - tmp.positions = new Vector3[] - { - new Vector3(-1.0f, -1.0f, -1.0f), - new Vector3( -1.0f, -1.0f, 1.0f), - new Vector3( 1.0f, -1.0f, -1.0f), - new Vector3(1.0f, -1.0f, 1.0f), - new Vector3(1.0f, 1.0f, -1.0f), - new Vector3( 1.0f, 1.0f, 1.0f), - new Vector3( -1.0f, 1.0f, -1.0f), - new Vector3(-1.0f, 1.0f, 1.0f) - }; - tmp.indices = new int[] - { - // front face - 0, 2, 1, 1, 2, 3, - // top face - 2, 4, 3, 3, 4, 5, - // back face - 4, 6, 5, 5, 6, 7, - // left face - 6, 0, 7, 7, 0, 1, - // bottom face - 1, 3, 7, 7, 3, 5, - // right face -// 1, 5, 6, 6, 2, 1, - }; - tmp.texCoords = new Vector2[] - { - new Vector2(0, 0), - new Vector2(0, 1), - new Vector2(1, 0), - new Vector2(1, 1), - new Vector2(0, 0), - new Vector2(0, 1), - new Vector2(1, 0), - new Vector2(1, 1), - }; - tmp.CreateBuffers (); - return tmp; -// Normals = new Vector3[] -// { -// new Vector3(-1.0f, -1.0f, 1.0f), -// new Vector3( 1.0f, -1.0f, 1.0f), -// new Vector3( 1.0f, 1.0f, 1.0f), -// new Vector3(-1.0f, 1.0f, 1.0f), -// new Vector3(-1.0f, -1.0f, -1.0f), -// new Vector3( 1.0f, -1.0f, -1.0f), -// new Vector3( 1.0f, 1.0f, -1.0f), -// new Vector3(-1.0f, 1.0f, -1.0f), -// }; -// -// Colors = new int[] -// { -// Utilities.ColorToRgba32(Color.DarkRed), -// Utilities.ColorToRgba32(Color.DarkRed), -// Utilities.ColorToRgba32(Color.Gold), -// Utilities.ColorToRgba32(Color.Gold), -// Utilities.ColorToRgba32(Color.DarkRed), -// Utilities.ColorToRgba32(Color.DarkRed), -// Utilities.ColorToRgba32(Color.Gold), -// Utilities.ColorToRgba32(Color.Gold), -// }; - } - public void CreateBuffers(){ - CreateVBOs (); - CreateVAOs (); - } - protected void CreateVBOs() - { - positionVboHandle = GL.GenBuffer(); - GL.BindBuffer(BufferTarget.ArrayBuffer, positionVboHandle); - GL.BufferData(BufferTarget.ArrayBuffer, - new IntPtr(positions.Length * Vector3.SizeInBytes), - positions, BufferUsageHint.StaticDraw); - - if (texCoords != null) { - texVboHandle = GL.GenBuffer (); - GL.BindBuffer (BufferTarget.ArrayBuffer, texVboHandle); - GL.BufferData (BufferTarget.ArrayBuffer, - new IntPtr (texCoords.Length * Vector2.SizeInBytes), - texCoords, BufferUsageHint.StaticDraw); - } - - GL.BindBuffer(BufferTarget.ArrayBuffer, 0); - - if (indices != null) { - eboHandle = GL.GenBuffer (); - GL.BindBuffer (BufferTarget.ElementArrayBuffer, eboHandle); - GL.BufferData (BufferTarget.ElementArrayBuffer, - new IntPtr (sizeof(uint) * indices.Length), - indices, BufferUsageHint.StaticDraw); - GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0); - } - } - protected void CreateVAOs() - { - vaoHandle = GL.GenVertexArray(); - GL.BindVertexArray(vaoHandle); - - GL.EnableVertexAttribArray(0); - GL.BindBuffer(BufferTarget.ArrayBuffer, positionVboHandle); - GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, true, Vector3.SizeInBytes, 0); - - if (texCoords != null) { - GL.EnableVertexAttribArray (1); - GL.BindBuffer (BufferTarget.ArrayBuffer, texVboHandle); - GL.VertexAttribPointer (1, 2, VertexAttribPointerType.Float, true, Vector2.SizeInBytes, 0); - } - if (indices != null) - GL.BindBuffer(BufferTarget.ElementArrayBuffer, eboHandle); - - GL.BindVertexArray(0); - } - - public void Render(BeginMode _primitiveType){ - GL.BindVertexArray(vaoHandle); - if (indices == null) - GL.DrawArrays (_primitiveType, 0, positions.Length); - else - GL.DrawElements(_primitiveType, indices.Length, - DrawElementsType.UnsignedInt, IntPtr.Zero); - GL.BindVertexArray (0); - } - public void Render(BeginMode _primitiveType, int[] _customIndices){ - GL.BindVertexArray(vaoHandle); - GL.DrawElements(_primitiveType, _customIndices.Length, - DrawElementsType.UnsignedInt, _customIndices); - GL.BindVertexArray (0); - } - public void Render(BeginMode _primitiveType, int instances){ - - GL.BindVertexArray(vaoHandle); - GL.DrawElementsInstanced(_primitiveType, indices.Length, - DrawElementsType.UnsignedInt, IntPtr.Zero, instances); - GL.BindVertexArray (0); - } - - #region IDisposable implementation - public void Dispose () - { - GL.DeleteBuffer (positionVboHandle); - GL.DeleteBuffer (texVboHandle); - GL.DeleteBuffer (eboHandle); - GL.DeleteVertexArray (vaoHandle); - } - #endregion - - } -} \ No newline at end of file diff --git a/ParsingException.cs b/ParsingException.cs deleted file mode 100644 index 88c51c9..0000000 --- a/ParsingException.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; - -namespace Crow.Coding -{ - public class ParsingException : Exception - { - public int Line; - public int Column; - public ParsingException(Parser parser, string txt) - : base(string.Format("Parser exception ({0},{1}): {2}", parser.currentLine, parser.currentColumn, txt)) - { - Line = parser.currentLine; - Column = parser.currentColumn; - } - public ParsingException(Parser parser, string txt, Exception innerException) - : base(txt, innerException) - { - txt = string.Format("Parser exception ({0},{1}): {2}", parser.currentLine, parser.currentColumn, txt); - } - } -} - diff --git a/src/CSharpParser.cs b/src/CSharpParser.cs deleted file mode 100644 index 7d2e28e..0000000 --- a/src/CSharpParser.cs +++ /dev/null @@ -1,45 +0,0 @@ -using System; -using Crow; - -namespace Crow.Coding -{ - public class CSharpParser : Parser - { - public new enum TokenType { - Unknown = Parser.TokenType.Unknown, - WhiteSpace = Parser.TokenType.WhiteSpace, - LineComment = Parser.TokenType.LineComment, - BlockComment = Parser.TokenType.BlockComment, - OpenParenth, - CloseParenth, - OpenBlock, - CloseBlock, - StatementEnding, - UnaryOp, - BinaryOp, - Affectation, - StringLiteral, - CharacterLiteral, - DigitalLiteral, - Literal, - Identifier, - Indexer, - Type, - Preprocessor, - } - - public CSharpParser (CodeBuffer _buffer) : base(_buffer) - { - } - - public override void ParseCurrentLine () - { - throw new NotImplementedException (); - } - public override void SyntaxAnalysis () - { - throw new NotImplementedException (); - } - } -} - diff --git a/src/CrowEdit.cs b/src/CrowEdit.cs index a9af7dc..54cb1c4 100644 --- a/src/CrowEdit.cs +++ b/src/CrowEdit.cs @@ -1,23 +1,7 @@ -// -// Main.cs +// Copyright (c) 2013-2020 Jean-Philippe Bruyère // -// Author: -// Jean-Philippe Bruyère -// -// Copyright (c) 2017 jp -// -// This program 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. -// -// This program 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 this program. If not, see . +// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) + using System; using Crow; using System.IO; @@ -25,11 +9,11 @@ using System.Collections.Generic; namespace CrowEdit { - public class CrowEdit : CrowWindow + public class CrowEdit : Interface { - public Command CMDNew, CMDOpen, CMDSave, CMDSaveAs, CMDQuit, CMDUndo, CMDRedo, CMDCut, CMDCopy, CMDPaste, CMDHelp, CMDAbout, CMDOptions; + public Command CMDNew, CMDOpen, CMDSave, CMDSaveAs, CMDQuit, CMDShowLeftPane, + CMDUndo, CMDRedo, CMDCut, CMDCopy, CMDPaste, CMDHelp, CMDAbout, CMDOptions; - string _curDir = Environment.GetFolderPath (Environment.SpecialFolder.MyDocuments); string _curFilePath = "unamed.txt"; string _text = "", _origText=""; @@ -46,7 +30,7 @@ namespace CrowEdit redoStack.Clear (); CMDRedo.CanExecute = false; _text = value; - NotifyValueChanged ("Text", _text); + NotifyValueChanged (_text); NotifyValueChanged ("IsDirty", IsDirty); } } @@ -54,12 +38,12 @@ namespace CrowEdit public bool IsDirty { get { return _text != _origText; }} public string CurrentDir { - get { return Configuration.Get("CurrentDir"); } + get { return Configuration.Global.Get("CurrentDir"); } set { if (CurrentDir == value) return; - Configuration.Set ("CurrentDir", value); - NotifyValueChanged ("CurrentDir", _curDir); + Configuration.Global.Set ("CurrentDir", value); + NotifyValueChanged (CurrentDir); } } public string CurFilePath { @@ -68,36 +52,43 @@ namespace CrowEdit if (_curFilePath == value) return; _curFilePath = value; - NotifyValueChanged ("CurFilePath", _curFilePath); + NotifyValueChanged (_curFilePath); } } + bool showLeftPane; + public bool ShowLeftPane { + get { return Configuration.Global.Get ("ShowLeftPane"); } + set { + if (ShowLeftPane == value) + return; + Configuration.Global.Set ("ShowLeftPane", value); + NotifyValueChanged (ShowLeftPane); + } + } + public string CurFileFullPath { get { return Path.Combine(CurrentDir,CurFilePath); }} void initCommands(){ - CMDNew = new Command(new Action(() => newFile())) { Caption = "New", Icon = new SvgPicture("#CrowEdit.ui.icons.blank-file.svg")}; + CMDNew = new Command(new Action(() => onNewFile())) { Caption = "New", Icon = new SvgPicture("#CrowEdit.ui.icons.blank-file.svg")}; CMDOpen = new Command(new Action(() => openFileDialog())) { Caption = "Open...", Icon = new SvgPicture("#CrowEdit.ui.icons.outbox.svg")}; CMDSave = new Command(new Action(() => saveFileDialog())) { Caption = "Save", Icon = new SvgPicture("#CrowEdit.ui.icons.inbox.svg"), CanExecute = false}; CMDSaveAs = new Command(new Action(() => saveFileDialog())) { Caption = "Save As...", Icon = new SvgPicture("#CrowEdit.ui.icons.inbox.svg"), CanExecute = false}; - CMDQuit = new Command(new Action(() => Quit (null, null))) { Caption = "Quit", Icon = new SvgPicture("#CrowEdit.ui.icons.sign-out.svg")}; + CMDQuit = new Command(new Action(() => base.Quit())) { Caption = "Quit", Icon = new SvgPicture("#CrowEdit.ui.icons.sign-out.svg")}; CMDUndo = new Command(new Action(() => undo())) { Caption = "Undo", Icon = new SvgPicture("#CrowEdit.ui.icons.reply.svg"), CanExecute = false}; CMDRedo = new Command(new Action(() => redo())) { Caption = "Redo", Icon = new SvgPicture("#CrowEdit.ui.icons.share-arrow.svg"), CanExecute = false}; - CMDCut = new Command(new Action(() => Quit (null, null))) { Caption = "Cut", Icon = new SvgPicture("#CrowEdit.ui.icons.scissors.svg"), CanExecute = false}; - CMDCopy = new Command(new Action(() => Quit (null, null))) { Caption = "Copy", Icon = new SvgPicture("#CrowEdit.ui.icons.copy-file.svg"), CanExecute = false}; - CMDPaste = new Command(new Action(() => Quit (null, null))) { Caption = "Paste", Icon = new SvgPicture("#CrowEdit.ui.icons.paste-on-document.svg"), CanExecute = false}; + CMDCut = new Command(new Action(() => Quit ())) { Caption = "Cut", Icon = new SvgPicture("#CrowEdit.ui.icons.scissors.svg"), CanExecute = false}; + CMDCopy = new Command(new Action(() => Quit ())) { Caption = "Copy", Icon = new SvgPicture("#CrowEdit.ui.icons.copy-file.svg"), CanExecute = false}; + CMDPaste = new Command(new Action(() => Quit ())) { Caption = "Paste", Icon = new SvgPicture("#CrowEdit.ui.icons.paste-on-document.svg"), CanExecute = false}; CMDHelp = new Command(new Action(() => System.Diagnostics.Debug.WriteLine("help"))) { Caption = "Help", Icon = new SvgPicture("#CrowEdit.ui.icons.question.svg")}; CMDOptions = new Command(new Action(() => openOptionsDialog())) { Caption = "Editor Options", Icon = new SvgPicture("#CrowEdit.ui.icons.tools.svg")}; - + CMDShowLeftPane = new Command (new Action (() => ShowLeftPane = !ShowLeftPane)) { Caption = "Show Left Pane" }; } - void newFile(){ - CurFilePath = "unamed.txt"; - _origText = _text = ""; - NotifyValueChanged ("Text", _text); - NotifyValueChanged ("IsDirty", false); - redoStack.Clear (); - undoStack.Clear (); - CMDRedo.CanExecute = false; - CMDUndo.CanExecute = false; - NotifyValueChanged ("CurFileFullPath", CurFileFullPath); + void onNewFile(){ + if (IsDirty) { + MessageBox mb = MessageBox.ShowModal (this, MessageBox.Type.YesNo, "Current file has unsaved changes, are you sure?"); + mb.Yes += (sender, e) => newFile(); + } else + newFile (); } void undo(){ string step = undoStack [undoStack.Count -1]; @@ -107,7 +98,7 @@ namespace CrowEdit _text = step; - NotifyValueChanged ("Text", _text); + NotifyValueChanged ("Text", (object)_text); NotifyValueChanged ("IsDirty", IsDirty); if (undoStack.Count == 0) @@ -119,14 +110,14 @@ namespace CrowEdit CMDUndo.CanExecute = true; redoStack.RemoveAt(redoStack.Count -1); _text = step; - NotifyValueChanged ("Text", _text); + NotifyValueChanged ("Text", (object)_text); NotifyValueChanged ("IsDirty", IsDirty); if (redoStack.Count == 0) CMDRedo.CanExecute = false; } void openOptionsDialog(){ - GraphicObject ed = this.FindByName("editor"); + Widget ed = this.FindByName("editor"); Load ("#CrowEdit.ui.EditorOptions.crow").DataSource = ed; } void openFileDialog(){ @@ -140,15 +131,7 @@ namespace CrowEdit FileDialog fd = sender as FileDialog; if (string.IsNullOrEmpty (fd.SelectedFile)) return; - CurFilePath = fd.SelectedFile; - CurrentDir = fd.SelectedDirectory; - -// redoStack.Clear (); -// undoStack.Clear (); -// CMDRedo.CanExecute = false; -// CMDUndo.CanExecute = false; -// - NotifyValueChanged ("CurFileFullPath", CurFileFullPath); + openFile (fd.SelectedFile, fd.SelectedDirectory); } void saveFileDialog_OkClicked (object sender, EventArgs e) { @@ -165,28 +148,73 @@ namespace CrowEdit _origText = _text; NotifyValueChanged ("IsDirty", false); - NotifyValueChanged ("CurFileFullPath", CurFileFullPath); + NotifyValueChanged ("CurFileFullPath", (object)CurFileFullPath); } void onTextChanged (object sender, TextChangeEventArgs e) { - System.Diagnostics.Debug.WriteLine ("text changed"); + //System.Diagnostics.Debug.WriteLine ("text changed"); NotifyValueChanged ("IsDirty", IsDirty); } + void goUpDirClick (object sender, MouseButtonEventArgs e) { + string root = Directory.GetDirectoryRoot (CurrentDir); + if (CurrentDir == root) + return; + CurrentDir = Directory.GetParent (CurrentDir).FullName; + } + + void Dv_SelectedItemChanged (object sender, SelectionChangeEventArgs e) { + FileSystemInfo fi = e.NewValue as FileSystemInfo; + if (fi == null) + return; + if (fi is DirectoryInfo) + return; + + OnOpenFile (Path.GetFileName (fi.FullName), Path.GetDirectoryName (fi.FullName)); + } + + void OnOpenFile (string filePath, string directory) { + if (IsDirty) { + MessageBox mb = MessageBox.ShowModal (this, MessageBox.Type.YesNo, "Current file has unsaved changes, are you sure?"); + mb.Yes += (sender, e) => openFile (filePath, directory); + } else + openFile (filePath, directory); + } + void newFile () { + CurFilePath = "unamed.txt"; + _origText = _text = ""; + NotifyValueChanged ("Text", (object)_text); + NotifyValueChanged ("IsDirty", false); + redoStack.Clear (); + undoStack.Clear (); + CMDRedo.CanExecute = false; + CMDUndo.CanExecute = false; + NotifyValueChanged ("CurFileFullPath", (object)CurFileFullPath); + } + void openFile (string filePath, string directory) { + CurFilePath = filePath; + CurrentDir = directory; + + redoStack.Clear (); + undoStack.Clear (); + CMDRedo.CanExecute = false; + CMDUndo.CanExecute = false; + + NotifyValueChanged ("CurFileFullPath", (object)CurFileFullPath); + } + [STAThread] static void Main () { - using (CrowEdit win = new CrowEdit ()) { - win.Run (30); - } + using (CrowEdit win = new CrowEdit ()) + win.Run (); } public CrowEdit () - : base(800, 600,"Crow Simple Editor") + : base(800, 600) {} - protected override void OnLoad (EventArgs e) - { - base.OnLoad (e); + protected override void OnInitialized () { + base.OnInitialized (); if (CurrentDir == null) CurrentDir = Environment.GetFolderPath (Environment.SpecialFolder.MyDocuments); @@ -194,10 +222,10 @@ namespace CrowEdit this.ValueChanged += CrowEdit_ValueChanged; initCommands (); Load ("#CrowEdit.ui.main.crow").DataSource = this; - NotifyValueChanged ("CurFileFullPath", CurFileFullPath); + NotifyValueChanged ("CurFileFullPath", (object)CurFileFullPath); } - void textView_KeyDown (object sender, Crow.KeyboardKeyEventArgs e) + /*void textView_KeyDown (object sender, Crow.KeyEventArgs e) { if (e.Control) { if (e.Key == Key.W) { @@ -207,7 +235,7 @@ namespace CrowEdit CMDUndo.Execute (); } } - } + }*/ void CrowEdit_ValueChanged (object sender, ValueChangeEventArgs e) { diff --git a/src/CrowEditExtentions.cs b/src/CrowEditExtentions.cs deleted file mode 100644 index a2d7ac6..0000000 --- a/src/CrowEditExtentions.cs +++ /dev/null @@ -1,41 +0,0 @@ -// -// CrowEditExtentions.cs -// -// Author: -// Jean-Philippe Bruyère -// -// Copyright (c) 2017 jp -// -// This program 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. -// -// This program 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 this program. If not, see . -using System; -using System.Collections.Generic; - -namespace CrowEdit -{ - public static class CrowEditExtentions - { - public static List AllIndexesOf(this string str, string value) { - if (String.IsNullOrEmpty(value)) - throw new ArgumentException("the string to find may not be empty", "value"); - List indexes = new List(); - for (int index = 0;; index += value.Length) { - index = str.IndexOf(value, index); - if (index == -1) - return indexes; - indexes.Add(index); - } - } - } -} - diff --git a/ui/EditorOptions.crow b/ui/EditorOptions.crow index bf2a2bc..81e529b 100644 --- a/ui/EditorOptions.crow +++ b/ui/EditorOptions.crow @@ -1,5 +1,5 @@  - + diff --git a/ui/icons/basic_floppydisk.svg b/ui/icons/basic_floppydisk.svg index 55d901d..85fbab9 100644 --- a/ui/icons/basic_floppydisk.svg +++ b/ui/icons/basic_floppydisk.svg @@ -3,13 +3,13 @@ - - - - - - - - - + + + + + + + + + diff --git a/ui/main.crow b/ui/main.crow index edad15d..07847f9 100755 --- a/ui/main.crow +++ b/ui/main.crow @@ -1,47 +1,61 @@  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 2.47.3