forked from gitextensions/gitextensions
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSplitterManager.cs
148 lines (131 loc) · 5.86 KB
/
SplitterManager.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using GitExtUtils.GitUI;
using GitUIPluginInterfaces;
namespace GitUI
{
public sealed class SplitterManager
{
private readonly List<SplitterData> _splitters = new();
private readonly ISettingsSource _settings;
public SplitterManager(ISettingsSource settings)
{
_settings = settings;
}
public void AddSplitter(SplitContainer splitter, string settingName, int? defaultDistance = null)
{
_splitters.Add(new SplitterData(
splitter,
settingName,
DpiUtil.DpiX,
defaultDistance));
}
public void RestoreSplitters()
{
foreach (var splitter in _splitters)
{
splitter.RestoreFromSettings(_settings);
}
}
public void SaveSplitters()
{
foreach (var splitter in _splitters)
{
splitter.SaveToSettings(_settings);
}
}
private sealed class SplitterData
{
private readonly SplitContainer _splitter;
private readonly string _settingName;
private readonly int _dpi;
private readonly int? _defaultDistance;
public SplitterData(SplitContainer splitter, string settingName, int dpi, int? defaultDistance)
{
_splitter = splitter;
_settingName = settingName;
_dpi = dpi;
_defaultDistance = defaultDistance;
}
private int SplitterSize => _splitter.Orientation == Orientation.Horizontal ? _splitter.Height : _splitter.Width;
private string SizeSettingsKey => _settingName + "_Size";
private string DpiSettingsKey => _settingName + "_Dpi";
private string DistanceSettingsKey => _settingName + "_Distance";
private string FontSizeSettingsKey => _settingName + "_FontSize";
private string Panel1CollapsedSettingsKey => _settingName + "_Panel1Collapsed";
public void RestoreFromSettings(ISettingsSource settings)
{
_splitter.BeginInit();
_splitter.SuspendLayout();
int prevDpi = settings.GetInt(DpiSettingsKey) ?? DpiUtil.DpiX;
int prevSize = settings.GetInt(SizeSettingsKey) ?? 0;
int prevDistance = settings.GetInt(DistanceSettingsKey) ?? 0;
if (prevSize > 0 && prevDistance > 0)
{
var fixedPanel = _splitter.FixedPanel;
var splitterWidth = _splitter.SplitterWidth;
if (SplitterSize == prevSize && _dpi == prevDpi)
{
SetSplitterDistance(fixedPanel == FixedPanel.Panel2 ? prevDistance + splitterWidth : prevDistance);
}
else
{
switch (fixedPanel)
{
case FixedPanel.None:
// At this point, the property "SplitterSize" has its original value from design time,
// i.e. the actual size after opening the window is unknown yet. The calculation below
// determines the resulting splitter distance by the ratio of both sides of the splitter.
SetSplitterDistance((float)SplitterSize * prevDistance / prevSize);
break;
case FixedPanel.Panel1:
SetSplitterDistance(DpiUtil.Scale(prevDistance, prevDpi));
break;
case FixedPanel.Panel2:
int panel2PrevSize = DpiUtil.Scale(prevSize, prevDpi) - DpiUtil.Scale(prevDistance, prevDpi);
const int paddingOffset = 2; // Refer to FormCommit.ctor+WorkaroundPaddingIncreaseBug
SetSplitterDistance(SplitterSize - panel2PrevSize - paddingOffset + splitterWidth);
break;
}
}
}
_splitter.Panel1Collapsed = settings.GetBool(Panel1CollapsedSettingsKey, defaultValue: false);
_splitter.ResumeLayout();
_splitter.EndInit();
}
public void SaveToSettings(ISettingsSource settings)
{
settings.SetInt(DpiSettingsKey, _dpi);
settings.SetInt(SizeSettingsKey, SplitterSize);
settings.SetInt(DistanceSettingsKey, _splitter.SplitterDistance);
settings.SetFloat(FontSizeSettingsKey, _splitter.Font.Size);
settings.SetBool(Panel1CollapsedSettingsKey, _splitter.Panel1Collapsed);
}
private void SetSplitterDistance(float distance)
{
try
{
int intDistance = Convert.ToInt32(distance);
if (IsValidSplitterDistance(intDistance))
{
_splitter.SplitterDistance = intDistance;
}
else if (_defaultDistance.HasValue && IsValidSplitterDistance(_defaultDistance.Value))
{
_splitter.SplitterDistance = _defaultDistance.Value;
}
}
catch
{
// The attempt to set even the default value has failed.
}
bool IsValidSplitterDistance(int d)
{
return d > _splitter.Panel1MinSize &&
d < SplitterSize - _splitter.Panel2MinSize;
}
}
}
}
}