From 02b0e93049722f1f8afbdd1bf52b89e289e33c28 Mon Sep 17 00:00:00 2001
From: volte <100103+volte@users.noreply.github.com>
Date: Sun, 16 Jan 2022 14:42:45 -0500
Subject: [PATCH] Added radial drawing capability to Rectangle and Ellipse tool
 (#689)

---
 Builder.sln.DotSettings.user                     |   1 +
 Source/Plugins/BuilderModes/BuilderModes.csproj  |   3 +++
 .../BuilderModes/ClassicModes/DrawEllipseMode.cs |   4 ++++
 .../ClassicModes/DrawRectangleMode.cs            |  15 +++++++++++++++
 .../DrawEllipseOptionsPanel.Designer.cs          |  14 ++++++++++++++
 .../Interface/DrawEllipseOptionsPanel.cs         |   9 +++++++++
 .../DrawRectangleOptionsPanel.Designer.cs        |  14 ++++++++++++++
 .../Interface/DrawRectangleOptionsPanel.cs       |   9 +++++++++
 .../Properties/Resources.Designer.cs             |  10 ++++++++++
 .../BuilderModes/Properties/Resources.resx       |   3 +++
 Source/Plugins/BuilderModes/Resources/Radial.png | Bin 0 -> 789 bytes
 11 files changed, 82 insertions(+)
 create mode 100644 Source/Plugins/BuilderModes/Resources/Radial.png

diff --git a/Builder.sln.DotSettings.user b/Builder.sln.DotSettings.user
index 9af4ab9ee..ab84c80c9 100644
--- a/Builder.sln.DotSettings.user
+++ b/Builder.sln.DotSettings.user
@@ -5,5 +5,6 @@
 	<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=UDMF/@EntryIndexedValue">UDMF</s:String>
 	<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=Constants/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /&gt;</s:String>
 	<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateInstanceFields/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
+	<s:Boolean x:Key="/Default/ResxEditorPersonal/CheckedGroups/=BuilderModes_002FProperties_002FResources/@EntryIndexedValue">True</s:Boolean>
 	<s:Boolean x:Key="/Default/ResxEditorPersonal/CheckedGroups/=Builder_002FProperties_002FResources/@EntryIndexedValue">True</s:Boolean>
 	<s:Boolean x:Key="/Default/ResxEditorPersonal/Initialized/@EntryValue">True</s:Boolean></wpf:ResourceDictionary>
\ No newline at end of file
diff --git a/Source/Plugins/BuilderModes/BuilderModes.csproj b/Source/Plugins/BuilderModes/BuilderModes.csproj
index 1046e548a..8ceabcce7 100755
--- a/Source/Plugins/BuilderModes/BuilderModes.csproj
+++ b/Source/Plugins/BuilderModes/BuilderModes.csproj
@@ -755,6 +755,9 @@
   <ItemGroup>
     <None Include="Resources\Warning.png" />
   </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\Radial.png" />
+  </ItemGroup>
   <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
        Other similar extension points exist, see Microsoft.Common.targets.
diff --git a/Source/Plugins/BuilderModes/ClassicModes/DrawEllipseMode.cs b/Source/Plugins/BuilderModes/ClassicModes/DrawEllipseMode.cs
index 9deaf565b..f462069a1 100755
--- a/Source/Plugins/BuilderModes/ClassicModes/DrawEllipseMode.cs
+++ b/Source/Plugins/BuilderModes/ClassicModes/DrawEllipseMode.cs
@@ -68,10 +68,12 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			panel.OnValueChanged += OptionsPanelOnValueChanged;
 			panel.OnContinuousDrawingChanged += OnContinuousDrawingChanged;
 			panel.OnShowGuidelinesChanged += OnShowGuidelinesChanged;
+			panel.OnRadialDrawingChanged += OnRadialDrawingChanged;
 
 			// Needs to be set after adding the OnContinuousDrawingChanged event...
 			panel.ContinuousDrawing = General.Settings.ReadPluginSetting("drawellipsemode.continuousdrawing", false);
 			panel.ShowGuidelines = General.Settings.ReadPluginSetting("drawellipsemode.showguidelines", false);
+			panel.RadialDrawing = General.Settings.ReadPluginSetting("drawellipsemode.radialdrawing", false);
 		}
 
 		override protected void AddInterface() 
@@ -87,6 +89,8 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			General.Settings.WritePluginSetting("drawellipsemode.angle", panel.Angle);
 			General.Settings.WritePluginSetting("drawellipsemode.continuousdrawing", panel.ContinuousDrawing);
 			General.Settings.WritePluginSetting("drawellipsemode.showguidelines", panel.ShowGuidelines);
+			General.Settings.WritePluginSetting("drawellipsemode.radialdrawing", panel.RadialDrawing);
+			
 
 			// Remove the buttons
 			panel.Unregister();
diff --git a/Source/Plugins/BuilderModes/ClassicModes/DrawRectangleMode.cs b/Source/Plugins/BuilderModes/ClassicModes/DrawRectangleMode.cs
index adc805685..9b3da24f3 100755
--- a/Source/Plugins/BuilderModes/ClassicModes/DrawRectangleMode.cs
+++ b/Source/Plugins/BuilderModes/ClassicModes/DrawRectangleMode.cs
@@ -46,6 +46,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
 		protected int height;
 		protected int minpointscount;
 		protected bool alwaysrendershapehints;
+		protected bool radialdrawing;
 
 		private bool blockupdate;
 
@@ -102,10 +103,12 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			panel.OnValueChanged += OptionsPanelOnValueChanged;
 			panel.OnContinuousDrawingChanged += OnContinuousDrawingChanged;
 			panel.OnShowGuidelinesChanged += OnShowGuidelinesChanged;
+			panel.OnRadialDrawingChanged += OnRadialDrawingChanged;
 
 			// Needs to be set after adding the OnContinuousDrawingChanged event...
 			panel.ContinuousDrawing = General.Settings.ReadPluginSetting("drawrectanglemode.continuousdrawing", false);
 			panel.ShowGuidelines = General.Settings.ReadPluginSetting("drawrectanglemode.showguidelines", false);
+			panel.RadialDrawing = General.Settings.ReadPluginSetting("drawrectanglemode.radialdrawing", false);
 		}
 
 		protected override void AddInterface() 
@@ -120,6 +123,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			General.Settings.WritePluginSetting("drawrectanglemode.bevelwidth", bevelwidth);
 			General.Settings.WritePluginSetting("drawrectanglemode.continuousdrawing", panel.ContinuousDrawing);
 			General.Settings.WritePluginSetting("drawrectanglemode.showguidelines", panel.ShowGuidelines);
+			General.Settings.WritePluginSetting("drawrectanglemode.radialdrawing", panel.RadialDrawing);
 
 			// Remove the buttons
 			panel.Unregister();
@@ -317,6 +321,12 @@ namespace CodeImp.DoomBuilder.BuilderModes
 		{
 			if(!p1.pos.IsFinite() || !p2.pos.IsFinite()) return;
 
+			if (radialdrawing)
+			{
+				Vector2D delta = p2.pos - p1.pos;
+				p1.pos -= delta;
+			}
+
 			// Make sure start always stays at left and up from the end
 			if (p1.pos.x < p2.pos.x) 
 			{
@@ -504,6 +514,11 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			subdivisions = panel.Subdivisions;
 			Update();
 		}
+		
+		protected void OnRadialDrawingChanged(object value, EventArgs e)
+		{
+			radialdrawing = (bool)value;
+		}
 
 		#endregion
 
diff --git a/Source/Plugins/BuilderModes/Interface/DrawEllipseOptionsPanel.Designer.cs b/Source/Plugins/BuilderModes/Interface/DrawEllipseOptionsPanel.Designer.cs
index 8fd1fa200..282914177 100755
--- a/Source/Plugins/BuilderModes/Interface/DrawEllipseOptionsPanel.Designer.cs
+++ b/Source/Plugins/BuilderModes/Interface/DrawEllipseOptionsPanel.Designer.cs
@@ -30,6 +30,7 @@
 		{
 			this.toolStrip1 = new System.Windows.Forms.ToolStrip();
 			this.continuousdrawing = new System.Windows.Forms.ToolStripButton();
+			this.radialdrawing = new System.Windows.Forms.ToolStripButton();
 			this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
 			this.subdivslabel = new System.Windows.Forms.ToolStripLabel();
 			this.subdivs = new CodeImp.DoomBuilder.Controls.ToolStripNumericUpDown();
@@ -47,6 +48,7 @@
 			this.toolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
             this.continuousdrawing,
             this.showguidelines,
+            this.radialdrawing,
             this.toolStripSeparator1,
             this.subdivslabel,
             this.subdivs,
@@ -184,6 +186,17 @@
 			this.showguidelines.Text = "Guidelines";
 			this.showguidelines.CheckedChanged += new System.EventHandler(this.showguidelines_CheckedChanged);
 			// 
+			// radialdrawing
+			// 
+			this.radialdrawing.CheckOnClick = true;
+			this.radialdrawing.Image = global::CodeImp.DoomBuilder.BuilderModes.Properties.Resources.Radial;
+			this.radialdrawing.ImageTransparentColor = System.Drawing.Color.Magenta;
+			this.radialdrawing.Margin = new System.Windows.Forms.Padding(2, 1, 0, 2);
+			this.radialdrawing.Name = "radialdrawing";
+			this.radialdrawing.Size = new System.Drawing.Size(82, 22);
+			this.radialdrawing.Text = "Radial drawing";
+			this.radialdrawing.CheckedChanged += new System.EventHandler(this.radialdrawing_CheckedChanged);
+			// 
 			// DrawEllipseOptionsPanel
 			// 
 			this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
@@ -207,6 +220,7 @@
 		private CodeImp.DoomBuilder.Controls.ToolStripNumericUpDown spikiness;
 		private System.Windows.Forms.ToolStripButton reset;
 		private System.Windows.Forms.ToolStripButton continuousdrawing;
+		private System.Windows.Forms.ToolStripButton radialdrawing;
 		private System.Windows.Forms.ToolStripSeparator toolStripSeparator1;
 		private System.Windows.Forms.ToolStripLabel anglelabel;
 		private CodeImp.DoomBuilder.Controls.ToolStripNumericUpDown angle;
diff --git a/Source/Plugins/BuilderModes/Interface/DrawEllipseOptionsPanel.cs b/Source/Plugins/BuilderModes/Interface/DrawEllipseOptionsPanel.cs
index 042b80aca..af681df73 100755
--- a/Source/Plugins/BuilderModes/Interface/DrawEllipseOptionsPanel.cs
+++ b/Source/Plugins/BuilderModes/Interface/DrawEllipseOptionsPanel.cs
@@ -8,6 +8,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
 		public event EventHandler OnValueChanged;
 		public event EventHandler OnContinuousDrawingChanged;
 		public event EventHandler OnShowGuidelinesChanged;
+		public event EventHandler OnRadialDrawingChanged;
 
 		private bool blockevents;
 
@@ -20,6 +21,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
 		public int MinSpikiness { get { return (int)spikiness.Minimum; } set { spikiness.Minimum = value; } }
 		public bool ContinuousDrawing { get { return continuousdrawing.Checked; } set { continuousdrawing.Checked = value; } }
 		public bool ShowGuidelines { get { return showguidelines.Checked; } set { showguidelines.Checked = value; } }
+		public bool RadialDrawing { get { return radialdrawing.Checked; } set { radialdrawing.Checked = value; } }
 		
 		public DrawEllipseOptionsPanel() 
 		{
@@ -35,6 +37,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			General.Interface.BeginToolbarUpdate();
 			General.Interface.AddButton(continuousdrawing);
 			General.Interface.AddButton(showguidelines);
+			General.Interface.AddButton(radialdrawing);
 			General.Interface.AddButton(toolStripSeparator1);
 			General.Interface.AddButton(subdivslabel);
 			General.Interface.AddButton(subdivs);
@@ -59,6 +62,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			General.Interface.RemoveButton(toolStripSeparator1);
 			General.Interface.RemoveButton(showguidelines);
 			General.Interface.RemoveButton(continuousdrawing);
+			General.Interface.RemoveButton(radialdrawing);
 			General.Interface.EndToolbarUpdate();
 		}
 
@@ -89,5 +93,10 @@ namespace CodeImp.DoomBuilder.BuilderModes
 		{
 			if(OnShowGuidelinesChanged != null) OnShowGuidelinesChanged(showguidelines.Checked, EventArgs.Empty);
 		}
+		
+		private void radialdrawing_CheckedChanged(object sender, EventArgs e)
+		{
+			if(OnRadialDrawingChanged != null) OnRadialDrawingChanged(radialdrawing.Checked, EventArgs.Empty);
+		}
 	}
 }
diff --git a/Source/Plugins/BuilderModes/Interface/DrawRectangleOptionsPanel.Designer.cs b/Source/Plugins/BuilderModes/Interface/DrawRectangleOptionsPanel.Designer.cs
index 1ac5f0257..002bdc537 100755
--- a/Source/Plugins/BuilderModes/Interface/DrawRectangleOptionsPanel.Designer.cs
+++ b/Source/Plugins/BuilderModes/Interface/DrawRectangleOptionsPanel.Designer.cs
@@ -31,6 +31,7 @@
 			this.toolStrip1 = new System.Windows.Forms.ToolStrip();
 			this.continuousdrawing = new System.Windows.Forms.ToolStripButton();
 			this.showguidelines = new System.Windows.Forms.ToolStripButton();
+			this.radialdrawing = new System.Windows.Forms.ToolStripButton();
 			this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
 			this.radiuslabel = new System.Windows.Forms.ToolStripLabel();
 			this.radius = new CodeImp.DoomBuilder.Controls.ToolStripNumericUpDown();
@@ -45,6 +46,7 @@
 			this.toolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
             this.continuousdrawing,
             this.showguidelines,
+            this.radialdrawing,
             this.toolStripSeparator1,
             this.radiuslabel,
             this.radius,
@@ -78,6 +80,17 @@
 			this.showguidelines.Text = "Guidelines";
 			this.showguidelines.CheckedChanged += new System.EventHandler(this.showguidelines_CheckedChanged);
 			// 
+			// radialdrawing
+			// 
+			this.radialdrawing.CheckOnClick = true;
+			this.radialdrawing.Image = global::CodeImp.DoomBuilder.BuilderModes.Properties.Resources.Radial;
+			this.radialdrawing.ImageTransparentColor = System.Drawing.Color.Magenta;
+			this.radialdrawing.Margin = new System.Windows.Forms.Padding(2, 1, 0, 2);
+			this.radialdrawing.Name = "radialdrawing";
+			this.radialdrawing.Size = new System.Drawing.Size(82, 22);
+			this.radialdrawing.Text = "Radial drawing";
+			this.radialdrawing.CheckedChanged += new System.EventHandler(this.radialdrawing_CheckedChanged);
+			// 
 			// toolStripSeparator1
 			// 
 			this.toolStripSeparator1.Name = "toolStripSeparator1";
@@ -176,5 +189,6 @@
 		private System.Windows.Forms.ToolStripButton continuousdrawing;
 		private System.Windows.Forms.ToolStripSeparator toolStripSeparator1;
 		private System.Windows.Forms.ToolStripButton showguidelines;
+		private System.Windows.Forms.ToolStripButton radialdrawing;
 	}
 }
diff --git a/Source/Plugins/BuilderModes/Interface/DrawRectangleOptionsPanel.cs b/Source/Plugins/BuilderModes/Interface/DrawRectangleOptionsPanel.cs
index cd880049a..f60b60d48 100755
--- a/Source/Plugins/BuilderModes/Interface/DrawRectangleOptionsPanel.cs
+++ b/Source/Plugins/BuilderModes/Interface/DrawRectangleOptionsPanel.cs
@@ -8,6 +8,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
 		public event EventHandler OnValueChanged;
 		public event EventHandler OnContinuousDrawingChanged;
 		public event EventHandler OnShowGuidelinesChanged;
+		public event EventHandler OnRadialDrawingChanged;
 
 		private bool blockevents;
 
@@ -19,6 +20,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
 		public int MinSubdivisions { get { return (int)subdivs.Minimum; } set { subdivs.Minimum = value; } }
 		public bool ContinuousDrawing { get { return continuousdrawing.Checked; } set { continuousdrawing.Checked = value; } }
 		public bool ShowGuidelines { get { return showguidelines.Checked; } set { showguidelines.Checked = value; } }
+		public bool RadialDrawing { get { return radialdrawing.Checked; } set { radialdrawing.Checked = value; } }
 
 		public DrawRectangleOptionsPanel() 
 		{
@@ -33,6 +35,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			General.Interface.BeginToolbarUpdate();
 			General.Interface.AddButton(continuousdrawing);
 			General.Interface.AddButton(showguidelines);
+			General.Interface.AddButton(radialdrawing);
 			General.Interface.AddButton(toolStripSeparator1);
 			General.Interface.AddButton(radiuslabel);
 			General.Interface.AddButton(radius);
@@ -53,6 +56,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			General.Interface.RemoveButton(toolStripSeparator1);
 			General.Interface.RemoveButton(showguidelines);
 			General.Interface.RemoveButton(continuousdrawing);
+			General.Interface.RemoveButton(radialdrawing);
 			General.Interface.EndToolbarUpdate();
 		}
 
@@ -82,5 +86,10 @@ namespace CodeImp.DoomBuilder.BuilderModes
 		{
 			if(OnShowGuidelinesChanged != null) OnShowGuidelinesChanged(showguidelines.Checked, EventArgs.Empty);
 		}
+		
+		private void radialdrawing_CheckedChanged(object sender, EventArgs e)
+		{
+			if(OnRadialDrawingChanged != null) OnRadialDrawingChanged(radialdrawing.Checked, EventArgs.Empty);
+		}
 	}
 }
diff --git a/Source/Plugins/BuilderModes/Properties/Resources.Designer.cs b/Source/Plugins/BuilderModes/Properties/Resources.Designer.cs
index b600770f9..9505d1834 100755
--- a/Source/Plugins/BuilderModes/Properties/Resources.Designer.cs
+++ b/Source/Plugins/BuilderModes/Properties/Resources.Designer.cs
@@ -450,6 +450,16 @@ namespace CodeImp.DoomBuilder.BuilderModes.Properties {
             }
         }
         
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap Radial {
+            get {
+                object obj = ResourceManager.GetObject("Radial", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
         /// <summary>
         ///   Looks up a localized resource of type System.Drawing.Bitmap.
         /// </summary>
diff --git a/Source/Plugins/BuilderModes/Properties/Resources.resx b/Source/Plugins/BuilderModes/Properties/Resources.resx
index 6697ef8e4..97dbda635 100755
--- a/Source/Plugins/BuilderModes/Properties/Resources.resx
+++ b/Source/Plugins/BuilderModes/Properties/Resources.resx
@@ -199,6 +199,9 @@
   <data name="Guidelines" type="System.Resources.ResXFileRef, System.Windows.Forms">
     <value>..\Resources\Guidelines.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
   </data>
+  <data name="Radial" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\Radial.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
   <data name="DrawGridMode" type="System.Resources.ResXFileRef, System.Windows.Forms">
     <value>..\Resources\DrawGridMode.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
   </data>
diff --git a/Source/Plugins/BuilderModes/Resources/Radial.png b/Source/Plugins/BuilderModes/Resources/Radial.png
new file mode 100644
index 0000000000000000000000000000000000000000..0702a267a424909a635b95d0a79db63b72d97209
GIT binary patch
literal 789
zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s73p1Ua12U7785lGsmQJ+w
zJ{%y@c7L0ftF~yV#-j-fyPUaQ9c7j_#jbLWKDf%eX!aJTNo})5G}kqCJ0El``I!Ad
z{)N^KEsiFo4vU}6f1;KgDW2`ry+!@boc8bYz8AdT*<ioc`0zVVhPIa<e6%#zKD)l;
zfpv|<Ap@n3Q)jkK+th7Y(mUUM)v}6??zp?Jt&TZ3Zk2rST6tcoSb4|u&dbq#sulee
zQ>H#)`p8+>bD6O-zja;3AGIAXK2A@VcUp&`?qaakwvCsLtvSN`Nb}K(h2asOZ62v9
zUX3{!B)8a<Pg-)xgccT7(Hy7tW{cFxY1eK}&-gJdP>p}_{#Gpu%Px(H=5AT7yH-sx
zy%hSZB;@Fw|K~4XOIx=0-9nWMzhCW|FYHhtzv6n#_wQFqU#B}fVBKLB{m<xZ=DXQn
zqP)B1m><eM__S=PCi{V_dIFW(QuNH1FzD`I#wag-AVE%IC;PAKdm~N17ye^;vh8K(
zyN1Kc36owOmahM{IfIQQ%D;_)fq}EYBeIx*fm;ZK886+f`@_J%=;i6+7-HeSbaG@K
zlc9jiapemFM;1Mi=*Zu}U|G7u;ZtuBAB&*31JBnrStnUOwJx1>``yvlyKk>-d+Qw<
zYP(P{>!FSeZ%Wwls+<Y>*W@i8*a)#XUGG{en|!!1Lt%c)e4|eaOSf=kr<xY3t$lx@
zNMrW<Lusdym+(|r>Ray5KKzjHTC1jA=}AlL*Hig57hE&fU7=WhLDX@@Wy_aIF&`d>
z^4OQ!PxjduvGv`)5_9vdd&^#JQFSO$2zs`4pR8DgcbwG&KX(U)0+p*7qO8mpUY$&A
zRA!to_v}KB58e95{B?~w6gjy9nv665FKy`CrLwqcS4Y5!;Ae`J#q2B0jz&paTQ&Hl
z=SXO%ZPwHbc>BV*wYMu+`BGk&<wL#y+(r&3bDlqS>@vIi2INZdtPffbFQz92%-B}(
s_G0=ihsJxG4F0{hKEC?Pzh~C*jHN%<O<5(E21@P>p00i_>zopr0457&*#H0l

literal 0
HcmV?d00001

-- 
GitLab