From 9a37708b53baf3724671eba02c3b50c7a63169f7 Mon Sep 17 00:00:00 2001 From: Patrick Simpson Date: Wed, 12 Apr 2017 10:23:52 +0200 Subject: [PATCH] [KOE-244] Added basic progress feature to ribbon, and disabled sync feature that just increases progress periodically. --- .../AcaciaZPushPlugin.csproj | 7 + .../AcaciaZPushPlugin/Features/Features.cs | 3 +- .../Features/SyncState/FeatureSyncState.cs | 165 ++++++++++++++++++ .../Properties/Resources.Designer.cs | 56 ++++++ .../Properties/Resources.resx | 19 ++ .../Resources/Icons/Progress0.png | Bin 0 -> 295 bytes .../Resources/Icons/Progress1.png | Bin 0 -> 300 bytes .../UI/Outlook/CommandElement.cs | 11 +- .../UI/Outlook/DataProvider.cs | 17 ++ .../AcaciaZPushPlugin/UI/Outlook/OutlookUI.cs | 83 ++++++--- 10 files changed, 335 insertions(+), 26 deletions(-) create mode 100644 src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/SyncState/FeatureSyncState.cs create mode 100644 src/AcaciaZPushPlugin/AcaciaZPushPlugin/Resources/Icons/Progress0.png create mode 100644 src/AcaciaZPushPlugin/AcaciaZPushPlugin/Resources/Icons/Progress1.png create mode 100644 src/AcaciaZPushPlugin/AcaciaZPushPlugin/UI/Outlook/DataProvider.cs diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/AcaciaZPushPlugin.csproj b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/AcaciaZPushPlugin.csproj index f989cbf..186931c 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/AcaciaZPushPlugin.csproj +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/AcaciaZPushPlugin.csproj @@ -287,6 +287,7 @@ SignaturesSettings.cs + @@ -337,6 +338,7 @@ + @@ -618,6 +620,11 @@ + + + + + diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/Features.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/Features.cs index a3166de..7f85a19 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/Features.cs +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/Features.cs @@ -38,7 +38,8 @@ namespace Acacia.Features typeof(SendAs.FeatureSendAs), typeof(Signatures.FeatureSignatures), typeof(MeetingRequest.FeatureMeetingRequest), - typeof(DebugSupport.FeatureDebugSupport) + typeof(DebugSupport.FeatureDebugSupport), + typeof(SyncState.FeatureSyncState), }; } } diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/SyncState/FeatureSyncState.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/SyncState/FeatureSyncState.cs new file mode 100644 index 0000000..0d840d2 --- /dev/null +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/SyncState/FeatureSyncState.cs @@ -0,0 +1,165 @@ +/// Copyright 2017 Kopano b.v. +/// +/// This program is free software: you can redistribute it and/or modify +/// it under the terms of the GNU Affero General Public License, version 3, +/// as published by the Free Software Foundation. +/// +/// 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 Affero General Public License for more details. +/// +/// You should have received a copy of the GNU Affero General Public License +/// along with this program.If not, see. +/// +/// Consult LICENSE file for details + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Acacia.Stubs; +using Acacia.Utils; +using Acacia.ZPush; +using Acacia.Features.SharedFolders; +using Acacia.ZPush.API.SharedFolders; +using static Acacia.DebugOptions; +using Acacia.UI.Outlook; +using System.Drawing; + +namespace Acacia.Features.SyncState +{ + public class FeatureSyncState : FeatureDisabled, FeatureWithRibbon + { + private class SyncStateData : DataProvider + { + private FeatureSyncState _feature; + + /// + /// Number in range [0,1] + /// + private double _syncProgress; + public double SyncProgress + { + get { return _syncProgress; } + set + { + int old = SyncProgressPercent; + + _syncProgress = value; + + if (SyncProgressPercent != old) + { + // Percentage has changed, update required + _feature._button.Invalidate(); + } + } + } + + public int SyncProgressPercent + { + get + { + return AlignProgress(100); + } + } + + private int AlignProgress(int steps, double round = 0.5) + { + int val = (int)Math.Floor(_syncProgress * steps + round); + return Math.Min(steps, val); + } + + public SyncStateData(FeatureSyncState feature) + { + this._feature = feature; + } + + private static readonly Bitmap[] PROGRESS = CreateProgressImages(); + + private const int PROGRESS_STEPS = 20; + private static Bitmap[] CreateProgressImages() + { + Bitmap[] images = new Bitmap[PROGRESS_STEPS + 1]; + + Bitmap img0 = Properties.Resources.Progress0; + Bitmap img1 = Properties.Resources.Progress1; + images[0] = img0; + images[PROGRESS_STEPS] = img1; + + // Create a series of images starting with img0, overlayed with part of img1. This shows the progress bar filling up. + for (int i = 1; i < PROGRESS_STEPS; ++i) + { + Bitmap img = new Bitmap(img0); + using (var canvas = Graphics.FromImage(img)) + { + int w = img1.Width * i / PROGRESS_STEPS; + Rectangle r = new Rectangle(0, 0, w, img0.Height); + canvas.DrawImage(img1, r, r, GraphicsUnit.Pixel); + canvas.Save(); + } + + images[i] = img; + } + + return images; + } + + public Bitmap GetImage(string elementId, bool large) + { + int index = AlignProgress(PROGRESS_STEPS, 0.05); + + // extra safety check, just in case + return (index >= 0 && index <= PROGRESS_STEPS) ? PROGRESS[index] : PROGRESS[0]; + } + + public string GetLabel(string elementId) + { + if (SyncProgressPercent == 100) + return Properties.Resources.Ribbon_SyncState_Label_Done; + return string.Format(Properties.Resources.Ribbon_SyncState_Label, SyncProgressPercent); + } + + public string GetScreenTip(string elementId) + { + return Properties.Resources.Ribbon_SyncState_Screentip; + } + + public string GetSuperTip(string elementId) + { + return Properties.Resources.Ribbon_SyncState_Supertip; + } + } + + private RibbonButton _button; + + public FeatureSyncState() + { + } + + public override void Startup() + { + _button = RegisterButton(this, "Progress", true, ShowSyncState, ZPushBehaviour.None); + _button.DataProvider = new SyncStateData(this); + + // Debug timer to increase progress + var timer = new System.Windows.Forms.Timer(); + timer.Interval = 1000; + timer.Tick += (o, args) => + { + SyncStateData data = (SyncStateData)_button.DataProvider; + double val = (data.SyncProgress + 0.05); + if (val > 1.01) + val = 0; + data.SyncProgress = val; + }; + timer.Start(); + + } + + private void ShowSyncState() + { + } + } +} diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Properties/Resources.Designer.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Properties/Resources.Designer.cs index 76429bb..961bee0 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Properties/Resources.Designer.cs +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Properties/Resources.Designer.cs @@ -324,6 +324,26 @@ namespace Acacia.Properties { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap Progress0 { + get { + object obj = ResourceManager.GetObject("Progress0", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap Progress1 { + get { + object obj = ResourceManager.GetObject("Progress1", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -745,6 +765,42 @@ namespace Acacia.Properties { } } + /// + /// Looks up a localized string similar to Syncing: {0}%. + /// + internal static string Ribbon_SyncState_Label { + get { + return ResourceManager.GetString("Ribbon_SyncState_Label", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Up-to-date. + /// + internal static string Ribbon_SyncState_Label_Done { + get { + return ResourceManager.GetString("Ribbon_SyncState_Label_Done", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Synchronisation state. + /// + internal static string Ribbon_SyncState_Screentip { + get { + return ResourceManager.GetString("Ribbon_SyncState_Screentip", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Open the "Synchronisation" dialog, in which the synchronisation state can be viewed and managed.. + /// + internal static string Ribbon_SyncState_Supertip { + get { + return ResourceManager.GetString("Ribbon_SyncState_Supertip", resourceCulture); + } + } + /// /// Looks up a localized string similar to Kopano. /// diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Properties/Resources.resx b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Properties/Resources.resx index 93f2739..cf507ad 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Properties/Resources.resx +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Properties/Resources.resx @@ -457,4 +457,23 @@ There are unsaved changes. Do you really want to to discard these? + + ..\Resources\Icons\Progress0.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\Icons\Progress1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + Syncing: {0}% + {0} will be replaced with progress in percent + + + Up-to-date + + + Synchronisation state + + + Open the "Synchronisation" dialog, in which the synchronisation state can be viewed and managed. + \ No newline at end of file diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Resources/Icons/Progress0.png b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Resources/Icons/Progress0.png new file mode 100644 index 0000000000000000000000000000000000000000..132939b827c213f9e60e088910c562821c8fd85d GIT binary patch literal 295 zcmeAS@N?(olHy`uVBq!ia0vp^HXzKw1|+Ti+$;i8Ea{HEjtmSN`?>!lvI6;>1s;*b z3=EQ2L6~uC#_I;4pk#?_L`iUdT1k0gQ7S`0VrE{6US4X6f{C7io}sY`b95C@(GpJ= z$B+!?w^ujv9x&ixF??@7&-^0`*94`jz7FmTvtRGKG;8MSlqsns!nJ$9-+3ZibNX-d w*WYaOi`RYNzgF9vKk0nrv_KN!Mbp=e53jcPh1oo;1-h5P)78&qol`;+0M!(7o&W#< literal 0 HcmV?d00001 diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Resources/Icons/Progress1.png b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Resources/Icons/Progress1.png new file mode 100644 index 0000000000000000000000000000000000000000..ce01430176dd93ec7d3bbf6c6d86f411e58ae8d2 GIT binary patch literal 300 zcmeAS@N?(olHy`uVBq!ia0vp^HXzKw1|+Ti+$;i8Ea{HEjtmSN`?>!lvI6;>1s;*b z3=EQ2L6~uC#_I;4pk#?_L`iUdT1k0gQ7S`0VrE{6US4X6f{C7io}sY`b95C@(MnGj z$B+!?w^tVmG8+o8IJV|KlQ}BWHgo2_Qx7h>T=>4==PVbeOi3jXuHE~6<`erL ze}DFV;JJ3UIsUixA>)X0{&_0rBc}zD2rrgiW1Ud9JTfzsTNCJL22WQ%mvv4FO#nBG BbxZ&N literal 0 HcmV?d00001 diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/UI/Outlook/CommandElement.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/UI/Outlook/CommandElement.cs index eb53650..85748f2 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/UI/Outlook/CommandElement.cs +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/UI/Outlook/CommandElement.cs @@ -35,6 +35,8 @@ namespace Acacia.UI.Outlook public CheckCommandHandler CheckEnabled; public CheckCommandHandler CheckVisible; + public DataProvider DataProvider { get; set; } + public CommandElement(FeatureWithUI feature, string id, System.Action callback, ZPushBehaviour zpushBehaviour) { @@ -65,6 +67,11 @@ namespace Acacia.UI.Outlook Logger.Instance.Trace(Owner, "Command {0}: Handled", Id); } + public void Invalidate() + { + UI?.InvalidateCommand(this); + } + private bool _isEnabled = true; public bool IsEnabled { @@ -78,7 +85,7 @@ namespace Acacia.UI.Outlook if (_isEnabled != value) { _isEnabled = value; - UI?.InvalidateCommand(this); + Invalidate(); } } } @@ -96,7 +103,7 @@ namespace Acacia.UI.Outlook if (_isVisible != value) { _isVisible = value; - UI?.InvalidateCommand(this); + Invalidate(); } } } diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/UI/Outlook/DataProvider.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/UI/Outlook/DataProvider.cs new file mode 100644 index 0000000..80bd763 --- /dev/null +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/UI/Outlook/DataProvider.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Acacia.UI.Outlook +{ + public interface DataProvider + { + string GetLabel(string elementId); + string GetScreenTip(string elementId); + string GetSuperTip(string elementId); + Bitmap GetImage(string elementId, bool large); + } +} diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/UI/Outlook/OutlookUI.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/UI/Outlook/OutlookUI.cs index 1f88a94..6fb19e8 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/UI/Outlook/OutlookUI.cs +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/UI/Outlook/OutlookUI.cs @@ -242,47 +242,84 @@ namespace Acacia.UI.Outlook this._officeUI = ribbonUI; } + private class ResourceDataProvider : DataProvider + { + public Bitmap GetImage(string elementId, bool large) + { + string id = "Ribbon_" + elementId + (large ? "" : "_Small"); + object o = Properties.Resources.ResourceManager.GetObject(id); + if (o == null) + throw new InvalidDataException("Missing image resource " + id); + return o as Bitmap; + } + + public string GetLabel(string elementId) + { + return GetString(elementId, "Label"); + } + + public string GetScreenTip(string elementId) + { + return GetString(elementId, "Screentip"); + } + + public string GetSuperTip(string elementId) + { + return GetString(elementId, "Supertip"); + } + + private string GetString(string elementId, string suffix) + { + string id = "Ribbon_" + elementId + "_" + suffix; + string s = Properties.Resources.ResourceManager.GetString(id); + if (s == null) + throw new InvalidDataException("Missing string resource " + id); + return s; + } + } + + private static readonly DataProvider RESOURCE_DATA_PROVIDER = new ResourceDataProvider(); + + private CommandElement GetCommand(Office.IRibbonControl control) + { + CommandElement command = null; + _commandIds.TryGetValue(control.Id, out command); + return command; + } + + private DataProvider GetDataProvider(CommandElement cmd) + { + return cmd?.DataProvider ?? RESOURCE_DATA_PROVIDER; + } + public Bitmap getControlImage_large(Office.IRibbonControl control) { - return GetControlImage(control, ""); + CommandElement cmd = GetCommand(control); + return GetDataProvider(cmd).GetImage(control.Id, true); } public Bitmap getControlImage_normal(Office.IRibbonControl control) { - return GetControlImage(control, "_Small"); - } - - private Bitmap GetControlImage(Office.IRibbonControl control, string suffix) - { - string id = "Ribbon_" + control.Id + suffix; - object o = Properties.Resources.ResourceManager.GetObject(id); - if (o == null) - throw new InvalidDataException("Missing image resource " + id); - return o as Bitmap; + CommandElement cmd = GetCommand(control); + return GetDataProvider(cmd).GetImage(control.Id, false); } public string getControlLabel(Office.IRibbonControl control) { - return GetString(control, "Label"); + CommandElement cmd = GetCommand(control); + return GetDataProvider(cmd).GetLabel(control.Id); } public string getControlScreentip(Office.IRibbonControl control) { - return GetString(control, "Screentip"); + CommandElement cmd = GetCommand(control); + return GetDataProvider(cmd).GetScreenTip(control.Id); } public string getControlSupertip(Office.IRibbonControl control) { - return GetString(control, "Supertip"); - } - - private string GetString(Office.IRibbonControl control, string suffix) - { - string id = "Ribbon_" + control.Id + "_" + suffix; - string s = Properties.Resources.ResourceManager.GetString(id); - if (s == null) - throw new InvalidDataException("Missing string resource " + id); - return s; + CommandElement cmd = GetCommand(control); + return GetDataProvider(cmd).GetSuperTip(control.Id); } #endregion