From 038171c5888d33607631e28317776c0cb7290e42 Mon Sep 17 00:00:00 2001 From: Robin Date: Fri, 18 Sep 2015 10:22:52 +0100 Subject: [PATCH] DarkScrollBar --- DarkUI/Config/Consts.cs | 4 + DarkUI/Config/Enums.cs | 6 + DarkUI/Controls/DarkLabel.cs | 19 +- DarkUI/Controls/DarkScrollBar.cs | 531 ++++++++++++++++++ .../EventArgs/ScrollValueEventArgs.cs | 14 + DarkUI/DarkUI.csproj | 26 + DarkUI/Icons/ScrollIcons.Designer.cs | 103 ++++ DarkUI/Icons/ScrollIcons.resx | 133 +++++ DarkUI/Resources/scrollbar_arrow.png | Bin 0 -> 15222 bytes DarkUI/Resources/scrollbar_arrow_clicked.png | Bin 0 -> 15228 bytes DarkUI/Resources/scrollbar_arrow_hot.png | Bin 0 -> 15228 bytes DarkUI/Resources/scrollbar_arrow_standard.png | Bin 0 -> 15228 bytes Example/Forms/MainForm.Designer.cs | 46 ++ 13 files changed, 880 insertions(+), 2 deletions(-) create mode 100644 DarkUI/Controls/DarkScrollBar.cs create mode 100644 DarkUI/Controls/EventArgs/ScrollValueEventArgs.cs create mode 100644 DarkUI/Icons/ScrollIcons.Designer.cs create mode 100644 DarkUI/Icons/ScrollIcons.resx create mode 100644 DarkUI/Resources/scrollbar_arrow.png create mode 100644 DarkUI/Resources/scrollbar_arrow_clicked.png create mode 100644 DarkUI/Resources/scrollbar_arrow_hot.png create mode 100644 DarkUI/Resources/scrollbar_arrow_standard.png diff --git a/DarkUI/Config/Consts.cs b/DarkUI/Config/Consts.cs index 3586b06..19e252b 100644 --- a/DarkUI/Config/Consts.cs +++ b/DarkUI/Config/Consts.cs @@ -3,5 +3,9 @@ public sealed class Consts { public static int Padding = 10; + + public static int ScrollBarSize = 15; + public static int ArrowButtonSize = 15; + public static int MinimumThumbSize = 11; } } diff --git a/DarkUI/Config/Enums.cs b/DarkUI/Config/Enums.cs index c497934..4e1029f 100644 --- a/DarkUI/Config/Enums.cs +++ b/DarkUI/Config/Enums.cs @@ -19,4 +19,10 @@ Left, Right } + + public enum DarkOrientation + { + Vertical, + Horizontal + } } diff --git a/DarkUI/Controls/DarkLabel.cs b/DarkUI/Controls/DarkLabel.cs index adc9e29..64ed4d7 100644 --- a/DarkUI/Controls/DarkLabel.cs +++ b/DarkUI/Controls/DarkLabel.cs @@ -16,8 +16,8 @@ namespace DarkUI #region Property Region - [Category("Appearance")] - [Description("Determines whether the label will automatically update height based on content.")] + [Category("Layout")] + [Description("Enables automatic height sizing based on the contents of the label.")] [DefaultValue(false)] public bool AutoUpdateHeight { @@ -34,6 +34,21 @@ namespace DarkUI } } + [Category("Layout")] + [Description("Enables automatic resizing based on font size. Note that this is only valid for label controls that do not wrap text.")] + [DefaultValue(true)] + public new bool AutoSize + { + get { return base.AutoSize; } + set + { + base.AutoSize = value; + + if (AutoSize) + AutoUpdateHeight = false; + } + } + #endregion #region Constructor Region diff --git a/DarkUI/Controls/DarkScrollBar.cs b/DarkUI/Controls/DarkScrollBar.cs new file mode 100644 index 0000000..878f69c --- /dev/null +++ b/DarkUI/Controls/DarkScrollBar.cs @@ -0,0 +1,531 @@ +using System; +using System.ComponentModel; +using System.Drawing; +using System.Windows.Forms; + +namespace DarkUI +{ + public class DarkScrollBar : Control + { + #region Event Region + + public event EventHandler ValueChanged; + + #endregion + + #region Field Region + + private DarkOrientation _scrollOrientation; + + private int _value; + private int _minimum = 0; + private int _maximum = 100; + + private int _viewSize; + + private Rectangle _trackArea; + private float _viewContentRatio; + + private Rectangle _thumbArea; + private Rectangle _upArrowArea; + private Rectangle _downArrowArea; + + private bool _thumbHot; + private bool _upArrowHot; + private bool _downArrowHot; + + private bool _thumbClicked; + private bool _upArrowClicked; + private bool _downArrowClicked; + + private bool _isScrolling; + private int _initialValue; + private Point _initialContact; + + private Timer _scrollTimer; + + #endregion + + #region Property Region + + [Category("Behavior")] + [Description("The orientation type of the scrollbar.")] + [DefaultValue(DarkOrientation.Vertical)] + public DarkOrientation ScrollOrientation + { + get { return _scrollOrientation; } + set + { + _scrollOrientation = value; + UpdateScrollBar(); + } + } + + [Category("Behavior")] + [Description("The value that the scroll thumb position represents.")] + [DefaultValue(0)] + public int Value + { + get { return _value; } + set + { + if (value < Minimum) + value = Minimum; + + var maximumValue = Maximum - ViewSize; + if (value > maximumValue) + value = maximumValue; + + if (_value == value) + return; + + _value = value; + + UpdateThumb(true); + + if (ValueChanged != null) + ValueChanged(this, new ScrollValueEventArgs(Value)); + } + } + + [Category("Behavior")] + [Description("The lower limit value of the scrollable range.")] + [DefaultValue(0)] + public int Minimum + { + get { return _minimum; } + set + { + _minimum = value; + UpdateScrollBar(); + } + } + + [Category("Behavior")] + [Description("The upper limit value of the scrollable range.")] + [DefaultValue(100)] + public int Maximum + { + get { return _maximum; } + set + { + _maximum = value; + UpdateScrollBar(); + } + } + + [Category("Behavior")] + [Description("The view size for the scrollable area.")] + [DefaultValue(0)] + public int ViewSize + { + get { return _viewSize; } + set + { + _viewSize = value; + UpdateScrollBar(); + } + } + + public new bool Visible + { + get { return base.Visible; } + set + { + if (base.Visible == value) + return; + + base.Visible = value; + } + } + + #endregion + + #region Constructor Region + + public DarkScrollBar() + { + SetStyle(ControlStyles.OptimizedDoubleBuffer | + ControlStyles.ResizeRedraw | + ControlStyles.UserPaint, true); + + SetStyle(ControlStyles.Selectable, false); + + _scrollTimer = new Timer(); + _scrollTimer.Interval = 1; + _scrollTimer.Tick += ScrollTimerTick; + } + + #endregion + + #region Event Handler Region + + protected override void OnResize(EventArgs e) + { + base.OnResize(e); + + UpdateScrollBar(); + } + + protected override void OnMouseDown(MouseEventArgs e) + { + base.OnMouseDown(e); + + if (_thumbArea.Contains(e.Location) && e.Button == MouseButtons.Left) + { + _isScrolling = true; + _initialContact = e.Location; + + if (_scrollOrientation == DarkOrientation.Vertical) + _initialValue = _thumbArea.Top; + else + _initialValue = _thumbArea.Left; + + Invalidate(); + return; + } + + if (_upArrowArea.Contains(e.Location) && e.Button == MouseButtons.Left) + { + _upArrowClicked = true; + _scrollTimer.Enabled = true; + + Invalidate(); + return; + } + + if (_downArrowArea.Contains(e.Location) && e.Button == MouseButtons.Left) + { + _downArrowClicked = true; + _scrollTimer.Enabled = true; + + Invalidate(); + return; + } + + if (_trackArea.Contains(e.Location) && e.Button == MouseButtons.Left) + { + // Check if our input is at least aligned with the thumb + if (_scrollOrientation == DarkOrientation.Vertical) + { + var modRect = new Rectangle(_thumbArea.Left, _trackArea.Top, _thumbArea.Width, _trackArea.Height); + if (!modRect.Contains(e.Location)) + return; + } + else if (_scrollOrientation == DarkOrientation.Horizontal) + { + var modRect = new Rectangle(_trackArea.Left, _thumbArea.Top, _trackArea.Width, _thumbArea.Height); + if (!modRect.Contains(e.Location)) + return; + } + + // Step 1. Scroll to the area initially clicked. + if (_scrollOrientation == DarkOrientation.Vertical) + { + var loc = e.Location.Y; + loc -= _upArrowArea.Bottom - 1; + loc -= _thumbArea.Height / 2; + ScrollToPhysical(loc); + } + else + { + var loc = e.Location.X; + loc -= _upArrowArea.Right - 1; + loc -= _thumbArea.Width / 2; + ScrollToPhysical(loc); + } + + // Step 2. Initiate a thumb drag. + _isScrolling = true; + _initialContact = e.Location; + _thumbHot = true; + + if (_scrollOrientation == DarkOrientation.Vertical) + _initialValue = _thumbArea.Top; + else + _initialValue = _thumbArea.Left; + + Invalidate(); + + return; + } + } + + protected override void OnMouseUp(MouseEventArgs e) + { + base.OnMouseUp(e); + + _isScrolling = false; + + _thumbClicked = false; + _upArrowClicked = false; + _downArrowClicked = false; + + Invalidate(); + } + + protected override void OnMouseMove(MouseEventArgs e) + { + base.OnMouseMove(e); + + if (!_isScrolling) + { + var thumbHot = _thumbArea.Contains(e.Location); + if (_thumbHot != thumbHot) + { + _thumbHot = thumbHot; + Invalidate(); + } + + var upArrowHot = _upArrowArea.Contains(e.Location); + if (_upArrowHot != upArrowHot) + { + _upArrowHot = upArrowHot; + Invalidate(); + } + + var downArrowHot = _downArrowArea.Contains(e.Location); + if (_downArrowHot != downArrowHot) + { + _downArrowHot = downArrowHot; + Invalidate(); + } + } + + if (_isScrolling) + { + if (e.Button != MouseButtons.Left) + { + OnMouseUp(null); + return; + } + + var difference = new Point(e.Location.X - _initialContact.X, e.Location.Y - _initialContact.Y); + + if (_scrollOrientation == DarkOrientation.Vertical) + { + var thumbPos = (_initialValue - _trackArea.Top); + var newPosition = thumbPos + difference.Y; + + ScrollToPhysical(newPosition); + } + else if (_scrollOrientation == DarkOrientation.Horizontal) + { + var thumbPos = (_initialValue - _trackArea.Left); + var newPosition = thumbPos + difference.X; + + ScrollToPhysical(newPosition); + } + + UpdateScrollBar(); + } + } + + protected override void OnMouseLeave(EventArgs e) + { + base.OnMouseLeave(e); + + _thumbHot = false; + _upArrowHot = false; + _downArrowHot = false; + + Invalidate(); + } + + private void ScrollTimerTick(object sender, EventArgs e) + { + if (!_upArrowClicked && !_downArrowClicked) + { + _scrollTimer.Enabled = false; + return; + } + + if (_upArrowClicked) + ScrollBy(-1); + else if (_downArrowClicked) + ScrollBy(1); + } + + #endregion + + #region Method Region + + public void ScrollTo(int position) + { + Value = position; + } + + public void ScrollToPhysical(int positionInPixels) + { + var isVert = _scrollOrientation == DarkOrientation.Vertical; + + var trackAreaSize = isVert ? _trackArea.Height - _thumbArea.Height : _trackArea.Width - _thumbArea.Width; + + var positionRatio = (float)positionInPixels / (float)trackAreaSize; + var viewScrollSize = (Maximum - ViewSize); + + var newValue = (int)(positionRatio * viewScrollSize); + Value = newValue; + } + + public void ScrollBy(int offset) + { + var newValue = Value + offset; + ScrollTo(newValue); + } + + public void ScrollByPhysical(int offsetInPixels) + { + var isVert = _scrollOrientation == DarkOrientation.Vertical; + + var thumbPos = isVert ? (_thumbArea.Top - _trackArea.Top) : (_thumbArea.Left - _trackArea.Left); + + var newPosition = thumbPos - offsetInPixels; + + ScrollToPhysical(newPosition); + } + + public void UpdateScrollBar() + { + if (ViewSize >= Maximum) + return; + + var area = ClientRectangle; + + // Cap to maximum value + var maximumValue = Maximum - ViewSize; + if (Value > maximumValue) + Value = maximumValue; + + // Arrow buttons + if (_scrollOrientation == DarkOrientation.Vertical) + { + _upArrowArea = new Rectangle(area.Left, area.Top, Consts.ArrowButtonSize, Consts.ArrowButtonSize); + _downArrowArea = new Rectangle(area.Left, area.Bottom - Consts.ArrowButtonSize, Consts.ArrowButtonSize, Consts.ArrowButtonSize); + } + else if (_scrollOrientation == DarkOrientation.Horizontal) + { + _upArrowArea = new Rectangle(area.Left, area.Top, Consts.ArrowButtonSize, Consts.ArrowButtonSize); + _downArrowArea = new Rectangle(area.Right - Consts.ArrowButtonSize, area.Top, Consts.ArrowButtonSize, Consts.ArrowButtonSize); + } + + // Track + if (_scrollOrientation == DarkOrientation.Vertical) + { + _trackArea = new Rectangle(area.Left, area.Top + Consts.ArrowButtonSize, area.Width, area.Height - (Consts.ArrowButtonSize * 2)); + } + else if (_scrollOrientation == DarkOrientation.Horizontal) + { + _trackArea = new Rectangle(area.Left + Consts.ArrowButtonSize, area.Top, area.Width - (Consts.ArrowButtonSize * 2), area.Height); + } + + // Thumb + UpdateThumb(); + + Invalidate(); + } + + private void UpdateThumb(bool forceRefresh = false) + { + // Calculate size ratio + _viewContentRatio = (float)ViewSize / (float)Maximum; + var viewAreaSize = Maximum - ViewSize; + var positionRatio = (float)Value / (float)viewAreaSize; + + // Update area + if (_scrollOrientation == DarkOrientation.Vertical) + { + var thumbSize = (int)(_trackArea.Height * _viewContentRatio); + + if (thumbSize < Consts.MinimumThumbSize) + thumbSize = Consts.MinimumThumbSize; + + var trackAreaSize = _trackArea.Height - thumbSize; + var thumbPosition = (int)(trackAreaSize * positionRatio); + + _thumbArea = new Rectangle(_trackArea.Left + 3, _trackArea.Top + thumbPosition, Consts.ScrollBarSize - 6, thumbSize); + } + else if (_scrollOrientation == DarkOrientation.Horizontal) + { + var thumbSize = (int)(_trackArea.Width * _viewContentRatio); + + if (thumbSize < Consts.MinimumThumbSize) + thumbSize = Consts.MinimumThumbSize; + + var trackAreaSize = _trackArea.Width - thumbSize; + var thumbPosition = (int)(trackAreaSize * positionRatio); + + _thumbArea = new Rectangle(_trackArea.Left + thumbPosition, _trackArea.Top + 3, thumbSize, Consts.ScrollBarSize - 6); + } + + if (forceRefresh) + { + Invalidate(); + Update(); + } + } + + #endregion + + #region Paint Region + + protected override void OnPaint(PaintEventArgs e) + { + var g = e.Graphics; + + // DEBUG: Scrollbar bg + /*using (var b = new SolidBrush(Colors.MediumBackground)) + { + g.FillRectangle(b, ClientRectangle); + }*/ + + // DEBUG: Arrow backgrounds + /*using (var b = new SolidBrush(Color.White)) + { + g.FillRectangle(b, _upArrowArea); + g.FillRectangle(b, _downArrowArea); + }*/ + + // Up arrow + var upIcon = _upArrowHot ? ScrollIcons.scrollbar_arrow_hot : ScrollIcons.scrollbar_arrow_standard; + + if (_upArrowClicked) + upIcon = ScrollIcons.scrollbar_arrow_clicked; + + if (_scrollOrientation == DarkOrientation.Vertical) + upIcon.RotateFlip(RotateFlipType.RotateNoneFlipY); + else if (_scrollOrientation == DarkOrientation.Horizontal) + upIcon.RotateFlip(RotateFlipType.Rotate90FlipNone); + + g.DrawImageUnscaled(upIcon, + _upArrowArea.Left + (_upArrowArea.Width / 2) - (upIcon.Width / 2), + _upArrowArea.Top + (_upArrowArea.Height / 2) - (upIcon.Height / 2)); + + // Down arrow + var downIcon = _downArrowHot ? ScrollIcons.scrollbar_arrow_hot : ScrollIcons.scrollbar_arrow_standard; + + if (_downArrowClicked) + downIcon = ScrollIcons.scrollbar_arrow_clicked; + + if (_scrollOrientation == DarkOrientation.Horizontal) + downIcon.RotateFlip(RotateFlipType.Rotate270FlipNone); + + g.DrawImageUnscaled(downIcon, + _downArrowArea.Left + (_downArrowArea.Width / 2) - (downIcon.Width / 2), + _downArrowArea.Top + (_downArrowArea.Height / 2) - (downIcon.Height / 2)); + + // Draw thumb + var scrollColor = _thumbHot ? Colors.GreyHighlight : Colors.GreySelection; + + if (_isScrolling) + scrollColor = Colors.ActiveControl; + + using (var b = new SolidBrush(scrollColor)) + { + g.FillRectangle(b, _thumbArea); + } + } + + #endregion + } +} diff --git a/DarkUI/Controls/EventArgs/ScrollValueEventArgs.cs b/DarkUI/Controls/EventArgs/ScrollValueEventArgs.cs new file mode 100644 index 0000000..460fb21 --- /dev/null +++ b/DarkUI/Controls/EventArgs/ScrollValueEventArgs.cs @@ -0,0 +1,14 @@ +using System; + +namespace DarkUI +{ + public class ScrollValueEventArgs : EventArgs + { + public int Value { get; private set; } + + public ScrollValueEventArgs(int value) + { + Value = value; + } + } +} diff --git a/DarkUI/DarkUI.csproj b/DarkUI/DarkUI.csproj index 5876080..38da2a9 100644 --- a/DarkUI/DarkUI.csproj +++ b/DarkUI/DarkUI.csproj @@ -49,12 +49,16 @@ Component + + Component + Component Component + Form @@ -64,6 +68,11 @@ True MenuIcons.resx + + True + True + ScrollIcons.resx + @@ -74,6 +83,11 @@ MenuIcons.Designer.cs DarkUI + + ResXFileCodeGenerator + ScrollIcons.Designer.cs + DarkUI + @@ -81,6 +95,18 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + ..\Resources\scrollbar_arrow.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\scrollbar_arrow_clicked.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\scrollbar_arrow_hot.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\scrollbar_arrow_standard.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + \ No newline at end of file diff --git a/DarkUI/Resources/scrollbar_arrow.png b/DarkUI/Resources/scrollbar_arrow.png new file mode 100644 index 0000000000000000000000000000000000000000..738e01bd53c24f6dc9250a77401fdb7e63e10f8a GIT binary patch literal 15222 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 literal 0 HcmV?d00001 diff --git a/DarkUI/Resources/scrollbar_arrow_hot.png b/DarkUI/Resources/scrollbar_arrow_hot.png new file mode 100644 index 0000000000000000000000000000000000000000..85c99ac8b5fe68ebc94f509ec79b96d9d32b4874 GIT binary patch literal 15228 zcmeI3PmkL~6u?~}(6Ul{MS_d#f&?m#|0GV2e3%6XaD*W}sj{@&HRpFl2kQ>1^Zo9h| zAwIg;KejJUZQT)W)z-~{K>~DfjQByf<3+}xDx`4@a-XOrflr6Tr&VDyNywix4)|?9 z#JpB0i?*zk_=;Xov~oqSyv?gbmgEgdl|@-Mw4x!a{OA&D>*UT1ou+YEzdcGvq^i)4 z&$CKB|*P72tuCEUSXk~1QH%EC3oZZqGUnI$Ba zrRng%UE-ElGPkr8vK=x>{TbUKMzJ3r`+ldERoTIK)%^B$T2=g;_gv5M`_Wsb1YPp| z&ZFTvigAt9qbAA~QB{vs#VG2AtlX3pLzbt4WFtY02C01q#b}i%Gh<;K-*KDgD@Dmi z&cqexS z&Znx3)LPnkj_^mb+OeVIrX3_eVT6-|Srx`7bJB7q9VPKe54eHsr1#Y9q)Xqt0BnZPq{D8(QjjqR{mM2bky=7k>8B_D8!pBQX#9H%q;4x8w_tsNw4m> z|G`E?=9@s6^n$;%L9@Wp{euW(e6*X)n{YqZiuNIYHwvgG3rnK68rjvbF8Lg8%;m#qPXUEQ433f*D|GCIW;o*&oxN%BL@+sO-C`MIUO8-k~FbSFCDL! zWpYVM@;!2$Hbd9@bk}J!bj>~A_1w6oj=VxafRU}d-f5W2{4(fI%?!v%oQ zMTU#c2Ur;{0E8|wTy#Fb%5VW7bdlkr^8r?d3jm>u3>Tdburgc#2wh~j=zM^c;Q~PD zBEv=J1FQ@e074fTE;=7zWw-zky2xR5A0ak_!0HKQv7o88VGF$)%U1YfEe1MhV0zl{@!$s!Iv-$VxBw8k zNX50Dzn6+V@-k|lymi|9{xW&>mA7{f8yt7>2FHE;3CCRy$?qQ=*ONK!&xhn?*T)?9 zivPt2zuYEcwY~c0@!&V>n-ANUch`!~hQlXUo;(^3hei3>@bmYs-?{d5?fvWDZG0v? h-ij6Czzv5laNquZ{`c$c2VW=h-p+pg>DI$X{{SOfcoF~r literal 0 HcmV?d00001 diff --git a/DarkUI/Resources/scrollbar_arrow_standard.png b/DarkUI/Resources/scrollbar_arrow_standard.png new file mode 100644 index 0000000000000000000000000000000000000000..6211702b8f562a1cda9f25c715a26435e4eb2519 GIT binary patch literal 15228 zcmeI3L2u(k6o9>2fl8(A2?+@D32 zHfc|2xlk@hNQk{H{DD1iLmUtiaO4N@58whES6V5I?Id^m+xu@>-}c==pdw!|1mMzG0rCh;5;^uA<=1#+lUjg$IX3q z%L@=I7ZlzUr7~Ml3zDo<)XF<-5zB&D6^bG+s+wHV#3DPoxcVx-(*w)a4jOkx>9ADe zI#J|ng3#~x3;j~T3)+IDs;VFsg<_G%Blz&bjf?^BhBwn7<2Vfznt|g-j_0y*T%+Zk zMKz9#6HTtsx_bU3ksFTKVT!`Q@CB(L3JaW?O|o0BH`gk0c@E9>Y^Ub8Dc+a?iwP;&NgRi z39)5iIy7(=xW$&#Eh&X`hjd(j+E##!$P11Skjs!89xb`h0GM0%lH5SJ4EXTfB zDoQqTI!3dp?Yd!PxF*_d)bZL2j$>(+l2xtBsKr;yip`61xyV;lwZfOHs;JmSNik6? zS>&|)Oz4JZp2c;5L#GGd@=P3lQdU|^DVuUxLVQVVNxUQ>nK#N+g>R`<*-}a+)I#<+ zQ7+g_qI-dZ`;yVkjfvM{;bgXAAzM~tzA9BkUN*}3PF5A(mh7seigpF3AE%fTW+v5+ z6XI&R$W^{L@g$sKr4-&yM;=fHvB=LY6t1Y1C;q7+x3R zUfp&6gN+D{^MAJu%blwK#WrMBY<3K{jjXybF5t0Zxt&Y*bNXbBPwVVS)U(bq?gSgS zv&9ECoUVxEz-}7tX>C01QT@#CSC*yNmQ}LjekCsKSMy3RUC4AsU080uxn*s6T`y>Q z7OI!>-kCbXs#~UJdqK~L>Q2vSBf)pux{xVzBjf*E4L3i05RIhiNV+higX53mCe}Sm z#;b~mFF}gGN3MA@bUh)v=FQMG^L*cRqIz+Z4XATo@q>Yu@HxcKu&A!ca!J+&sD>W< z&H#0f8xH>a3gb4cj$ELAuHQ-KH%^uK<@6)Jv@CMZnn^*XTKpu7AEJfHQ}j%&PFnwq zyvY{yBBO#>GzkDg7AY<=A7G`p01&cBagq4|E5!wXkVT4%%m-L0E&zlqQe0#{z)Eoe zAY_r^BJ%-OiVFZCixd}`53o{P00>#6xX65fmEr<^!x07XU&QDK0V}V5PVK z5VA;dk@)~C#RY(nMT(2e2UsaC0E8@3Tx34LN^t=oWRc<`^8r?h3jiUD6c?Efuu@zA z2w9}K$b5j6;sQX(BE?1K1FRGm074ciE;1irrMLhPvPf}}`2Z`$1%Qx6ii^w#SSc<5 zge($qt!D3~A{W1m+Q)C5{`KD9-{3b^S##&0$uO61GR()HFwCDAS