OSDN Git Service

OpenTween v2.4.2 リリース
[opentween/open-tween.git] / OpenTween / ToolStripAPIGauge.cs
1 // OpenTween - Client of Twitter
2 // Copyright (c) 2013 kim_upsilon (@kim_upsilon) <https://upsilo.net/~upsilon/>
3 // All rights reserved.
4 // 
5 // This file is part of OpenTween.
6 // 
7 // This program is free software; you can redistribute it and/or modify it
8 // under the terms of the GNU General Public License as published by the Free
9 // Software Foundation; either version 3 of the License, or (at your option)
10 // any later version.
11 // 
12 // This program is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 // for more details. 
16 // 
17 // You should have received a copy of the GNU General Public License along
18 // with this program. If not, see <http://www.gnu.org/licenses/>, or write to
19 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
20 // Boston, MA 02110-1301, USA.
21
22 #nullable enable
23
24 using System;
25 using System.Collections.Generic;
26 using System.Linq;
27 using System.Text;
28 using System.Windows.Forms;
29 using System.Drawing;
30 using System.Windows.Forms.Design;
31 using System.ComponentModel;
32 using OpenTween.Api;
33
34 namespace OpenTween
35 {
36     /// <summary>
37     /// API 実行回数制限に到達するまでの目安を表示する ToolStripItem
38     /// </summary>
39     [ToolStripItemDesignerAvailability(ToolStripItemDesignerAvailability.All)]
40     public class ToolStripAPIGauge : ToolStripStatusLabel
41     {
42         public ToolStripAPIGauge()
43         {
44             UpdateText();
45
46             this.DisplayStyle = ToolStripItemDisplayStyle.Text;
47         }
48
49         /// <summary>
50         /// ゲージに表示される横棒グラフの幅
51         /// </summary>
52         [DefaultValue(8)]
53         [RefreshProperties(RefreshProperties.Repaint)]
54         public int GaugeHeight
55         {
56             get => this._GaugeHeight;
57             set
58             {
59                 this._GaugeHeight = value;
60
61                 this.UpdateGaugeBounds();
62                 this.Invalidate();
63             }
64         }
65         private int _GaugeHeight = 8;
66
67         /// <summary>
68         /// API 実行回数制限の値
69         /// </summary>
70         [Browsable(false)]
71         public ApiLimit? ApiLimit
72         {
73             get => this._ApiLimit;
74             private set
75             {
76                 this._ApiLimit = value;
77
78                 this.UpdateRemainMinutes();
79                 this.UpdateText();
80                 this.UpdateGaugeBounds();
81                 this.Invalidate();
82             }
83         }
84         private ApiLimit? _ApiLimit = null;
85
86         /// <summary>
87         /// API エンドポイント名
88         /// </summary>
89         [Browsable(false)]
90         public string? ApiEndpoint
91         {
92             get => this._ApiEndpoint;
93             set
94             {
95                 if (MyCommon.IsNullOrEmpty(value))
96                 {
97                     // リセット
98                     this._ApiEndpoint = null;
99                     this.ApiLimit = null;
100                     return;
101                 }
102
103                 var apiLimit = MyCommon.TwitterApiInfo.AccessLimit[value];
104
105                 if (this._ApiEndpoint != value)
106                 {
107                     // ApiEndpointが変更されているので更新する
108                     this._ApiEndpoint = value;
109                     this.ApiLimit = apiLimit;
110                 }
111                 else
112                 {
113                     // ApiLimitが変更されていれば更新する
114                     if (this._ApiLimit == null ||
115                         !this._ApiLimit.Equals(apiLimit))
116                     {
117                         this.ApiLimit = apiLimit;
118                     }
119                 }
120             }
121         }
122         private string? _ApiEndpoint = null;
123
124         [Browsable(false)]
125         [EditorBrowsable(EditorBrowsableState.Never)]
126         public new string Text
127         {
128             get => base.Text;
129             set => base.Text = value;
130         }
131
132         [Browsable(false)]
133         [EditorBrowsable(EditorBrowsableState.Never)]
134         public new string ToolTipText
135         {
136             get => base.ToolTipText;
137             set => base.ToolTipText = value;
138         }
139
140         [DefaultValue(ToolStripItemDisplayStyle.Text)]
141         [RefreshProperties(RefreshProperties.Repaint)]
142         public new ToolStripItemDisplayStyle DisplayStyle
143         {
144             get => base.DisplayStyle;
145             set => base.DisplayStyle = value;
146         }
147
148         protected double remainMinutes = -1;
149
150         protected virtual void UpdateRemainMinutes()
151         {
152             if (this._ApiLimit != null)
153                 this.remainMinutes = (this._ApiLimit.AccessLimitResetDate - DateTimeUtc.Now).TotalMinutes;
154             else
155                 this.remainMinutes = -1;
156         }
157
158         protected override void OnPaint(PaintEventArgs e)
159         {
160             var g = e.Graphics;
161
162             if (this.apiGaugeBounds != Rectangle.Empty)
163                 g.FillRectangle(Brushes.LightBlue, this.apiGaugeBounds);
164
165             if (this.timeGaugeBounds != Rectangle.Empty)
166                 g.FillRectangle(Brushes.LightPink, this.timeGaugeBounds);
167
168             base.OnPaint(e);
169         }
170
171         #region from Tween v1.1.0.0
172
173         // The code in this region block is based on code written by the following authors:
174         //   (C) 2010 anis774 (@anis774) <http://d.hatena.ne.jp/anis774/>
175         //   (C) 2010 Moz (@syo68k)
176
177         internal Rectangle apiGaugeBounds = Rectangle.Empty;
178         internal Rectangle timeGaugeBounds = Rectangle.Empty;
179
180         protected virtual void UpdateGaugeBounds()
181         {
182             if (this._ApiLimit == null || this._GaugeHeight < 1)
183             {
184                 this.apiGaugeBounds = Rectangle.Empty;
185                 this.timeGaugeBounds = Rectangle.Empty;
186                 return;
187             }
188
189             var apiGaugeValue = (double)this._ApiLimit.AccessLimitRemain / this._ApiLimit.AccessLimitCount;
190             this.apiGaugeBounds = new Rectangle(
191                 0,
192                 (this.Height - this._GaugeHeight * 2) / 2,
193                 (int)(this.Width * apiGaugeValue),
194                 this._GaugeHeight
195             );
196
197             var timeGaugeValue = this.remainMinutes >= 15 ? 1.00 : this.remainMinutes / 15;
198             this.timeGaugeBounds = new Rectangle(
199                 0,
200                 this.apiGaugeBounds.Top + this._GaugeHeight,
201                 (int)(this.Width * timeGaugeValue),
202                 this._GaugeHeight
203             );
204         }
205
206         protected virtual void UpdateText()
207         {
208             string remainCountText;
209             string maxCountText;
210             string minuteText;
211
212             if (this._ApiLimit == null || this.remainMinutes < 0)
213             {
214                 remainCountText = "???";
215                 maxCountText = "???";
216                 minuteText = "???";
217             }
218             else
219             {
220                 remainCountText = this._ApiLimit.AccessLimitRemain.ToString();
221                 maxCountText = this._ApiLimit.AccessLimitCount.ToString();
222                 minuteText = Math.Ceiling(this.remainMinutes).ToString();
223             }
224
225             var endpointText = MyCommon.IsNullOrEmpty(this._ApiEndpoint) ? "unknown" : this._ApiEndpoint;
226
227             var textFormat = "API {0}/{1}";
228             this.Text = string.Format(textFormat, remainCountText, maxCountText);
229
230             var toolTipTextFormat =
231                 "API rest {0} {1}/{2}" + Environment.NewLine +
232                 "(reset after {3} minutes)";
233
234             this.ToolTipText = string.Format(toolTipTextFormat, endpointText, remainCountText, maxCountText, minuteText);
235         }
236
237         #endregion
238     }
239 }