<h2 dir="auto"><g-emoji class="g-emoji" alias="information_source" fallback-src="https://github.githubassets.com/images/icons/emoji/unicode/2139.png">ℹ</g-emoji> Computer information</h2>
<ul dir="auto">
<li>PowerToys version: 0.23.0</li>
<li>PowerToy Utility: FancyZones</li>
<li>Running PowerToys as Admin: No</li>
<li>Windows build number: 1909 (18363.1082)</li>
</ul>
<h2 dir="auto"><g-emoji class="g-emoji" alias="memo" fallback-src="https://github.githubassets.com/images/icons/emoji/unicode/1f4dd.png">📝</g-emoji> Provide detailed reproduction steps (if any)</h2>
<ol dir="auto">
<li>Open the FZ editor with Win+`</li>
<li>Set the number of zones to 7</li>
<li>Select the Priority Grid layout</li>
<li>Select "Edit selected layout"</li>
<li>Drag the slider between zone 3 and zone 5 up and down repeatedly.</li>
</ol>
<h3 dir="auto"><g-emoji class="g-emoji" alias="heavy_check_mark" fallback-src="https://github.githubassets.com/images/icons/emoji/unicode/2714.png">✔️</g-emoji> Expected result</h3>
<p dir="auto">Zones 3/5 resize.</p>
<h3 dir="auto">❌ Actual result</h3>
<p dir="auto"><em>What is the actual result of the above steps?</em><br>
Zone 4,5 continually increases in size, and zones 1,6,7 decrease to accomodate. See screenshot</p>
<h2 dir="auto"><g-emoji class="g-emoji" alias="camera" fallback-src="https://github.githubassets.com/images/icons/emoji/unicode/1f4f7.png">📷</g-emoji> Screenshots</h2>
<p dir="auto"><em>Are there any useful screenshots? WinKey+Shift+S and then just paste them directly into the form</em><br>
<a target="_blank" rel="noopener noreferrer nofollow" href="https://user-images.githubusercontent.com/43283738/94722765-96d58a80-030c-11eb-8312-e3b1257080f7.png"><img src="https://user-images.githubusercontent.com/43283738/94722765-96d58a80-030c-11eb-8312-e3b1257080f7.png" alt="image" style="max-width: 100%;"></a></p>
<h1 dir="auto">Summary of the new feature/enhancement</h1>
<p dir="auto">Improve current implementation of the FancyZones Editor that is complicated and hard to maintain.<br>
Proposal created in cooperation with <a class="user-mention notranslate" data-hovercard-type="user" data-hovercard-url="/users/ivan100sic/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/ivan100sic">@ivan100sic</a>.</p>

<h1 dir="auto">Proposed technical implementation details (optional)</h1>
<h3 dir="auto">Data structures:</h3>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="Zone: {
    int index;
    double width; 
    double height;
    double x;
    double y;
}

Splitter: {
    Orientation orientation; //Horizontal or Vertical
    double position;
    List&lt;int&gt; negativeSideIndexes; //left/top zone indexes
    List&lt;int&gt; positiveSideIndexes; //right/bottom zone indexes
}"><pre class="notranslate"><code class="notranslate">Zone: {
    int index;
    double width; 
    double height;
    double x;
    double y;
}

Splitter: {
    Orientation orientation; //Horizontal or Vertical
    double position;
    List&lt;int&gt; negativeSideIndexes; //left/top zone indexes
    List&lt;int&gt; positiveSideIndexes; //right/bottom zone indexes
}
</code></pre></div>
<h2 dir="auto">Use cases</h2>
<h3 dir="auto">Drag splitter:</h3>
<ul dir="auto">
<li>Move left: reduce width/height for each grid zone that has index contained in <code class="notranslate">negativeSideIndexes</code> and increase those parameters for <code class="notranslate">positiveSideIndexes</code>.</li>
<li>Move right: similarly</li>
</ul>
<p dir="auto"><strong>Move is possible until every zone width/height is bigger than some small constant, ideally so that zone index numbers are not clipped.</strong></p>
<h3 dir="auto">Split zone:</h3>
<ul dir="auto">
<li>
<p dir="auto">Non-snapped, snapped non-adjacent: update indexes in <code class="notranslate">zones</code> and in <code class="notranslate">splitters</code></p>
<p dir="auto"><em>Rule for updating splitters:</em></p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="index &gt; splittedIndex -&gt; index++
index == splittedIndex &amp;&amp; orientation != newSplitterOrientation -&gt; insert(index + 1)
index == splittedIndex &amp;&amp; orientation == newSplitterOrientation &amp;&amp; list == negativeSideIndexes -&gt; index++"><pre class="notranslate"><code class="notranslate">index &gt; splittedIndex -&gt; index++
index == splittedIndex &amp;&amp; orientation != newSplitterOrientation -&gt; insert(index + 1)
index == splittedIndex &amp;&amp; orientation == newSplitterOrientation &amp;&amp; list == negativeSideIndexes -&gt; index++
</code></pre></div>
</li>
</ul>
<p dir="auto"><em>Examples:</em></p>
<p dir="auto"><a target="_blank" rel="noopener noreferrer nofollow" href="https://user-images.githubusercontent.com/8949536/87671359-e975c080-c779-11ea-8317-abefe5162cd4.png"><img src="https://user-images.githubusercontent.com/8949536/87671359-e975c080-c779-11ea-8317-abefe5162cd4.png" alt="image" style="max-width: 100%;"></a></p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="splittedIndex == 0
newSplitterOrientation == Horizontal

Splitters update:
{ orientation: Horizontal, negativeSideIndexes: [ 0, 1 ], positiveSideIndexes: [ 2, 3 ] } -&gt; { orientation: Horizontal, negativeSideIndexes: [ 1, 2 ], positiveSideIndexes: [ 3, 4 ] } 
{ orientation: Vertical, negativeSideIndexes: [ 0, 2 ], positiveSideIndexes: [ 1, 3 ] } -&gt; { orientation: Vertical, negativeSideIndexes: [ 0, 1, 3 ], positiveSideIndexes: [ 2, 4 ] } "><pre class="notranslate"><code class="notranslate">splittedIndex == 0
newSplitterOrientation == Horizontal

Splitters update:
{ orientation: Horizontal, negativeSideIndexes: [ 0, 1 ], positiveSideIndexes: [ 2, 3 ] } -&gt; { orientation: Horizontal, negativeSideIndexes: [ 1, 2 ], positiveSideIndexes: [ 3, 4 ] } 
{ orientation: Vertical, negativeSideIndexes: [ 0, 2 ], positiveSideIndexes: [ 1, 3 ] } -&gt; { orientation: Vertical, negativeSideIndexes: [ 0, 1, 3 ], positiveSideIndexes: [ 2, 4 ] } 
</code></pre></div>
<p dir="auto"><a target="_blank" rel="noopener noreferrer nofollow" href="https://user-images.githubusercontent.com/8949536/87671507-20e46d00-c77a-11ea-8ab2-c1cc6361651f.png"><img src="https://user-images.githubusercontent.com/8949536/87671507-20e46d00-c77a-11ea-8ab2-c1cc6361651f.png" alt="image" style="max-width: 100%;"></a></p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="splittedIndex == 1
newSplitterOrientation == Horizontal

Splitters update:
{ orientation: Horizontal, negativeSideIndexes: [ 0, 1 ], positiveSideIndexes: [ 2, 3 ] } -&gt; { orientation: Horizontal, negativeSideIndexes: [ 0, 2 ], positiveSideIndexes: [ 3, 4 ] } 
{ orientation: Vertical, negativeSideIndexes: [ 0, 2 ], positiveSideIndexes: [ 1, 3 ] } -&gt; { orientation: Vertical, negativeSideIndexes: [ 0, 3 ], positiveSideIndexes: [ 1, 2, 4 ] } "><pre class="notranslate"><code class="notranslate">splittedIndex == 1
newSplitterOrientation == Horizontal

Splitters update:
{ orientation: Horizontal, negativeSideIndexes: [ 0, 1 ], positiveSideIndexes: [ 2, 3 ] } -&gt; { orientation: Horizontal, negativeSideIndexes: [ 0, 2 ], positiveSideIndexes: [ 3, 4 ] } 
{ orientation: Vertical, negativeSideIndexes: [ 0, 2 ], positiveSideIndexes: [ 1, 3 ] } -&gt; { orientation: Vertical, negativeSideIndexes: [ 0, 3 ], positiveSideIndexes: [ 1, 2, 4 ] } 
</code></pre></div>
<p dir="auto"><a target="_blank" rel="noopener noreferrer nofollow" href="https://user-images.githubusercontent.com/8949536/87671514-2477f400-c77a-11ea-940e-3fec89b2fd79.png"><img src="https://user-images.githubusercontent.com/8949536/87671514-2477f400-c77a-11ea-940e-3fec89b2fd79.png" alt="image" style="max-width: 100%;"></a></p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="splittedIndex == 2
newSplitterOrientation == Horizontal

Splitters update:
{ orientation: Horizontal, negativeSideIndexes: [ 0, 1 ], positiveSideIndexes: [ 2, 3 ] } -&gt; { orientation: Horizontal, negativeSideIndexes: [ 0, 1 ], positiveSideIndexes: [ 2, 4 ] } 
{ orientation: Vertical, negativeSideIndexes: [ 0, 2 ], positiveSideIndexes: [ 1, 3 ] } -&gt; { orientation: Vertical, negativeSideIndexes: [ 0, 2, 3 ], positiveSideIndexes: [ 1, 4 ] } "><pre class="notranslate"><code class="notranslate">splittedIndex == 2
newSplitterOrientation == Horizontal

Splitters update:
{ orientation: Horizontal, negativeSideIndexes: [ 0, 1 ], positiveSideIndexes: [ 2, 3 ] } -&gt; { orientation: Horizontal, negativeSideIndexes: [ 0, 1 ], positiveSideIndexes: [ 2, 4 ] } 
{ orientation: Vertical, negativeSideIndexes: [ 0, 2 ], positiveSideIndexes: [ 1, 3 ] } -&gt; { orientation: Vertical, negativeSideIndexes: [ 0, 2, 3 ], positiveSideIndexes: [ 1, 4 ] } 
</code></pre></div>
<p dir="auto"><a target="_blank" rel="noopener noreferrer nofollow" href="https://user-images.githubusercontent.com/8949536/87671525-26da4e00-c77a-11ea-8ede-f9a479d8e8b4.png"><img src="https://user-images.githubusercontent.com/8949536/87671525-26da4e00-c77a-11ea-8ede-f9a479d8e8b4.png" alt="image" style="max-width: 100%;"></a></p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="splittedIndex == 3
newSplitterOrientation == Horizontal

Splitters update:
{ orientation: Horizontal, negativeSideIndexes: [ 0, 1 ], positiveSideIndexes: [ 2, 3 ] } -&gt; { orientation: Horizontal, negativeSideIndexes: [ 0, 1 ], positiveSideIndexes: [ 2, 3 ] } 
{ orientation: Vertical, negativeSideIndexes: [ 0, 2 ], positiveSideIndexes: [ 1, 3 ] } -&gt; { orientation: Vertical, negativeSideIndexes: [ 0, 2 ], positiveSideIndexes: [ 1, 3, 4 ] } "><pre class="notranslate"><code class="notranslate">splittedIndex == 3
newSplitterOrientation == Horizontal

Splitters update:
{ orientation: Horizontal, negativeSideIndexes: [ 0, 1 ], positiveSideIndexes: [ 2, 3 ] } -&gt; { orientation: Horizontal, negativeSideIndexes: [ 0, 1 ], positiveSideIndexes: [ 2, 3 ] } 
{ orientation: Vertical, negativeSideIndexes: [ 0, 2 ], positiveSideIndexes: [ 1, 3 ] } -&gt; { orientation: Vertical, negativeSideIndexes: [ 0, 2 ], positiveSideIndexes: [ 1, 3, 4 ] } 
</code></pre></div>
<ul dir="auto">
<li>
<p dir="auto">Snapped adjacent:<br>
Update existing splitter if</p>
<ul dir="auto">
<li>orientation same</li>
<li>position same</li>
<li>one of the zones from negativeSideIndexes has bottom/right side == splitted zone top/left</li>
<li>one of the zones from positiveSideIndexes has top/left side == splitted zone bottom/right</li>
</ul>
<p dir="auto">Otherwise add new splitter</p>
</li>
</ul>
<p dir="auto"><strong>Don't to show splitter if it splits the zone into two pieces which are too small (less  than Minimum Bounding Rectangle).</strong></p>
<h3 dir="auto">Merge zones</h3>
<ul dir="auto">
<li>Remove merged zones and add a new zone corresponding to Minimum Bounding Rectangle (use the closure algorithm <code class="notranslate">ExtendRangeToHaveEvenCellEdges</code> that should be reimplemented to work with a list of rectangles instead of cell child map).</li>
<li>Update zone indexes</li>
<li>Update splitters
<ul dir="auto">
<li>Replace merged zones indexes with first merged zone index</li>
<li>Update other indexes</li>
<li>if <code class="notranslate">negativeSideIndexes</code> and <code class="notranslate">positiveSideIndexes</code> both contain same index after previous steps, remove that index from both lists</li>
<li>if <code class="notranslate">negativeSideIndexes</code> or <code class="notranslate">positiveSideIndexes</code> contain only merged indexes, remove splitter</li>
</ul>
</li>
</ul>
<p dir="auto"><em>Example:</em><br>
<a target="_blank" rel="noopener noreferrer nofollow" href="https://user-images.githubusercontent.com/8949536/87672511-c21ff300-c77b-11ea-95fc-2449973a796a.png"><img src="https://user-images.githubusercontent.com/8949536/87672511-c21ff300-c77b-11ea-95fc-2449973a796a.png" alt="image" style="max-width: 100%;"></a></p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="merged: [ 2, 3, 7, 8, 9 ]

Splitters
{ Horizontal, negativeSideIndexes: [ 3 ], positiveSideIndexes: [ 8, 9 ] } -&gt; removed
{ Horizontal, negativeSideIndexes: [ 1, 2 ], positiveSideIndexes: [ 5, 6, 7 ] } -&gt; { Horizontal, negativeSideIndexes: [ 1 ], positiveSideIndexes: [ 5, 6 ] }
{ Horizontal, negativeSideIndexes: [ 7, 8, 9 ], positiveSideIndexes: [ 10, 11 ] } -&gt; { Horizontal, negativeSideIndexes: [ 2 ], positiveSideIndexes: [ 10, 11 ] }
{ Vertical, negativeSideIndexes: [ 5 ], positiveSideIndexes: [ 6 ] } -&gt; { Vertical, negativeSideIndexes: [ 5 ], positiveSideIndexes: [ 6 ] }
{ Vertical, negativeSideIndexes: [ 1, 6 ], positiveSideIndexes: [ 2, 7, 10 ] } -&gt; { Vertical, negativeSideIndexes: [ 1, 6 ], positiveSideIndexes: [ 2, 10 ] }
{ Vertical, negativeSideIndexes: [ 2, 7, 10 ], positiveSideIndexes: [ 3, 8, 11 ] } -&gt; { Vertical, negativeSideIndexes: [ 2, 6 ], positiveSideIndexes: [ 2, 7 ] } -&gt; { Vertical, negativeSideIndexes: [ 6 ], positiveSideIndexes: [ 7 ] }
{ Vertical, negativeSideIndexes: [ 8 ], positiveSideIndexes: [ 9 ] } -&gt; removed
{ Vertical, negativeSideIndexes: [ 3, 9, 11 ], positiveSideIndexes: [ 4, 12 ] } -&gt; { Vertical, negativeSideIndexes: [ 2, 7 ], positiveSideIndexes: [ 3, 8 ] }"><pre class="notranslate"><code class="notranslate">merged: [ 2, 3, 7, 8, 9 ]

Splitters
{ Horizontal, negativeSideIndexes: [ 3 ], positiveSideIndexes: [ 8, 9 ] } -&gt; removed
{ Horizontal, negativeSideIndexes: [ 1, 2 ], positiveSideIndexes: [ 5, 6, 7 ] } -&gt; { Horizontal, negativeSideIndexes: [ 1 ], positiveSideIndexes: [ 5, 6 ] }
{ Horizontal, negativeSideIndexes: [ 7, 8, 9 ], positiveSideIndexes: [ 10, 11 ] } -&gt; { Horizontal, negativeSideIndexes: [ 2 ], positiveSideIndexes: [ 10, 11 ] }
{ Vertical, negativeSideIndexes: [ 5 ], positiveSideIndexes: [ 6 ] } -&gt; { Vertical, negativeSideIndexes: [ 5 ], positiveSideIndexes: [ 6 ] }
{ Vertical, negativeSideIndexes: [ 1, 6 ], positiveSideIndexes: [ 2, 7, 10 ] } -&gt; { Vertical, negativeSideIndexes: [ 1, 6 ], positiveSideIndexes: [ 2, 10 ] }
{ Vertical, negativeSideIndexes: [ 2, 7, 10 ], positiveSideIndexes: [ 3, 8, 11 ] } -&gt; { Vertical, negativeSideIndexes: [ 2, 6 ], positiveSideIndexes: [ 2, 7 ] } -&gt; { Vertical, negativeSideIndexes: [ 6 ], positiveSideIndexes: [ 7 ] }
{ Vertical, negativeSideIndexes: [ 8 ], positiveSideIndexes: [ 9 ] } -&gt; removed
{ Vertical, negativeSideIndexes: [ 3, 9, 11 ], positiveSideIndexes: [ 4, 12 ] } -&gt; { Vertical, negativeSideIndexes: [ 2, 7 ], positiveSideIndexes: [ 3, 8 ] }
</code></pre></div>