1 // Copyright (C) 2019 Kazuhiro Fujieda <fujieda@users.osdn.me>
\r
3 // Licensed under the Apache License, Version 2.0 (the "License");
\r
4 // you may not use this file except in compliance with the License.
\r
5 // You may obtain a copy of the License at
\r
7 // http://www.apache.org/licenses/LICENSE-2.0
\r
9 // Unless required by applicable law or agreed to in writing, software
\r
10 // distributed under the License is distributed on an "AS IS" BASIS,
\r
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
\r
12 // See the License for the specific language governing permissions and
\r
13 // limitations under the License.
\r
16 using System.Drawing;
\r
17 using System.Windows.Forms;
\r
19 namespace KancolleSniffer.View
\r
21 public class ListScroller
\r
23 private readonly Panel _panel;
\r
24 private const int MarkWidth = 20;
\r
26 public int Padding { get; set; }
\r
28 public int Position { get; set; }
\r
30 public int Lines { get; set; }
\r
32 public int DataCount { get; set; }
\r
34 public event Action Update;
\r
36 public event Action StartScroll;
\r
38 public event Action EndScroll;
\r
40 public ListScroller(Panel panel, Control[] topLabels, Control[] bottomLabels)
\r
43 panel.Paint += (obj, ev) => DrawMark();
\r
44 SetTopEventHandler(topLabels);
\r
45 SetBottomEventHandler(bottomLabels);
\r
48 public void SetTopEventHandler(Control[] top)
\r
50 foreach (var label in top)
\r
52 label.MouseEnter += TopLineOnMouseEnter;
\r
53 label.MouseLeave += TopLineOnMouseLeave;
\r
55 _topScrollRepeatTimer.Tick += (obj, e) => ScrollUp();
\r
58 public void SetBottomEventHandler(Control[] bottom)
\r
60 foreach (var label in bottom)
\r
62 label.MouseEnter += BottomLineOnMouseEnter;
\r
63 label.MouseLeave += BottomLineOnMouseLeave;
\r
65 _bottomScrollRepeatTimer.Tick += (obj, e) => ScrollDown();
\r
68 private readonly Timer _topScrollRepeatTimer = new Timer {Interval = 100};
\r
69 private readonly Timer _bottomScrollRepeatTimer = new Timer {Interval = 100};
\r
71 private void TopLineOnMouseEnter(object sender, EventArgs e)
\r
75 StartScroll?.Invoke();
\r
76 _topScrollRepeatTimer.Start();
\r
79 private void ScrollUp()
\r
87 private bool IsTop => Position == 0;
\r
89 private void TopLineOnMouseLeave(object sender, EventArgs e)
\r
91 EndScroll?.Invoke();
\r
92 _topScrollRepeatTimer.Stop();
\r
95 private void BottomLineOnMouseEnter(object sender, EventArgs e)
\r
99 StartScroll?.Invoke();
\r
100 _bottomScrollRepeatTimer.Start();
\r
103 private void ScrollDown()
\r
111 private bool NeedScroll => Position + Lines < DataCount;
\r
113 private void BottomLineOnMouseLeave(object sender, EventArgs e)
\r
115 EndScroll?.Invoke();
\r
116 _bottomScrollRepeatTimer.Stop();
\r
119 public void DrawMark()
\r
121 var halfOfWidth = _panel.Width * 0.5f;
\r
122 var halfOfMark = Scaler.ScaleWidth(MarkWidth * 0.5f);
\r
123 var left = halfOfWidth - halfOfMark;
\r
124 var right = halfOfWidth + halfOfMark;
\r
125 var center = halfOfWidth;
\r
126 using (var g = _panel.CreateGraphics())
\r
128 DrawTopMark(g, left, right, center);
\r
129 DrawBottomMark(g, left, right, center);
\r
133 private void DrawTopMark(Graphics g, float left, float right, float center)
\r
135 var brush = Position > 0 ? Brushes.Black : new SolidBrush(_panel.BackColor);
\r
137 var base_ = Padding - 1;
\r
138 g.FillPolygon(brush,
\r
141 new PointF(left, base_), new PointF(right, base_), new PointF(center, top),
\r
142 new PointF(left, base_)
\r
146 private void DrawBottomMark(Graphics g, float left, float right, float center)
\r
148 var brush = Position + Lines < DataCount ? Brushes.Black : new SolidBrush(_panel.BackColor);
\r
149 var top = _panel.Height - 2;
\r
150 var base_ = _panel.Height - Padding - 1;
\r
151 g.FillPolygon(brush,
\r
154 new PointF(left, base_), new PointF(right, base_), new PointF(center, top),
\r
155 new PointF(left, base_)
\r