From ae076fe12f14c1ec688b43b7ba0b7d4ad008b7b6 Mon Sep 17 00:00:00 2001 From: Patrick Simpson Date: Wed, 29 Nov 2017 11:18:10 +0200 Subject: [PATCH] [KOE-124] Added UI support for opening whole stores --- .../Controls/KCheckManager.cs | 28 +- .../Controls/KTreeNodeLoader.cs | 5 + .../SharedFoldersDialog.Designer.cs | 54 ++- .../SharedFolders/SharedFoldersDialog.cs | 373 +++++++++++++----- .../SharedFolders/SharedFoldersDialog.resx | 198 +++++++--- .../SharedFolders/SharedFoldersManager.cs | 5 + .../Features/SharedFolders/StoreTreeNode.cs | 57 ++- 7 files changed, 525 insertions(+), 195 deletions(-) diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Controls/KCheckManager.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Controls/KCheckManager.cs index 86974c7..c8c811b 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Controls/KCheckManager.cs +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Controls/KCheckManager.cs @@ -29,7 +29,8 @@ namespace Acacia.Controls TwoState, ThreeState, Recursive, - RecursiveThreeState + RecursiveThreeState, + Custom } abstract public class KCheckManager @@ -119,7 +120,7 @@ namespace Acacia.Controls // Set the check state recursively node.Owner?.BeginUpdate(); - SetNodeCheckState(node, NextCheckState(node.CheckState)); + SetNodeCheckState(node, NextCheckState(node)); // Update the parent state SetParentCheckState(node.Parent, node.CheckState); @@ -130,12 +131,12 @@ namespace Acacia.Controls } } - protected virtual CheckState NextCheckState(CheckState checkState) + protected virtual CheckState NextCheckState(KTreeNode node) { - return (checkState == CheckState.Checked) ? CheckState.Unchecked : CheckState.Checked; + return (node.CheckState == CheckState.Checked) ? CheckState.Unchecked : CheckState.Checked; } - protected void SetParentCheckState(KTreeNode parent, CheckState childCheckState) + protected virtual void SetParentCheckState(KTreeNode parent, CheckState childCheckState) { if (parent == null) return; @@ -174,11 +175,18 @@ namespace Acacia.Controls SetParentCheckState(parent.Parent, parent.CheckState); } - private void SetNodeCheckState(KTreeNode node, CheckState checkState) + protected virtual void SetChildrenCheckState(KTreeNode parent, CheckState checkState) + { + foreach (KTreeNode child in parent.Children) + SetNodeCheckState(child, checkState != CheckState.Indeterminate ? checkState : CheckState.Unchecked); + } + + protected virtual void SetNodeCheckState(KTreeNode node, CheckState checkState) { // Apply the children first, otherwise the node's check state will be based on that again - foreach (KTreeNode child in node.Children) - SetNodeCheckState(child, checkState != CheckState.Indeterminate ? checkState : CheckState.Unchecked); + SetChildrenCheckState(node, checkState); + + // Set the node now node.CheckState = checkState; } @@ -252,9 +260,9 @@ namespace Acacia.Controls SetParentCheckState(node.Parent, state); } - protected override CheckState NextCheckState(CheckState checkState) + protected override CheckState NextCheckState(KTreeNode node) { - switch(checkState) + switch(node.CheckState) { case CheckState.Unchecked: return CheckState.Indeterminate; diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Controls/KTreeNodeLoader.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Controls/KTreeNodeLoader.cs index 5022ade..13f5540 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Controls/KTreeNodeLoader.cs +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Controls/KTreeNodeLoader.cs @@ -197,6 +197,11 @@ namespace Acacia.Controls EndLoading(node); } + public void Reset() + { + State = LoadingState.NotLoaded; + } + public void Reload() { if (State != LoadingState.Loading) diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/SharedFolders/SharedFoldersDialog.Designer.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/SharedFolders/SharedFoldersDialog.Designer.cs index 15555f7..40b4a14 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/SharedFolders/SharedFoldersDialog.Designer.cs +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/SharedFolders/SharedFoldersDialog.Designer.cs @@ -29,7 +29,6 @@ private void InitializeComponent() { System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(SharedFoldersDialog)); - Acacia.Controls.KCheckManager.RecursiveThreeState recursiveThreeState1 = new Acacia.Controls.KCheckManager.RecursiveThreeState(); this._layout = new System.Windows.Forms.TableLayoutPanel(); this._mainBusyHider = new Acacia.Controls.KBusyHider(); this._layoutMain = new System.Windows.Forms.TableLayoutPanel(); @@ -39,6 +38,9 @@ this.buttonOpenUser = new System.Windows.Forms.Button(); this.kTreeFolders = new Acacia.Controls.KTree(); this._layoutOptions = new System.Windows.Forms.TableLayoutPanel(); + this._labelWholeStore = new System.Windows.Forms.Label(); + this.checkWholeStore = new System.Windows.Forms.CheckBox(); + this.labelPermissionsValue = new System.Windows.Forms.Label(); this._labelName = new System.Windows.Forms.Label(); this.textName = new System.Windows.Forms.TextBox(); this._labelSendAs = new System.Windows.Forms.Label(); @@ -46,7 +48,6 @@ this._labelReminders = new System.Windows.Forms.Label(); this.checkReminders = new System.Windows.Forms.CheckBox(); this._labelPermissions = new System.Windows.Forms.Label(); - this.labelPermissionsValue = new System.Windows.Forms.Label(); this.dialogButtons = new Acacia.Controls.KDialogButtons(); this._layout.SuspendLayout(); this._mainBusyHider.SuspendLayout(); @@ -118,8 +119,8 @@ // this.kTreeFolders.BackColor = System.Drawing.SystemColors.Window; this.kTreeFolders.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.kTreeFolders.CheckManager = recursiveThreeState1; - this.kTreeFolders.CheckStyle = Acacia.Controls.KCheckStyle.RecursiveThreeState; + this.kTreeFolders.CheckManager = null; + this.kTreeFolders.CheckStyle = Acacia.Controls.KCheckStyle.None; resources.ApplyResources(this.kTreeFolders, "kTreeFolders"); this.kTreeFolders.FullRowSelect = true; this.kTreeFolders.Images = null; @@ -129,21 +130,39 @@ this.kTreeFolders.NodePadding = new System.Windows.Forms.Padding(2, 4, 2, 4); this.kTreeFolders.CheckStateChanged += new Acacia.Controls.KTree.CheckStateChangedHandler(this.kTreeFolders_CheckStateChanged); this.kTreeFolders.SelectionChanged += new Acacia.Controls.KTree.SelectionChangedDelegate(this.kTreeFolders_SelectionChanged); - this.kTreeFolders.DoubleClick += new System.EventHandler(this.kTreeFolders_DoubleClick); // // _layoutOptions // resources.ApplyResources(this._layoutOptions, "_layoutOptions"); - this._layoutOptions.Controls.Add(this._labelName, 0, 0); - this._layoutOptions.Controls.Add(this.textName, 1, 0); - this._layoutOptions.Controls.Add(this._labelSendAs, 0, 1); - this._layoutOptions.Controls.Add(this.checkSendAs, 1, 1); - this._layoutOptions.Controls.Add(this._labelReminders, 0, 2); - this._layoutOptions.Controls.Add(this.checkReminders, 1, 2); - this._layoutOptions.Controls.Add(this._labelPermissions, 0, 3); - this._layoutOptions.Controls.Add(this.labelPermissionsValue, 1, 3); + this._layoutOptions.Controls.Add(this._labelWholeStore, 0, 0); + this._layoutOptions.Controls.Add(this.checkWholeStore, 1, 0); + this._layoutOptions.Controls.Add(this.labelPermissionsValue, 0, 4); + this._layoutOptions.Controls.Add(this._labelName, 0, 1); + this._layoutOptions.Controls.Add(this.textName, 1, 1); + this._layoutOptions.Controls.Add(this._labelSendAs, 0, 2); + this._layoutOptions.Controls.Add(this.checkSendAs, 1, 2); + this._layoutOptions.Controls.Add(this._labelReminders, 0, 3); + this._layoutOptions.Controls.Add(this.checkReminders, 1, 3); + this._layoutOptions.Controls.Add(this._labelPermissions, 0, 4); this._layoutOptions.Name = "_layoutOptions"; // + // _labelWholeStore + // + resources.ApplyResources(this._labelWholeStore, "_labelWholeStore"); + this._labelWholeStore.Name = "_labelWholeStore"; + // + // checkWholeStore + // + resources.ApplyResources(this.checkWholeStore, "checkWholeStore"); + this.checkWholeStore.Name = "checkWholeStore"; + this.checkWholeStore.UseVisualStyleBackColor = true; + this.checkWholeStore.CheckedChanged += new System.EventHandler(this.checkWholeStore_CheckedChanged); + // + // labelPermissionsValue + // + resources.ApplyResources(this.labelPermissionsValue, "labelPermissionsValue"); + this.labelPermissionsValue.Name = "labelPermissionsValue"; + // // _labelName // resources.ApplyResources(this._labelName, "_labelName"); @@ -185,11 +204,6 @@ resources.ApplyResources(this._labelPermissions, "_labelPermissions"); this._labelPermissions.Name = "_labelPermissions"; // - // labelPermissionsValue - // - resources.ApplyResources(this.labelPermissionsValue, "labelPermissionsValue"); - this.labelPermissionsValue.Name = "labelPermissionsValue"; - // // dialogButtons // resources.ApplyResources(this.dialogButtons, "dialogButtons"); @@ -237,11 +251,13 @@ private System.Windows.Forms.Label _labelSendAs; private System.Windows.Forms.CheckBox checkSendAs; private System.Windows.Forms.Label _labelPermissions; - private System.Windows.Forms.Label labelPermissionsValue; + private System.Windows.Forms.Label _labelWholeStore; private Controls.KBusyHider _mainBusyHider; private Controls.KDialogButtons dialogButtons; private UI.GABLookupControl gabLookup; private System.Windows.Forms.Label _labelReminders; private System.Windows.Forms.CheckBox checkReminders; + private System.Windows.Forms.CheckBox checkWholeStore; + private System.Windows.Forms.Label labelPermissionsValue; } } \ No newline at end of file diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/SharedFolders/SharedFoldersDialog.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/SharedFolders/SharedFoldersDialog.cs index 444f876..1a48110 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/SharedFolders/SharedFoldersDialog.cs +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/SharedFolders/SharedFoldersDialog.cs @@ -16,6 +16,7 @@ using Acacia.Controls; using Acacia.Features.GAB; +using Acacia.Stubs; using Acacia.UI; using Acacia.UI.Outlook; using Acacia.ZPush; @@ -37,6 +38,58 @@ namespace Acacia.Features.SharedFolders { public partial class SharedFoldersDialog : KDialogNew { + /// + /// Check manager that makes the store check box independent of the folder checkboxes, which are + /// still applied recursively + /// + private class ShareCheckManager : KCheckManager.RecursiveThreeState + { + public override KCheckStyle CheckStyle { get { return KCheckStyle.Custom; } } + + protected override void SetParentCheckState(KTreeNode parent, CheckState childCheckState) + { + // The store node state is independent of the rest + if (parent == null || parent is StoreTreeNode) + return; + + base.SetParentCheckState(parent, childCheckState); + } + + protected override void SetNodeCheckState(KTreeNode node, CheckState checkState) + { + // The store node state is independent of the rest + if (node is StoreTreeNode) + node.CheckState = checkState; + else + base.SetNodeCheckState(node, checkState); + } + + protected override CheckState NextCheckState(KTreeNode node) + { + if (node is StoreTreeNode) + { + // The store node has a two-state checkbox + return (node.CheckState == CheckState.Checked) ? CheckState.Unchecked : CheckState.Checked; + } + else + { + return base.NextCheckState(node); + } + } + + public override void SetCheck(KTreeNode node, CheckState state) + { + if (node is StoreTreeNode) + { + node.CheckStateDirect = state; + } + else + { + base.SetCheck(node, state); + } + } + } + private readonly ZPushAccount _account; private readonly SharedFoldersManager _folders; private readonly SyncId _initialSyncId; @@ -67,6 +120,9 @@ namespace Acacia.Features.SharedFolders ).Images; + // Set the check manager + kTreeFolders.CheckManager = new ShareCheckManager(); + // Add the email address to the title Text = string.Format(Text, account.Account.SmtpAddress); @@ -143,10 +199,10 @@ namespace Acacia.Features.SharedFolders { KTreeNode folderNode = node.FindNode(_initialFolder); if (folderNode != null) - FocusNode(folderNode); + FocusNode(folderNode, true); context.AddBusy(-1); }; - FocusNode(node); + FocusNode(node, true); } SetInitialFocus(kTreeFolders); } @@ -165,41 +221,77 @@ namespace Acacia.Features.SharedFolders }); } + private class ApplyState + { + public int folders; + public readonly List stores = new List(); + } + private void dialogButtons_Apply(object sender, EventArgs e) { BusyText = Properties.Resources.SharedFolders_Applying_Label; KUITask.New((ctx) => { // We reuse the same busy indicationg for all calls. A count is kept to ensure it's removed. - int count = 0; + ApplyState state = new ApplyState(); foreach (StoreTreeNode storeNode in _userFolders.Values) { if (storeNode.IsDirty) { ctx.AddBusy(1); - ++count; + ++state.folders; _folders.SetSharesForStore(storeNode.User, storeNode.CurrentShares, ctx.CancellationToken); } + + if (storeNode.IsWholeStoreDirty) + { + state.stores.Add(storeNode); + } } - return count; + return state; }) - .OnSuccess((ctx, count) => + .OnSuccess((ctx, state) => { // Update UI state foreach (StoreTreeNode storeNode in _userFolders.Values) if (storeNode.IsDirty) storeNode.ChangesApplied(); - ctx.AddBusy(-count); + ctx.AddBusy(-state.folders); - // Sync account - _account.Account.SendReceive(); + if (state.folders != 0) + { + // Sync account + _account.Account.SendReceive(); - // Show success - ShowCompletion(Properties.Resources.SharedFolders_Applying_Success); + // Show success + ShowCompletion(Properties.Resources.SharedFolders_Applying_Success); + } + + if (state.stores.Count > 0) + { + bool restart = MessageBox.Show(ThisAddIn.Instance.Window, + "Outlook will be restarted to open the new stores", + "Open stores", + MessageBoxButtons.OKCancel, + MessageBoxIcon.Information + ) == DialogResult.OK; + + // Reset state. Also do this when restarting, to avoid warning message about unsaved changes + foreach (StoreTreeNode node in state.stores) + node.WantShare = node.IsShared; + + if (!restart) + return; + + // Restart + IRestarter restarter = ThisAddIn.Instance.Restarter(); + restarter.CloseWindows = true; + restarter.Restart(); + } }, true) .OnError((x) => { @@ -263,23 +355,24 @@ namespace Acacia.Features.SharedFolders node = new StoreTreeNode(_folders, gabLookup.GAB, user, user.DisplayName, currentShares ?? new Dictionary()); node.DirtyChanged += UserSharesChanged; + node.CheckStateChanged += WholeStoreShareChanged; _userFolders.Add(user, node); kTreeFolders.RootNodes.Add(node); } if (select) { - FocusNode(node); + FocusNode(node, false); } } - private void FocusNode(KTreeNode node) + private void FocusNode(KTreeNode node, bool expand) { // Scroll it to the top of the window kTreeFolders.SelectNode(node, KTree.ScrollMode.Top); - // Start loading folders - node.IsExpanded = true; + // Start loading folders if requested + node.IsExpanded = expand; // Clear any selected user gabLookup.SelectedUser = null; @@ -288,12 +381,25 @@ namespace Acacia.Features.SharedFolders kTreeFolders.Focus(); } - private readonly Dictionary _dirtyUsers = new Dictionary(); + private readonly Dictionary _dirtyWholeStores = new Dictionary(); + private readonly Dictionary _dirtyUsers = new Dictionary(); private void UserSharesChanged(StoreTreeNode node) { - _dirtyUsers[node.User.UserName] = node.IsDirty; - dialogButtons.IsDirty = _dirtyUsers.Values.Any((x) => x); + _dirtyUsers[node.User] = node.IsDirty; + CheckDirty(); + } + + private void WholeStoreShareChanged(KTreeNode node) + { + StoreTreeNode storeNode = (StoreTreeNode)node; + _dirtyWholeStores[storeNode.User] = storeNode.IsWholeStoreDirty; + CheckDirty(); + } + + private void CheckDirty() + { + dialogButtons.IsDirty = _dirtyUsers.Values.Any((x) => x) || _dirtyWholeStores.Values.Any((x) => x); } #region Advanced options @@ -392,6 +498,25 @@ namespace Acacia.Features.SharedFolders } private readonly List _optionPermissionNodes = new List(); + private CheckState? OptionWholeStore + { + get + { + if (checkWholeStore.Visible) + return checkWholeStore.CheckState; + return null; + } + + set + { + _labelWholeStore.Visible = checkWholeStore.Visible = value != null; + if (value != null) + checkWholeStore.CheckState = value.Value; + } + } + private readonly List _optionWholeStoreNodes = new List(); + private readonly List _optionWholeStoreNodesInitial = new List(); + private void ShowOptions(KTreeNode[] nodes) { try @@ -404,102 +529,146 @@ namespace Acacia.Features.SharedFolders _optionRemindersNodes.Clear(); _optionRemindersInitial.Clear(); _optionPermissionNodes.Clear(); + _optionWholeStoreNodes.Clear(); + _optionWholeStoreNodesInitial.Clear(); OptionName = null; OptionTrackName = null; OptionSendAs = null; OptionReminders = null; OptionPermissions = null; + OptionWholeStore = null; bool readOnly = false; + bool haveStoreNodes = false; + bool haveFolderNodes = false; foreach (KTreeNode node in nodes) { // Ignore the root nodes if (node is StoreTreeNode) - continue; - - FolderTreeNode folderNode = (FolderTreeNode)node; - // Can only set options for shared folders - if (!folderNode.IsShared) - continue; - - // Set all controls to read-only if any of the nodes is read-only - if (folderNode.IsReadOnly) - readOnly = true; - - SharedFolder share = folderNode.SharedFolder; - AvailableFolder folder = folderNode.AvailableFolder; - - // Assume we will edit the name for this node; cleared below if there are multiple - _optionNameNode = folderNode; - - if (folder.Type.IsMail()) { - // Show send as if there are any mail folders - _optionSendAsNodes.Add(folderNode); - _optionSendAsInitial.Add(folderNode.SharedFolder.FlagSendAsOwner); - } - else if (folder.Type.IsAppointment()) - { - // Show reminders for appointment folders - _optionRemindersNodes.Add(folderNode); - _optionRemindersInitial.Add(folderNode.SharedFolder.FlagCalendarReminders); - } + if (!_folders.SupportsWholeStore) + continue; - // Show permissions for all shared nodes - _optionPermissionNodes.Add(folderNode); + StoreTreeNode storeNode = (StoreTreeNode)node; + haveStoreNodes = true; + _optionWholeStoreNodes.Add(storeNode); + _optionWholeStoreNodesInitial.Add(storeNode.IsShared); + } + else + { + FolderTreeNode folderNode = (FolderTreeNode)node; + // Can only set options for shared folders + if (!folderNode.IsShared) + continue; + + haveFolderNodes = true; + + // Set all controls to read-only if any of the nodes is read-only + if (folderNode.IsReadOnly) + readOnly = true; + + SharedFolder share = folderNode.SharedFolder; + AvailableFolder folder = folderNode.AvailableFolder; + + // Assume we will edit the name for this node; cleared below if there are multiple + _optionNameNode = folderNode; + + if (folder.Type.IsMail()) + { + // Show send as if there are any mail folders + _optionSendAsNodes.Add(folderNode); + _optionSendAsInitial.Add(folderNode.SharedFolder.FlagSendAsOwner); + } + else if (folder.Type.IsAppointment()) + { + // Show reminders for appointment folders + _optionRemindersNodes.Add(folderNode); + _optionRemindersInitial.Add(folderNode.SharedFolder.FlagCalendarReminders); + } + + // Show permissions for all shared nodes + _optionPermissionNodes.Add(folderNode); + } } // Now check consistency of the options - // Only show the name if there is a single node. - // We do that here so there doesn't have to be duplication if testing if it's sharedd, - // ect - if (_optionNameNode != null && nodes.Length == 1) + if (haveFolderNodes && haveStoreNodes) { - OptionName = _optionNameNode.SharedFolder.Name; - OptionTrackName = _optionNameNode.SharedFolder.FlagUpdateShareName; + // Mixed nodes, no options + return; + } + + if (haveStoreNodes) + { + if (_optionWholeStoreNodes.Count > 0) + { + bool isShared = _optionWholeStoreNodes.First().WantShare; + if (_optionWholeStoreNodes.All(x => x.WantShare == isShared)) + { + OptionWholeStore = isShared ? CheckState.Checked : CheckState.Unchecked; + checkWholeStore.ThreeState = false; + } + else + { + OptionWholeStore = CheckState.Indeterminate; + checkWholeStore.ThreeState = true; + } + } + } else { - _optionNameNode = null; - } - - // Permissions shown if all are the same - if (_optionPermissionNodes.Count > 0) - { - Permission? permissions = _optionPermissionNodes.First().SharedFolder.Permissions; - if (_optionPermissionNodes.All(x => x.SharedFolder.Permissions == permissions)) - OptionPermissions = permissions; - } - - // Send as shown if any node supports it - if (_optionSendAsNodes.Count > 0) - { - bool sendAs = _optionSendAsNodes.First().SharedFolder.FlagSendAsOwner; - if (_optionSendAsNodes.All(x => x.SharedFolder.FlagSendAsOwner == sendAs)) + // Only show the name if there is a single node. + // We do that here so there doesn't have to be duplication if testing if it's sharedd, + // ect + if (_optionNameNode != null && nodes.Length == 1) { - OptionSendAs = sendAs ? CheckState.Checked : CheckState.Unchecked; - checkSendAs.ThreeState = false; + OptionName = _optionNameNode.SharedFolder.Name; + OptionTrackName = _optionNameNode.SharedFolder.FlagUpdateShareName; } else { - OptionSendAs = CheckState.Indeterminate; - checkSendAs.ThreeState = true; + _optionNameNode = null; } - } - // Reminders shown if any node supports it - if (_optionRemindersNodes.Count > 0) - { - bool reminders = _optionRemindersNodes.First().SharedFolder.FlagCalendarReminders; - if (_optionRemindersNodes.All(x => x.SharedFolder.FlagCalendarReminders == reminders)) + + // Permissions shown if all are the same + if (_optionPermissionNodes.Count > 0) { - OptionReminders = reminders ? CheckState.Checked : CheckState.Unchecked; - checkReminders.ThreeState = false; + Permission? permissions = _optionPermissionNodes.First().SharedFolder.Permissions; + if (_optionPermissionNodes.All(x => x.SharedFolder.Permissions == permissions)) + OptionPermissions = permissions; } - else + + // Send as shown if any node supports it + if (_optionSendAsNodes.Count > 0) { - OptionReminders = CheckState.Indeterminate; - checkReminders.ThreeState = true; + bool sendAs = _optionSendAsNodes.First().SharedFolder.FlagSendAsOwner; + if (_optionSendAsNodes.All(x => x.SharedFolder.FlagSendAsOwner == sendAs)) + { + OptionSendAs = sendAs ? CheckState.Checked : CheckState.Unchecked; + checkSendAs.ThreeState = false; + } + else + { + OptionSendAs = CheckState.Indeterminate; + checkSendAs.ThreeState = true; + } + } + // Reminders shown if any node supports it + if (_optionRemindersNodes.Count > 0) + { + bool reminders = _optionRemindersNodes.First().SharedFolder.FlagCalendarReminders; + if (_optionRemindersNodes.All(x => x.SharedFolder.FlagCalendarReminders == reminders)) + { + OptionReminders = reminders ? CheckState.Checked : CheckState.Unchecked; + checkReminders.ThreeState = false; + } + else + { + OptionReminders = CheckState.Indeterminate; + checkReminders.ThreeState = true; + } } } @@ -538,6 +707,23 @@ namespace Acacia.Features.SharedFolders } } + private void checkWholeStore_CheckedChanged(object sender, EventArgs e) + { + for (int i = 0; i < _optionWholeStoreNodes.Count; ++i) + { + StoreTreeNode node = _optionWholeStoreNodes[i]; + bool wholeStore = false; + switch (checkWholeStore.CheckState) + { + case CheckState.Checked: wholeStore = true; break; + case CheckState.Indeterminate: wholeStore = _optionWholeStoreNodesInitial[i]; break; + case CheckState.Unchecked: wholeStore = false; break; + } + + node.WantShare = wholeStore; + } + } + private void checkSendAs_CheckedChanged(object sender, EventArgs e) { for (int i = 0; i < _optionSendAsNodes.Count; ++i) @@ -586,22 +772,5 @@ namespace Acacia.Features.SharedFolders #endregion - private void kTreeFolders_DoubleClick(object sender, EventArgs e) - { - // TODO: This is some testing code for [KOE-123] - /* - if (ModifierKeys.HasFlag(Keys.Shift) && kTreeFolders.SelectedNodes.Count == 1) - { - KTreeNode selected = kTreeFolders.SelectedNodes.First(); - if (selected is StoreTreeNode) - { - // Open store for user - Acacia.Stubs.IRestarter restarter = ThisAddIn.Instance.Restarter(); - restarter.CloseWindows = true; - restarter.OpenShare(this._account, ((StoreTreeNode)selected).User); - restarter.Restart(); - } - }*/ - } } } diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/SharedFolders/SharedFoldersDialog.resx b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/SharedFolders/SharedFoldersDialog.resx index 79c73f4..4949a8e 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/SharedFolders/SharedFoldersDialog.resx +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/SharedFolders/SharedFoldersDialog.resx @@ -283,7 +283,7 @@ 3, 38 - 442, 277 + 442, 250 1 @@ -309,6 +309,117 @@ 2 + + True + + + Fill + + + MiddleLeft + + + 3, 0 + + + 0, 4, 0, 3 + + + 90, 27 + + + 5 + + + Open whole store + + + MiddleLeft + + + _labelWholeStore + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + _layoutOptions + + + 0 + + + True + + + Left + + + NoControl + + + 102, 4 + + + 6, 4, 3, 3 + + + 0, 3, 0, 3 + + + 15, 20 + + + 9 + + + checkWholeStore + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + _layoutOptions + + + 1 + + + True + + + Fill + + + NoControl + + + 99, 107 + + + 346, 20 + + + 8 + + + Share as + + + MiddleLeft + + + labelPermissionsValue + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + _layoutOptions + + + 2 + True @@ -316,10 +427,10 @@ Fill - 3, 0 + 3, 27 - 82, 26 + 90, 26 0 @@ -340,19 +451,19 @@ _layoutOptions - 0 + 3 Fill - 94, 3 + 102, 30 6, 3, 3, 3 - 351, 20 + 343, 20 0 @@ -367,7 +478,7 @@ _layoutOptions - 1 + 4 True @@ -376,10 +487,10 @@ Fill - 3, 26 + 3, 53 - 82, 27 + 90, 27 2 @@ -400,7 +511,7 @@ _layoutOptions - 2 + 5 True @@ -409,7 +520,7 @@ Left - 94, 30 + 102, 57 6, 4, 3, 3 @@ -433,7 +544,7 @@ _layoutOptions - 3 + 6 True @@ -442,10 +553,10 @@ Fill - 3, 53 + 3, 80 - 82, 27 + 90, 27 6 @@ -466,7 +577,7 @@ _layoutOptions - 4 + 7 True @@ -475,7 +586,7 @@ Left - 94, 57 + 102, 84 6, 4, 3, 3 @@ -499,7 +610,7 @@ _layoutOptions - 5 + 8 True @@ -508,13 +619,13 @@ Fill - 3, 80 + 3, 107 0, 4, 0, 3 - 82, 20 + 90, 20 4 @@ -535,61 +646,22 @@ _layoutOptions - 6 - - - True - - - Fill - - - MiddleLeft - - - 91, 80 - - - 0, 4, 0, 3 - - - 354, 20 - - - 5 - - - Permissions - - - MiddleLeft - - - labelPermissionsValue - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - _layoutOptions - - - 7 + 9 Fill - 0, 318 + 0, 291 0, 0, 0, 0 - 4 + 5 - 448, 100 + 448, 127 2 @@ -607,7 +679,7 @@ 2 - <?xml version="1.0" encoding="utf-16"?><TableLayoutSettings><Controls><Control Name="_labelName" Row="0" RowSpan="1" Column="0" ColumnSpan="1" /><Control Name="textName" Row="0" RowSpan="1" Column="1" ColumnSpan="1" /><Control Name="_labelSendAs" Row="1" RowSpan="1" Column="0" ColumnSpan="1" /><Control Name="checkSendAs" Row="1" RowSpan="1" Column="1" ColumnSpan="1" /><Control Name="_labelReminders" Row="2" RowSpan="1" Column="0" ColumnSpan="1" /><Control Name="checkReminders" Row="2" RowSpan="1" Column="1" ColumnSpan="1" /><Control Name="_labelPermissions" Row="3" RowSpan="1" Column="0" ColumnSpan="1" /><Control Name="labelPermissionsValue" Row="3" RowSpan="1" Column="1" ColumnSpan="1" /></Controls><Columns Styles="AutoSize,0,Percent,100" /><Rows Styles="AutoSize,0,AutoSize,0,AutoSize,0,AutoSize,0,Absolute,20" /></TableLayoutSettings> + <?xml version="1.0" encoding="utf-16"?><TableLayoutSettings><Controls><Control Name="_labelWholeStore" Row="0" RowSpan="1" Column="0" ColumnSpan="1" /><Control Name="checkWholeStore" Row="0" RowSpan="1" Column="1" ColumnSpan="1" /><Control Name="labelPermissionsValue" Row="4" RowSpan="1" Column="0" ColumnSpan="1" /><Control Name="_labelName" Row="1" RowSpan="1" Column="0" ColumnSpan="1" /><Control Name="textName" Row="1" RowSpan="1" Column="1" ColumnSpan="1" /><Control Name="_labelSendAs" Row="2" RowSpan="1" Column="0" ColumnSpan="1" /><Control Name="checkSendAs" Row="2" RowSpan="1" Column="1" ColumnSpan="1" /><Control Name="_labelReminders" Row="3" RowSpan="1" Column="0" ColumnSpan="1" /><Control Name="checkReminders" Row="3" RowSpan="1" Column="1" ColumnSpan="1" /><Control Name="_labelPermissions" Row="4" RowSpan="1" Column="0" ColumnSpan="1" /></Controls><Columns Styles="AutoSize,0,Percent,100" /><Rows Styles="AutoSize,0,AutoSize,0,AutoSize,0,AutoSize,0,AutoSize,0" /></TableLayoutSettings> Fill diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/SharedFolders/SharedFoldersManager.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/SharedFolders/SharedFoldersManager.cs index adbe510..9936ac8 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/SharedFolders/SharedFoldersManager.cs +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/SharedFolders/SharedFoldersManager.cs @@ -41,6 +41,11 @@ namespace Acacia.Features.SharedFolders _query.Dispose(); } + public bool SupportsWholeStore + { + get { return true; } // TODO: use capability + } + public FeatureSharedFolders Feature { get { return _feature; } } #region API diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/SharedFolders/StoreTreeNode.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/SharedFolders/StoreTreeNode.cs index a42b327..d70571d 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/SharedFolders/StoreTreeNode.cs +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/SharedFolders/StoreTreeNode.cs @@ -65,7 +65,7 @@ namespace Acacia.Features.SharedFolders ChildLoader = new UserFolderLoader(this, folders, user); ChildLoader.ReloadOnCloseOpen = true; - HasCheckBox = false; + HasCheckBox = folders.SupportsWholeStore; ApplyReadOnly(this, IsReadOnly); // TODO: better icons, better way of handling this @@ -92,6 +92,38 @@ namespace Acacia.Features.SharedFolders get { return ((UserFolderLoader)ChildLoader).User; } } + public bool IsShared + { + get { return false; } + } + + public bool WantShare + { + get + { + return CheckState != System.Windows.Forms.CheckState.Unchecked; + } + + set + { + CheckState = value ? System.Windows.Forms.CheckState.Checked : System.Windows.Forms.CheckState.Unchecked; + } + } + + protected override void OnCheckStateChanged() + { + base.OnCheckStateChanged(); + if (WantShare) + { + // Reload, this will return no children + ChildLoader.Reload(); + } + else + { + ChildLoader.Reset(); + } + } + #region Share management /// @@ -204,6 +236,14 @@ namespace Acacia.Features.SharedFolders } } + public bool IsWholeStoreDirty + { + get + { + return WantShare != IsShared; + } + } + public void ChangesApplied() { // Save a copy of current folders to initial folders @@ -232,6 +272,8 @@ namespace Acacia.Features.SharedFolders protected override object DoLoadChildren(KTreeNode node) { + if (!WantsChildren(node)) + return null; return _folders.GetStoreFolders(User); } @@ -257,8 +299,19 @@ namespace Acacia.Features.SharedFolders } } + private static bool WantsChildren(KTreeNode node) + { + // No children if we're sharing the whole store + if (node is StoreTreeNode) + return !((StoreTreeNode)node).WantShare; + return true; + } + protected override void DoRenderChildren(KTreeNode node, object loaded, KTreeNodes children) { + if (!WantsChildren(node)) + return; + List folders = (List)loaded; foreach (AvailableFolder folder in folders.OrderBy(f => f, new FolderComparer(true))) { @@ -319,6 +372,8 @@ namespace Acacia.Features.SharedFolders case KTreeNodeLoader.LoadingState.Loading: return Properties.Resources.SharedFolders_Loading; case KTreeNodeLoader.LoadingState.Loaded: + if (!WantsChildren(children.Parent)) + return null; if (children.Count == 0) return Properties.Resources.SharedFolders_None; return null;