public ImageCache ImageCache
=> this.imageCacheLazy.Value;
+ public IconAssetsManager IconAssetsManager
+ => this.iconAssetsManagerLazy.Value;
+
public TweenMain MainForm
=> this.mainFormLazy.Value;
private readonly DisposableLazy<TwitterApi> twitterApiLazy;
private readonly DisposableLazy<Twitter> twitterLazy;
private readonly DisposableLazy<ImageCache> imageCacheLazy;
+ private readonly DisposableLazy<IconAssetsManager> iconAssetsManagerLazy;
private readonly DisposableLazy<TweenMain> mainFormLazy;
public ApplicationContainer()
this.twitterApiLazy = new(this.CreateTwitterApi);
this.twitterLazy = new(this.CreateTwitter);
this.imageCacheLazy = new(this.CreateImageCache);
+ this.iconAssetsManagerLazy = new(this.CreateIconAssetsManager);
this.mainFormLazy = new(this.CreateTweenMain);
}
private ImageCache CreateImageCache()
=> new();
+ private IconAssetsManager CreateIconAssetsManager()
+ => new();
+
private TweenMain CreateTweenMain()
- => new(this.Settings, this.TabInfo, this.Twitter, this.ImageCache);
+ => new(this.Settings, this.TabInfo, this.Twitter, this.ImageCache, this.IconAssetsManager);
public void Dispose()
{
this.mainFormLazy.Dispose();
this.twitterLazy.Dispose();
this.twitterApiLazy.Dispose();
+ this.iconAssetsManagerLazy.Dispose();
this.imageCacheLazy.Dispose();
}
}
--- /dev/null
+// OpenTween - Client of Twitter
+// Copyright (c) 2007-2011 kiri_feather (@kiri_feather) <kiri.feather@gmail.com>
+// (c) 2008-2011 Moz (@syo68k)
+// (c) 2008-2011 takeshik (@takeshik) <http://www.takeshik.org/>
+// (c) 2010-2011 anis774 (@anis774) <http://d.hatena.ne.jp/anis774/>
+// (c) 2010-2011 fantasticswallow (@f_swallow) <http://twitter.com/f_swallow>
+// (c) 2011 kim_upsilon (@kim_upsilon) <https://upsilo.net/~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 <http://www.gnu.org/licenses/>, or write to
+// the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
+// Boston, MA 02110-1301, USA.
+
+#nullable enable
+
+using System;
+using System.Drawing;
+using System.IO;
+using System.Windows.Forms;
+
+namespace OpenTween
+{
+ public sealed class IconAssetsManager : IDisposable
+ {
+ public bool IsDisposed { get; private set; } = false;
+
+ /// <summary>ウィンドウ左上のアイコン</summary>
+ public Icon IconMain { get; }
+
+ /// <summary>タブ見出し未読表示アイコン</summary>
+ public Icon IconTab { get; }
+
+ /// <summary>タスクトレイ: 通常時アイコン</summary>
+ public Icon IconTray { get; }
+
+ /// <summary>タスクトレイ: エラー時アイコン</summary>
+ public Icon IconTrayError { get; }
+
+ /// <summary>タスクトレイ: オフライン時アイコン</summary>
+ public Icon IconTrayOffline { get; }
+
+ /// <summary>タスクトレイ: Reply通知アイコン</summary>
+ public Icon IconTrayReply { get; }
+
+ /// <summary>タスクトレイ: Reply通知アイコン(点滅時)</summary>
+ public Icon IconTrayReplyBlink { get; }
+
+ /// <summary>タスクトレイ: 更新中アイコン</summary>
+ public Icon[] IconTrayRefresh { get; }
+
+ private readonly Icon? iconMain;
+ private readonly Icon? iconTab;
+ private readonly Icon? iconAt;
+ private readonly Icon? iconAtRed;
+ private readonly Icon? iconAtSmoke;
+ private readonly Icon? iconReply;
+ private readonly Icon? iconReplyBlink;
+ private readonly Icon? iconRefresh1;
+ private readonly Icon? iconRefresh2;
+ private readonly Icon? iconRefresh3;
+ private readonly Icon? iconRefresh4;
+
+ public IconAssetsManager()
+ : this(Path.Combine(Application.StartupPath, "Icons"))
+ {
+ }
+
+ public IconAssetsManager(string iconsDir)
+ {
+ this.iconMain = this.LoadIcon(iconsDir, "MIcon.ico");
+ this.iconTab = this.LoadIcon(iconsDir, "Tab.ico");
+ this.iconAt = this.LoadIcon(iconsDir, "At.ico");
+ this.iconAtRed = this.LoadIcon(iconsDir, "AtRed.ico");
+ this.iconAtSmoke = this.LoadIcon(iconsDir, "AtSmoke.ico");
+ this.iconReply = this.LoadIcon(iconsDir, "Reply.ico");
+ this.iconReplyBlink = this.LoadIcon(iconsDir, "ReplyBlink.ico");
+ this.iconRefresh1 = this.LoadIcon(iconsDir, "Refresh.ico");
+ this.iconRefresh2 = this.LoadIcon(iconsDir, "Refresh2.ico");
+ this.iconRefresh3 = this.LoadIcon(iconsDir, "Refresh3.ico");
+ this.iconRefresh4 = this.LoadIcon(iconsDir, "Refresh4.ico");
+
+ this.IconMain = this.iconMain ?? Properties.Resources.MIcon;
+ this.IconTab = this.iconTab ?? Properties.Resources.TabIcon;
+ this.IconTray = this.iconAt ?? this.iconMain ?? Properties.Resources.At;
+ this.IconTrayError = this.iconAtRed ?? Properties.Resources.AtRed;
+ this.IconTrayOffline = this.iconAtSmoke ?? Properties.Resources.AtSmoke;
+
+ if (this.iconReply != null && this.iconReplyBlink != null)
+ {
+ this.IconTrayReply = this.iconReply;
+ this.IconTrayReplyBlink = this.iconReplyBlink;
+ }
+ else
+ {
+ this.IconTrayReply = this.iconReply ?? this.iconReplyBlink ?? Properties.Resources.Reply;
+ this.IconTrayReplyBlink = this.IconTray;
+ }
+
+ if (this.iconRefresh1 == null)
+ {
+ this.IconTrayRefresh = new[]
+ {
+ Properties.Resources.Refresh, Properties.Resources.Refresh2,
+ Properties.Resources.Refresh3, Properties.Resources.Refresh4,
+ };
+ }
+ else if (this.iconRefresh2 == null)
+ {
+ this.IconTrayRefresh = new[] { this.iconRefresh1 };
+ }
+ else if (this.iconRefresh3 == null)
+ {
+ this.IconTrayRefresh = new[] { this.iconRefresh1, this.iconRefresh2 };
+ }
+ else if (this.iconRefresh4 == null)
+ {
+ this.IconTrayRefresh = new[] { this.iconRefresh1, this.iconRefresh2, this.iconRefresh3 };
+ }
+ else // iconRefresh1 から iconRefresh4 まで全て揃っている
+ {
+ this.IconTrayRefresh = new[] { this.iconRefresh1, this.iconRefresh2, this.iconRefresh3, this.iconRefresh4 };
+ }
+ }
+
+ private Icon? LoadIcon(string baseDir, string fileName)
+ {
+ var filePath = Path.Combine(baseDir, fileName);
+ if (!File.Exists(filePath))
+ return null;
+
+ try
+ {
+ return new(filePath);
+ }
+ catch
+ {
+ return null;
+ }
+ }
+
+ public void Dispose()
+ {
+ if (this.IsDisposed)
+ return;
+
+ this.iconMain?.Dispose();
+ this.iconTab?.Dispose();
+ this.iconAt?.Dispose();
+ this.iconAtRed?.Dispose();
+ this.iconAtSmoke?.Dispose();
+ this.iconReply?.Dispose();
+ this.iconReplyBlink?.Dispose();
+ this.iconRefresh1?.Dispose();
+ this.iconRefresh2?.Dispose();
+ this.iconRefresh3?.Dispose();
+ this.iconRefresh4?.Dispose();
+ this.IsDisposed = true;
+ }
+ }
+}
<Compile Include="ApplicationInstanceMutex.cs" />
<Compile Include="ApplicationPreconditions.cs" />
<Compile Include="ApplicationSettings.cs" />
+ <Compile Include="IconAssetsManager.cs" />
<Compile Include="AsyncTimer.cs" />
<Compile Include="AtIdSupplement.cs">
<SubType>Form</SubType>
/// <summary>アイコン画像リスト</summary>
private readonly ImageCache iconCache;
- /// <summary>タスクトレイアイコン:通常時 (At.ico)</summary>
- private Icon nIconAt = null!;
-
- /// <summary>タスクトレイアイコン:通信エラー時 (AtRed.ico)</summary>
- private Icon nIconAtRed = null!;
-
- /// <summary>タスクトレイアイコン:オフライン時 (AtSmoke.ico)</summary>
- private Icon nIconAtSmoke = null!;
-
- /// <summary>タスクトレイアイコン:更新中 (Refresh.ico)</summary>
- private Icon[] nIconRefresh = new Icon[4];
-
- /// <summary>未読のあるタブ用アイコン (Tab.ico)</summary>
- private Icon tabIcon = null!;
-
- /// <summary>画面左上のアイコン (Main.ico)</summary>
- private Icon mainIcon = null!;
-
- private Icon replyIcon = null!;
- private Icon replyIconBlink = null!;
+ private readonly IconAssetsManager iconAssets;
private readonly ImageList listViewImageList = new(); // ListViewItemの高さ変更用
// 後始末
this.SearchDialog.Dispose();
this.urlDialog.Dispose();
- this.nIconAt?.Dispose();
- this.nIconAtRed?.Dispose();
- this.nIconAtSmoke?.Dispose();
- foreach (var iconRefresh in this.nIconRefresh)
- {
- iconRefresh?.Dispose();
- }
- this.tabIcon?.Dispose();
- this.mainIcon?.Dispose();
- this.replyIcon?.Dispose();
- this.replyIconBlink?.Dispose();
this.listViewImageList.Dispose();
this.brsHighLight.Dispose();
this.brsBackColorMine?.Dispose();
this.disposed = true;
}
- private void LoadIcons()
- {
- // Icons フォルダ以下のアイコンを読み込み(着せ替えアイコン対応)
- var iconsDir = Path.Combine(Application.StartupPath, "Icons");
-
- // ウィンドウ左上のアイコン
- var iconMain = this.LoadIcon(Path.Combine(iconsDir, "MIcon.ico"));
-
- // タブ見出し未読表示アイコン
- var iconTab = this.LoadIcon(Path.Combine(iconsDir, "Tab.ico"));
-
- // タスクトレイ: 通常時アイコン
- var iconAt = this.LoadIcon(Path.Combine(iconsDir, "At.ico"));
-
- // タスクトレイ: エラー時アイコン
- var iconAtRed = this.LoadIcon(Path.Combine(iconsDir, "AtRed.ico"));
-
- // タスクトレイ: オフライン時アイコン
- var iconAtSmoke = this.LoadIcon(Path.Combine(iconsDir, "AtSmoke.ico"));
-
- // タスクトレイ: Reply通知アイコン (最大2枚でアニメーション可能)
- var iconReply = this.LoadIcon(Path.Combine(iconsDir, "Reply.ico"));
- var iconReplyBlink = this.LoadIcon(Path.Combine(iconsDir, "ReplyBlink.ico"));
-
- // タスクトレイ: 更新中アイコン (最大4枚でアニメーション可能)
- var iconRefresh1 = this.LoadIcon(Path.Combine(iconsDir, "Refresh.ico"));
- var iconRefresh2 = this.LoadIcon(Path.Combine(iconsDir, "Refresh2.ico"));
- var iconRefresh3 = this.LoadIcon(Path.Combine(iconsDir, "Refresh3.ico"));
- var iconRefresh4 = this.LoadIcon(Path.Combine(iconsDir, "Refresh4.ico"));
-
- // 読み込んだアイコンを設定 (不足するアイコンはデフォルトのものを設定)
-
- this.mainIcon = iconMain ?? Properties.Resources.MIcon;
- this.tabIcon = iconTab ?? Properties.Resources.TabIcon;
- this.nIconAt = iconAt ?? iconMain ?? Properties.Resources.At;
- this.nIconAtRed = iconAtRed ?? Properties.Resources.AtRed;
- this.nIconAtSmoke = iconAtSmoke ?? Properties.Resources.AtSmoke;
-
- if (iconReply != null && iconReplyBlink != null)
- {
- this.replyIcon = iconReply;
- this.replyIconBlink = iconReplyBlink;
- }
- else
- {
- this.replyIcon = iconReply ?? iconReplyBlink ?? Properties.Resources.Reply;
- this.replyIconBlink = this.nIconAt;
- }
-
- if (iconRefresh1 == null)
- {
- this.nIconRefresh = new[]
- {
- Properties.Resources.Refresh, Properties.Resources.Refresh2,
- Properties.Resources.Refresh3, Properties.Resources.Refresh4,
- };
- }
- else if (iconRefresh2 == null)
- {
- this.nIconRefresh = new[] { iconRefresh1 };
- }
- else if (iconRefresh3 == null)
- {
- this.nIconRefresh = new[] { iconRefresh1, iconRefresh2 };
- }
- else if (iconRefresh4 == null)
- {
- this.nIconRefresh = new[] { iconRefresh1, iconRefresh2, iconRefresh3 };
- }
- else // iconRefresh1 から iconRefresh4 まで全て揃っている
- {
- this.nIconRefresh = new[] { iconRefresh1, iconRefresh2, iconRefresh3, iconRefresh4 };
- }
- }
-
- private Icon? LoadIcon(string filePath)
- {
- if (!File.Exists(filePath))
- return null;
-
- try
- {
- return new Icon(filePath);
- }
- catch (Exception)
- {
- return null;
- }
- }
-
private void InitColumns(ListView list, bool startup)
{
this.InitColumnText();
}
}
- public TweenMain(SettingManager settingManager, TabInformations tabInfo, Twitter twitter, ImageCache imageCache)
+ public TweenMain(SettingManager settingManager, TabInformations tabInfo, Twitter twitter, ImageCache imageCache, IconAssetsManager iconAssets)
{
this.settings = settingManager;
this.statuses = tabInfo;
this.tw = twitter;
this.iconCache = imageCache;
+ this.iconAssets = iconAssets;
this.InitializeComponent();
Regex.CacheSize = 100;
// アイコン設定
- this.LoadIcons();
- this.Icon = this.mainIcon; // メインフォーム(TweenMain)
- this.NotifyIcon1.Icon = this.nIconAt; // タスクトレイ
- this.TabImage.Images.Add(this.tabIcon); // タブ見出し
+ this.Icon = this.iconAssets.IconMain; // メインフォーム(TweenMain)
+ this.NotifyIcon1.Icon = this.iconAssets.IconTray; // タスクトレイ
+ this.TabImage.Images.Add(this.iconAssets.IconTab); // タブ見出し
// <<<<<<<<<設定関連>>>>>>>>>
// 設定読み出し
var result = DialogResult.Abort;
using var settingDialog = new AppendSettingDialog();
- settingDialog.Icon = this.mainIcon;
+ settingDialog.Icon = this.iconAssets.IconMain;
settingDialog.Owner = this;
settingDialog.ShowInTaskbar = showTaskbarIcon;
settingDialog.IntervalChanged += this.TimerInterval_Changed;
if (busyTasks)
{
this.iconCnt += 1;
- if (this.iconCnt >= this.nIconRefresh.Length)
+ if (this.iconCnt >= this.iconAssets.IconTrayRefresh.Length)
this.iconCnt = 0;
- this.NotifyIcon1.Icon = this.nIconRefresh[this.iconCnt];
+ this.NotifyIcon1.Icon = this.iconAssets.IconTrayRefresh[this.iconCnt];
this.myStatusError = false;
EnableTasktrayAnimation();
return;
if (this.blinkCnt == 0)
this.blink = !this.blink;
- this.NotifyIcon1.Icon = this.blink ? this.replyIconBlink : this.replyIcon;
+ this.NotifyIcon1.Icon = this.blink ? this.iconAssets.IconTrayReplyBlink : this.iconAssets.IconTrayReply;
EnableTasktrayAnimation();
return;
}
// 優先度:リプライ→エラー→オフライン→アイドル
// エラーは更新アイコンでクリアされる
if (replyIconType == MyCommon.REPLY_ICONSTATE.StaticIcon && reply)
- this.NotifyIcon1.Icon = this.replyIcon;
+ this.NotifyIcon1.Icon = this.iconAssets.IconTrayReply;
else if (this.myStatusError)
- this.NotifyIcon1.Icon = this.nIconAtRed;
+ this.NotifyIcon1.Icon = this.iconAssets.IconTrayError;
else if (this.myStatusOnline)
- this.NotifyIcon1.Icon = this.nIconAt;
+ this.NotifyIcon1.Icon = this.iconAssets.IconTray;
else
- this.NotifyIcon1.Icon = this.nIconAtSmoke;
+ this.NotifyIcon1.Icon = this.iconAssets.IconTrayOffline;
}
private void TimerRefreshIcon_Tick(object sender, EventArgs e)