[KOE-244] Added basic progress feature to ribbon, and disabled sync feature that just increases progress periodically.

This commit is contained in:
Patrick Simpson 2017-04-12 10:23:52 +02:00
parent fc43bd4c41
commit 9a37708b53
10 changed files with 335 additions and 26 deletions

View File

@ -287,6 +287,7 @@
<Compile Include="Features\Signatures\SignaturesSettings.Designer.cs">
<DependentUpon>SignaturesSettings.cs</DependentUpon>
</Compile>
<Compile Include="Features\SyncState\FeatureSyncState.cs" />
<Compile Include="GlobalOptions.cs" />
<Compile Include="Logging.cs" />
<Compile Include="Native\IOleWindow.cs" />
@ -337,6 +338,7 @@
<Compile Include="Stubs\OutlookWrappers\StoresWrapper.cs" />
<Compile Include="Stubs\OutlookWrappers\SyncObjectWrapper.cs" />
<Compile Include="Stubs\Wrappers.cs" />
<Compile Include="UI\Outlook\DataProvider.cs" />
<Compile Include="UI\Outlook\OutlookImageList.cs" />
<Compile Include="UI\Outlook\RibbonToggleButton.cs" />
<Compile Include="UI\Outlook\RibbonButton.cs" />
@ -618,6 +620,11 @@
<None Include="Properties\TreeLoading.gif" />
<None Include="Resources\Icons\Ribbon_About.png" />
<None Include="Resources\Icons\Ribbon_About_Small.png" />
<None Include="Resources\Icons\Progress0.png" />
<None Include="Resources\Icons\Progress1.png" />
<None Include="Resources\Icons\Progress2.png" />
<None Include="Resources\Icons\Progress3.png" />
<None Include="Resources\Icons\Progress4.png" />
<Content Include="Resources\Icons\Ribbon_AddSharedFolder.png" />
<Content Include="Resources\Icons\Ribbon_AddSharedFolder_Small.png" />
<Content Include="Resources\Icons\Ribbon_Debug.png" />

View File

@ -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),
};
}
}

View File

@ -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<http://www.gnu.org/licenses/>.
///
/// 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;
/// <summary>
/// Number in range [0,1]
/// </summary>
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()
{
}
}
}

View File

@ -324,6 +324,26 @@ namespace Acacia.Properties {
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap Progress0 {
get {
object obj = ResourceManager.GetObject("Progress0", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap Progress1 {
get {
object obj = ResourceManager.GetObject("Progress1", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
@ -745,6 +765,42 @@ namespace Acacia.Properties {
}
}
/// <summary>
/// Looks up a localized string similar to Syncing: {0}%.
/// </summary>
internal static string Ribbon_SyncState_Label {
get {
return ResourceManager.GetString("Ribbon_SyncState_Label", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Up-to-date.
/// </summary>
internal static string Ribbon_SyncState_Label_Done {
get {
return ResourceManager.GetString("Ribbon_SyncState_Label_Done", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Synchronisation state.
/// </summary>
internal static string Ribbon_SyncState_Screentip {
get {
return ResourceManager.GetString("Ribbon_SyncState_Screentip", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Open the &quot;Synchronisation&quot; dialog, in which the synchronisation state can be viewed and managed..
/// </summary>
internal static string Ribbon_SyncState_Supertip {
get {
return ResourceManager.GetString("Ribbon_SyncState_Supertip", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Kopano.
/// </summary>

View File

@ -457,4 +457,23 @@
<data name="OOF_Unsaved_Changes" xml:space="preserve">
<value>There are unsaved changes. Do you really want to to discard these?</value>
</data>
<data name="Progress0" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\Icons\Progress0.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="Progress1" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\Icons\Progress1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="Ribbon_SyncState_Label" xml:space="preserve">
<value>Syncing: {0}%</value>
<comment>{0} will be replaced with progress in percent</comment>
</data>
<data name="Ribbon_SyncState_Label_Done" xml:space="preserve">
<value>Up-to-date</value>
</data>
<data name="Ribbon_SyncState_Screentip" xml:space="preserve">
<value>Synchronisation state</value>
</data>
<data name="Ribbon_SyncState_Supertip" xml:space="preserve">
<value>Open the "Synchronisation" dialog, in which the synchronisation state can be viewed and managed.</value>
</data>
</root>

Binary file not shown.

After

Width:  |  Height:  |  Size: 295 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 300 B

View File

@ -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();
}
}
}

View File

@ -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);
}
}

View File

@ -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