From fd3397cdf340284c7cbb912b45ebfdbb654947d5 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jean-Philippe=20Bruy=C3=A8re?= Date: Fri, 9 Mar 2018 23:11:41 +0100 Subject: [PATCH] undo/redo, hscrollbar --- Crow.csproj | 3 + CrowIDE/CrowIDE.csproj | 2 + CrowIDE/icons/expand-arrows-1.svg | 9 +++ CrowIDE/icons/redo.svg | 6 ++ CrowIDE/icons/undo.svg | 6 ++ CrowIDE/src/ProjectNodes.cs | 85 ++++++++++++++++++++++-- CrowIDE/src/SourceEditor/SourceEditor.cs | 20 +++++- CrowIDE/src/SvgEditor.cs | 56 +++++++++++++++- CrowIDE/ui/CrowIDE.crow | 12 ++-- CrowIDE/ui/EditPaneItems.template | 17 +++-- CrowIDE/ui/SourceEditor.crow | 2 +- Default.style | 17 +++++ Templates/HScrollBar.template | 18 +++++ src/GraphicObjects/FileDialog.cs | 1 + src/GraphicObjects/Slider.cs | 8 +-- src/Interface.cs | 5 +- 16 files changed, 241 insertions(+), 26 deletions(-) create mode 100644 CrowIDE/icons/expand-arrows-1.svg create mode 100644 CrowIDE/icons/redo.svg create mode 100644 CrowIDE/icons/undo.svg create mode 100755 Templates/HScrollBar.template diff --git a/Crow.csproj b/Crow.csproj index 9e474f58..f14b185a 100644 --- a/Crow.csproj +++ b/Crow.csproj @@ -386,6 +386,9 @@ Crow.DockWindow.template + + Crow.HScrollBar.template + diff --git a/CrowIDE/CrowIDE.csproj b/CrowIDE/CrowIDE.csproj index 1779b1d2..4f48ad0e 100644 --- a/CrowIDE/CrowIDE.csproj +++ b/CrowIDE/CrowIDE.csproj @@ -253,6 +253,8 @@ + + diff --git a/CrowIDE/icons/expand-arrows-1.svg b/CrowIDE/icons/expand-arrows-1.svg new file mode 100644 index 00000000..d96d2ec9 --- /dev/null +++ b/CrowIDE/icons/expand-arrows-1.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/CrowIDE/icons/redo.svg b/CrowIDE/icons/redo.svg new file mode 100644 index 00000000..5c177f00 --- /dev/null +++ b/CrowIDE/icons/redo.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/CrowIDE/icons/undo.svg b/CrowIDE/icons/undo.svg new file mode 100644 index 00000000..955b767a --- /dev/null +++ b/CrowIDE/icons/undo.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/CrowIDE/src/ProjectNodes.cs b/CrowIDE/src/ProjectNodes.cs index 1524b3d2..f96ec5cd 100644 --- a/CrowIDE/src/ProjectNodes.cs +++ b/CrowIDE/src/ProjectNodes.cs @@ -191,19 +191,30 @@ namespace Crow.Coding internal ReaderWriterLockSlim srcEditMtx = new ReaderWriterLockSlim(); public Dictionary RegisteredEditors = new Dictionary(); + List undoStack = new List(); + List redoStack = new List(); - Crow.Command cmdSave, cmdOpen; + public Crow.Command cmdSave, cmdSaveAs, cmdOpen, cmdUndo, cmdRedo; public ProjectFile (ProjectItem pi) : base (pi.Project, pi.node) { cmdSave = new Crow.Command (new Action (() => Save ())) - { Caption = "Save", Icon = new SvgPicture ("#Crow.Coding.ui.icons.inbox.svg"), CanExecute = true }; + { Caption = "Save", Icon = new SvgPicture ("#Crow.Coding.ui.icons.inbox.svg"), CanExecute = false }; + cmdSave = new Crow.Command (new Action (() => SaveAs ())) + { Caption = "Save As ..", Icon = new SvgPicture ("#Crow.Coding.ui.icons.inbox.svg"), CanExecute = false }; cmdOpen = new Crow.Command (new Action (() => Open ())) { Caption = "Open", Icon = new SvgPicture ("#Crow.Coding.ui.icons.outbox.svg"), CanExecute = false }; - + cmdUndo = new Crow.Command (new Action (() => Undo (null))) + { Caption = "Undo", Icon = new SvgPicture ("#Crow.Coding.icons.undo.svg"), CanExecute = false }; + cmdRedo = new Crow.Command (new Action (() => Redo (null))) + { Caption = "Redo", Icon = new SvgPicture ("#Crow.Coding.icons.redo.svg"), CanExecute = false }; + Commands.Insert (0, cmdOpen); Commands.Insert (1, cmdSave); + + //Commands.Add (cmdUndo); + //Commands.Add (cmdRedo); } public string ResourceID { @@ -233,6 +244,9 @@ namespace Crow.Coding public void UpdateSource (object sender, string newSrc){ System.Diagnostics.Debug.WriteLine ("update source by {0}", sender); Source = newSrc; + signalOtherRegisteredEditors (sender); + } + void signalOtherRegisteredEditors (object sender) { lock (RegisteredEditors) { object[] keys = RegisteredEditors.Keys.ToArray (); foreach (object editor in keys) { @@ -259,11 +273,16 @@ namespace Crow.Coding srcEditMtx.EnterWriteLock (); + undoStack.Add (source); + cmdUndo.CanExecute = true; + redoStack.Clear (); + cmdRedo.CanExecute = false; source = value; + NotifyValueChanged ("Source", source); NotifyValueChanged ("IsDirty", IsDirty); - cmdSave.CanExecute = IsDirty; + cmdSave.CanExecute = cmdSaveAs.CanExecute = IsDirty; srcEditMtx.ExitWriteLock (); } @@ -327,11 +346,69 @@ namespace Crow.Coding origSource = source; NotifyValueChanged ("IsDirty", false); } + public void SaveAs () { + if (!IsDirty) + return; + using (StreamWriter sw = new StreamWriter (AbsolutePath)) { + sw.Write (source); + } + origSource = source; + NotifyValueChanged ("IsDirty", false); + } public void Close () { origSource = null; isOpened = false; Project.solution.CloseItem (this); } + public void Undo(object sender){ + undo(); + signalOtherRegisteredEditors (sender); + } + public void Redo(object sender){ + redo(); + signalOtherRegisteredEditors (sender); + } + + void undo () { + if (undoStack.Count == 0) + return; + + srcEditMtx.EnterWriteLock (); + string step = undoStack [undoStack.Count -1]; + redoStack.Add (source); + cmdRedo.CanExecute = true; + undoStack.RemoveAt(undoStack.Count -1); + + source = step; + + NotifyValueChanged ("Source", source); + NotifyValueChanged ("IsDirty", IsDirty); + cmdSave.CanExecute = IsDirty; + + if (undoStack.Count == 0) + cmdUndo.CanExecute = false; + srcEditMtx.ExitWriteLock (); + } + + void redo () { + if (redoStack.Count == 0) + return; + srcEditMtx.EnterWriteLock (); + string step = redoStack [redoStack.Count -1]; + undoStack.Add (source); + cmdUndo.CanExecute = true; + redoStack.RemoveAt(redoStack.Count -1); + source = step; + NotifyValueChanged ("Source", source); + NotifyValueChanged ("IsDirty", IsDirty); + cmdSave.CanExecute = IsDirty; + + if (redoStack.Count == 0) + cmdRedo.CanExecute = false; + srcEditMtx.ExitWriteLock (); + + } + public void OnQueryClose (object sender, EventArgs e){ if (IsDirty) { diff --git a/CrowIDE/src/SourceEditor/SourceEditor.cs b/CrowIDE/src/SourceEditor/SourceEditor.cs index 22666f53..14538135 100644 --- a/CrowIDE/src/SourceEditor/SourceEditor.cs +++ b/CrowIDE/src/SourceEditor/SourceEditor.cs @@ -208,9 +208,13 @@ namespace Crow.Coding buffer.ToogleFolding (line); } + #region Editor overrides protected override void updateEditorFromProjFile () { + buffer.editMutex.EnterWriteLock (); loadSource (); + buffer.editMutex.ExitWriteLock (); + isDirty = false; oldSource = projFile.Source; CurrentLine = requestedLine; @@ -231,6 +235,7 @@ namespace Crow.Coding protected override bool IsReady { get { return buffer != null; } } + #endregion #region Buffer events handlers void Buffer_BufferCleared (object sender, EventArgs e) @@ -830,6 +835,8 @@ namespace Crow.Coding Foreground.SetAsSource (gr); buffer.editMutex.EnterReadLock (); + editorMutex.EnterReadLock (); + #region draw text cursor if (buffer.SelectionInProgress){ selStartCol = getTabulatedColumn (buffer.SelectionStart); @@ -843,8 +850,6 @@ namespace Crow.Coding } #endregion - editorMutex.EnterReadLock (); - if (PrintedLines != null) { int unfoldedLines = buffer.UnfoldedLines; currentNode = null; @@ -1001,6 +1006,17 @@ namespace Crow.Coding case Key.S: projFile.Save (); break; + case Key.W: + editorMutex.EnterWriteLock (); + if (e.Shift) + projFile.Redo (null); + else + projFile.Undo (null); + editorMutex.ExitWriteLock (); + break; + default: + Console.WriteLine (""); + break; } } diff --git a/CrowIDE/src/SvgEditor.cs b/CrowIDE/src/SvgEditor.cs index dba622ea..219eea67 100644 --- a/CrowIDE/src/SvgEditor.cs +++ b/CrowIDE/src/SvgEditor.cs @@ -33,18 +33,49 @@ namespace Crow.Coding { SvgPicture _pic = new SvgPicture(); + int zoom; + + [DefaultValue(100)] + public int Zoom { + get { return zoom; } + set { + if (zoom == value) + return; + zoom = value; + NotifyValueChanged ("Zoom", zoom); + updateMaxScrolls (); + RegisterForGraphicUpdate (); + } + } + + void updateMaxScrolls() { + MaxScrollX = Math.Max(0, _pic.Dimensions.Width * zoom / 100 - Slot.Width); + MaxScrollY = Math.Max(0, _pic.Dimensions.Height * zoom / 100 - Slot.Height); + + if (Slot.Width + MaxScrollX > 0) + NotifyValueChanged ("ChildWidthRatio", Slot.Width * Slot.Width / (Slot.Width + MaxScrollX)); + else + NotifyValueChanged ("ChildWidthRatio", 0); + + if (Slot.Height + MaxScrollY > 0) + NotifyValueChanged ("ChildHeightRatio", Slot.Height * Slot.Height / (Slot.Height + MaxScrollY)); + else + NotifyValueChanged ("ChildHeightRatio", 0); + } + #region editor overrides protected override void updateEditorFromProjFile () { Error = null; try { editorMutex.EnterWriteLock(); _pic.LoadSvgFragment (projFile.Source); - _pic.Scaled = false; + _pic.Scaled = true; _pic.KeepProportions = true; } catch (Exception ex) { Error = ex; } editorMutex.ExitWriteLock (); + updateMaxScrolls (); RegisterForGraphicUpdate (); } protected override void updateProjFileFromEditor () @@ -57,6 +88,7 @@ namespace Crow.Coding throw new NotImplementedException (); } } + #endregion #region GraphicObject overrides protected override int measureRawSize (LayoutingType lt) @@ -74,10 +106,30 @@ namespace Crow.Coding { base.onDraw (gr); + Rectangle r = ClientRectangle; + Foreground.SetAsSource (gr, r); + gr.Rectangle (r, 0.1); + gr.Stroke (); + + r.Width = _pic.Dimensions.Width * zoom / 100; + r.Height = _pic.Dimensions.Height * zoom / 100; + + gr.Save (); + editorMutex.EnterReadLock (); + + gr.Translate (-ScrollX, -ScrollY); if (_pic != null) - _pic.Paint (gr, ClientRectangle); + _pic.Paint (gr, r); editorMutex.ExitReadLock (); + + gr.Restore (); + } + public override void OnLayoutChanges (LayoutingType layoutType) + { + base.OnLayoutChanges (layoutType); + if ((layoutType | LayoutingType.Sizing) > 0) + updateMaxScrolls (); } #endregion } diff --git a/CrowIDE/ui/CrowIDE.crow b/CrowIDE/ui/CrowIDE.crow index 6d056536..02aa6fd8 100644 --- a/CrowIDE/ui/CrowIDE.crow +++ b/CrowIDE/ui/CrowIDE.crow @@ -2,16 +2,16 @@ - + - - + + - - - + + + diff --git a/CrowIDE/ui/EditPaneItems.template b/CrowIDE/ui/EditPaneItems.template index 1279af9e..d0c0922f 100644 --- a/CrowIDE/ui/EditPaneItems.template +++ b/CrowIDE/ui/EditPaneItems.template @@ -8,18 +8,25 @@ - + - + Height="14" /> + + +