// OpenTween - Client of Twitter // Copyright (c) 2013 kim_upsilon (@kim_upsilon) // All rights reserved. // // This file is part of OpenTween. // // This program is free software; you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by the Free // Software Foundation; either version 3 of the License, or (at your option) // any later version. // // This program is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License // for more details. // // You should have received a copy of the GNU General Public License along // with this program. If not, see , or write to // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, // Boston, MA 02110-1301, USA. using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows.Forms; using System.Drawing; using System.Windows.Forms.Design; using System.ComponentModel; using OpenTween.Api; namespace OpenTween { /// /// API 実行回数制限に到達するまでの目安を表示する ToolStripItem /// [ToolStripItemDesignerAvailability(ToolStripItemDesignerAvailability.All)] public class ToolStripAPIGauge : ToolStripStatusLabel { public ToolStripAPIGauge() { UpdateText(); this.DisplayStyle = ToolStripItemDisplayStyle.Text; } /// /// ゲージに表示される横棒グラフの幅 /// [DefaultValue(8)] [RefreshProperties(RefreshProperties.Repaint)] public int GaugeHeight { get { return this._GaugeHeight; } set { this._GaugeHeight = value; this.UpdateGaugeBounds(); this.Invalidate(); } } private int _GaugeHeight = 8; /// /// API 実行回数制限の値 /// [Browsable(false)] public ApiLimit ApiLimit { get { return this._ApiLimit; } private set { this._ApiLimit = value; this.UpdateRemainMinutes(); this.UpdateText(); this.UpdateGaugeBounds(); this.Invalidate(); } } private ApiLimit _ApiLimit = null; /// /// API エンドポイント名 /// [Browsable(false)] public string ApiEndpoint { get { return this._ApiEndpoint; } set { if (string.IsNullOrEmpty(value)) { // リセット this._ApiEndpoint = null; this.ApiLimit = null; return; } var apiLimit = MyCommon.TwitterApiInfo.AccessLimit[value]; if (this._ApiEndpoint != value) { // ApiEndpointが変更されているので更新する this._ApiEndpoint = value; this.ApiLimit = apiLimit; } else { // ApiLimitが変更されていれば更新する if (this._ApiLimit == null || !this._ApiLimit.Equals(apiLimit)) { this.ApiLimit = apiLimit; } } } } private string _ApiEndpoint = null; [Browsable(false)] [EditorBrowsable(EditorBrowsableState.Never)] public new string Text { get => base.Text; set => base.Text = value; } [Browsable(false)] [EditorBrowsable(EditorBrowsableState.Never)] public new string ToolTipText { get => base.ToolTipText; set => base.ToolTipText = value; } [DefaultValue(ToolStripItemDisplayStyle.Text)] [RefreshProperties(RefreshProperties.Repaint)] public new ToolStripItemDisplayStyle DisplayStyle { get => base.DisplayStyle; set => base.DisplayStyle = value; } protected double remainMinutes = -1; protected virtual void UpdateRemainMinutes() { if (this._ApiLimit != null) this.remainMinutes = (this._ApiLimit.AccessLimitResetDate - DateTimeUtc.Now).TotalMinutes; else this.remainMinutes = -1; } protected override void OnPaint(PaintEventArgs e) { var g = e.Graphics; if (this.apiGaugeBounds != Rectangle.Empty) g.FillRectangle(Brushes.LightBlue, this.apiGaugeBounds); if (this.timeGaugeBounds != Rectangle.Empty) g.FillRectangle(Brushes.LightPink, this.timeGaugeBounds); base.OnPaint(e); } #region from Tween v1.1.0.0 // The code in this region block is based on code written by the following authors: // (C) 2010 anis774 (@anis774) // (C) 2010 Moz (@syo68k) internal Rectangle apiGaugeBounds = Rectangle.Empty; internal Rectangle timeGaugeBounds = Rectangle.Empty; protected virtual void UpdateGaugeBounds() { if (this._ApiLimit == null || this._GaugeHeight < 1) { this.apiGaugeBounds = Rectangle.Empty; this.timeGaugeBounds = Rectangle.Empty; return; } var apiGaugeValue = (double)this._ApiLimit.AccessLimitRemain / this._ApiLimit.AccessLimitCount; this.apiGaugeBounds = new Rectangle( 0, (this.Height - this._GaugeHeight * 2) / 2, (int)(this.Width * apiGaugeValue), this._GaugeHeight ); var timeGaugeValue = this.remainMinutes >= 15 ? 1.00 : this.remainMinutes / 15; this.timeGaugeBounds = new Rectangle( 0, this.apiGaugeBounds.Top + this._GaugeHeight, (int)(this.Width * timeGaugeValue), this._GaugeHeight ); } protected virtual void UpdateText() { string remainCountText; string maxCountText; string minuteText; if (this._ApiLimit == null || this.remainMinutes < 0) { remainCountText = "???"; maxCountText = "???"; minuteText = "???"; } else { remainCountText = this._ApiLimit.AccessLimitRemain.ToString(); maxCountText = this._ApiLimit.AccessLimitCount.ToString(); minuteText = Math.Ceiling(this.remainMinutes).ToString(); } var endpointText = string.IsNullOrEmpty(this._ApiEndpoint) ? "unknown" : this._ApiEndpoint; var textFormat = "API {0}/{1}"; this.Text = string.Format(textFormat, remainCountText, maxCountText); var toolTipTextFormat = "API rest {0} {1}/{2}" + Environment.NewLine + "(reset after {3} minutes)"; this.ToolTipText = String.Format(toolTipTextFormat, endpointText, remainCountText, maxCountText, minuteText); } #endregion } }