public SubfolderBranchFinder( IElement parent, ElemCreationFlags options) { _parent = parent; _maxChildren = Core.SM.UI.ElementWdw.LimitChildrenCount; _subFolders = parent.Children .Choose(TryMatchSubfolder) .ToList(); _it = options.HasFlag(ElemCreationFlags.ReuseSubFolders) ? 1 : Math.Max(1, _subFolders.Count); //while (newElemCount > 0) //{ // SubfolderData data; // if (i < _subFolders.Count) // { // var (child, sfNo) = _subFolders[i]; // data = new SubfolderData(child.Id, sfNo, _maxChildren - child.ChildrenCount); // } // else // { // data = new SubfolderData(null, ++folderCount, _maxChildren); // } // newElemCount -= data.SlotsLeft; // _data.Add(data); //} }
private int FindDestinationBranch(IElement parent, ElemCreationFlags options) { if (options.HasFlag(ElemCreationFlags.CreateSubfolders) == false) { return(CanAddElement(parent, options) ? parent.Id : -1); } var regExSubfolders = new Regex($"\\[([0-9]+)\\] {Regex.Escape(parent.Title)}"); var subFolders = parent.Children .Select(child => (child, regExSubfolders.Match(child.Title))) .Where(p => p.Item2.Success) .ToList(); if (subFolders.Any() == false) { return(CreateAutoSubfolders(parent, 1)); } var subFolder = subFolders.MaxBy(p => int.Parse(p.Item2.Groups[1].Value)) .First(); if (subFolder.child == null || CanAddElement(subFolder.child, ElemCreationFlags.None) == false) { return(CreateAutoSubfolders( parent, subFolder.child == null ? 1 : int.Parse(subFolder.Item2.Groups[1].Value) + 1 )); } return(subFolder.child.Id); }
// // private bool CanAddElement(IElement parent, ElemCreationFlags options) { if (options.HasFlag(ElemCreationFlags.ForceCreate)) { return(true); } return(parent.ChildrenCount < Core.SMA.CollectionConfig.ChildrenPerBranch); }
// // private bool CanAddElement(IElement parent, ElemCreationFlags options) { if (options.HasFlag(ElemCreationFlags.ForceCreate)) { return(true); } return(parent.ChildrenCount < Core.SM.UI.ElementWdw.LimitChildrenCount); }
private async Task <List <ElemCreationResult> > AddInternalAsync( ElemCreationFlags options, ElementBuilder[] builders) { if (builders == null || builders.Length == 0) { return(null); } var inSMUpdateLockMode = false; var inSMAUpdateLockMode = false; var singleMode = builders.Length == 1; var results = new List <ElemCreationResult>( builders.Select( b => new ElemCreationResult(ElemCreationResultCodes.ErrorUnknown, b)) ); try { int restoreElementId = Core.SM.UI.ElementWdw.CurrentElementId; int restoreHookId = Core.SM.UI.ElementWdw.CurrentHookId; // // Enter critical section _addMutex.WaitOne(); // // Suspend element changed monitoring inSMAUpdateLockMode = Core.SM.UI.ElementWdw.EnterSMAUpdateLock(); // // Focus // toDispose.Add(new FocusSnapshot(true)); // TODO: Only if inserting 1 element // // Regroup by parent id to optimize remote calls var resultsByParent = results.GroupBy(k => k.Builder.ParentId); // // Freeze element window if we want to insert the element without displaying it immediately if (singleMode == false || builders[0].ShouldDisplay == false) { inSMUpdateLockMode = Core.SM.UI.ElementWdw.EnterSMUpdateLock(); // TODO: Pass in EnterUpdateLock } foreach (var rpGroup in resultsByParent) { using var h = new HookSnapshot(); var parent = rpGroup.Key.HasValue ? this[rpGroup.Key.Value] : this[restoreHookId]; var branchFinder = options.HasFlag(ElemCreationFlags.CreateSubfolders) ? (IDestinationBranchFinder) new SubfolderBranchFinder(parent, options) : (IDestinationBranchFinder) new ConstantBranchFinder(parent); await AddInternalAsync(rpGroup.ToList(), branchFinder).ConfigureAwait(false); } // // Display original element, and unfreeze window -- or simply resume element changed monitoring if (inSMUpdateLockMode) { inSMUpdateLockMode = Core.SM.UI.ElementWdw.QuitSMUpdateLock() == false; Core.SM.UI.ElementWdw.GoToElement(restoreElementId); } inSMAUpdateLockMode = Core.SM.UI.ElementWdw.QuitSMAUpdateLock(inSMUpdateLockMode); return(results); } catch (Exception ex) { LogTo.Error(ex, "An exception was thrown while creating a new element in SM."); return(results); } finally { // // Unlock SM if necessary if (inSMUpdateLockMode) { try { Core.SM.UI.ElementWdw.QuitSMUpdateLock(); } catch (Exception ex) { LogTo.Warning(ex, "Failed to exit SM Update Lock."); MessageBox.Show($@"Failed to exit SuperMemo UI update lock. You might have to restart SuperMemo. Exception: {ex}", "Critical error"); } } // // Unlock element changed monitoring if necessary if (inSMAUpdateLockMode) { Core.SM.UI.ElementWdw.QuitSMAUpdateLock(); } // // Exit Critical section _addMutex.ReleaseMutex(); } }