private static void AddSpecificCustomCharacterSetting(string strSettingName)
        {
            if (_intDicLoadedCharacterSettingsLoadedStatus <= 1)
            {
                return;
            }

            CharacterSettings objNewCharacterSettings = new CharacterSettings();

            if (!objNewCharacterSettings.Load(strSettingName, false) ||
                (objNewCharacterSettings.BuildMethodIsLifeModule &&
                 !GlobalSettings.LifeModuleEnabled))
            {
                objNewCharacterSettings.Dispose();
                return;
            }

            while (true)
            {
                if (s_DicLoadedCharacterSettings.TryAdd(objNewCharacterSettings.DictionaryKey,
                                                        objNewCharacterSettings))
                {
                    return;
                }
                // We somehow already have a setting loaded with this name, so just copy over the values and dispose of the new setting instead
                if (s_DicLoadedCharacterSettings.TryGetValue(objNewCharacterSettings.DictionaryKey,
                                                             out CharacterSettings objOldCharacterSettings))
                {
                    objOldCharacterSettings.CopyValues(objNewCharacterSettings);
                    objNewCharacterSettings.Dispose();
                    return;
                }
            }
        }
 /// <summary>
 /// Use in place of CollectionChanged Adder
 /// </summary>
 /// <param name="objTag">Tag to associate with added delegate</param>
 /// <param name="funcDelegateToAdd">Delegate to add to CollectionChanged</param>
 /// <returns>True if delegate was successfully added, false if a delegate already exists with the associated tag.</returns>
 public bool AddTaggedCollectionChanged(object objTag, NotifyCollectionChangedEventHandler funcDelegateToAdd)
 {
     if (!_dicTaggedAddedDelegates.TryGetValue(objTag, out HashSet <NotifyCollectionChangedEventHandler> setFuncs))
     {
         setFuncs = new HashSet <NotifyCollectionChangedEventHandler>();
         _dicTaggedAddedDelegates.Add(objTag, setFuncs);
     }
     if (setFuncs.Add(funcDelegateToAdd))
     {
         base.CollectionChanged += funcDelegateToAdd;
         return(true);
     }
     Utils.BreakIfDebug();
     return(false);
 }
Exemple #3
0
        /// <summary>
        /// Get the compiled Xsl Transform of an Xsl file. Will throw exceptions if anything goes awry.
        /// If we've already compiled the same Xsl Transform before, we'll fetch the cached version of that transform instead of repeating it.
        /// </summary>
        /// <param name="strXslFilePath">Absolute path to the Xsl file to be transformed.</param>
        /// <returns>The compiled Xsl transform of <paramref name="strXslFilePath"/>.</returns>
        public static XslCompiledTransform GetTransformForFile(string strXslFilePath)
        {
            if (!File.Exists(strXslFilePath))
            {
                throw new FileNotFoundException(nameof(strXslFilePath));
            }

            DateTime datLastWriteTimeUtc = File.GetLastWriteTimeUtc(strXslFilePath);

            XslCompiledTransform objReturn;

            if (!s_dicCompiledTransforms.TryGetValue(
                    strXslFilePath, out Tuple <DateTime, XslCompiledTransform> tupCachedData) ||
                tupCachedData.Item1 <= datLastWriteTimeUtc)
            {
#if DEBUG
                objReturn = new XslCompiledTransform(true);
#else
                objReturn = new XslCompiledTransform();
#endif
                objReturn.Load(strXslFilePath);

                s_dicCompiledTransforms.Remove(strXslFilePath);
                s_dicCompiledTransforms.TryAdd(
                    strXslFilePath, new Tuple <DateTime, XslCompiledTransform>(datLastWriteTimeUtc, objReturn));
            }
            else
            {
                objReturn = tupCachedData.Item2;
            }

            return(objReturn);
        }
Exemple #4
0
        public static TimeSpan Finish(string taskname)
        {
            TimeSpan final = TimeSpan.Zero;

            if (s_DictionaryStarts.TryRemove(taskname, out TimeSpan objStartTimeSpan))
            {
                final = s_Time.Elapsed - objStartTimeSpan;

#if DEBUG
                string strLogEntry = string.Format(GlobalSettings.InvariantCultureInfo, "Task \"{0}\" finished in {1}",
                                                   taskname, final);
                //Log.Trace(strLogEntry);

                Debug.WriteLine(strLogEntry);
#endif

                if (s_DictionaryStatistics.TryGetValue(taskname, out Tuple <TimeSpan, int> existing))
                {
                    s_DictionaryStatistics[taskname] = new Tuple <TimeSpan, int>(existing.Item1 + final, existing.Item2 + 1);
                }
                else
                {
                    s_DictionaryStatistics.TryAdd(taskname, new Tuple <TimeSpan, int>(final, 1));
                }
            }
            else
            {
                Debug.WriteLine("Non started task \"" + taskname + "\" finished");
            }
            return(final);
        }
Exemple #5
0
        public static TimeSpan Elapsed(string taskname)
        {
            if (s_DictionaryStarts.TryGetValue(taskname, out TimeSpan objStartTimeSpan))
            {
                return(s_Time.Elapsed - objStartTimeSpan);
            }

            return(TimeSpan.Zero);
        }
Exemple #6
0
        /// <summary>
        /// Get the compiled Xsl Transform of an Xsl file. Will throw exceptions if anything goes awry.
        /// If we've already compiled the same Xsl Transform before, we'll fetch the cached version of that transform instead of repeating it.
        /// Uses flag hack method design outlined here to avoid locking:
        /// https://docs.microsoft.com/en-us/archive/msdn-magazine/2015/july/async-programming-brownfield-async-development
        /// </summary>
        /// <param name="blnSync">Flag for whether method should always use synchronous code or not.</param>
        /// <param name="strXslFilePath">Absolute path to the Xsl file to be transformed.</param>
        /// <returns>The compiled Xsl transform of <paramref name="strXslFilePath"/>.</returns>
        private static async Task <XslCompiledTransform> GetTransformForFileCoreAsync(bool blnSync, string strXslFilePath)
        {
            if (!File.Exists(strXslFilePath))
            {
                throw new FileNotFoundException(nameof(strXslFilePath));
            }

            DateTime datLastWriteTimeUtc = File.GetLastWriteTimeUtc(strXslFilePath);

            XslCompiledTransform objReturn;
            bool blnSuccess;
            Tuple <DateTime, XslCompiledTransform> tupCachedData;

            if (blnSync)
            {
                // ReSharper disable once MethodHasAsyncOverload
                blnSuccess = s_dicCompiledTransforms.TryGetValue(strXslFilePath, out tupCachedData);
            }
            else
            {
                (blnSuccess, tupCachedData) = await s_dicCompiledTransforms.TryGetValueAsync(strXslFilePath);
            }

            if (!blnSuccess || tupCachedData.Item1 <= datLastWriteTimeUtc)
            {
#if DEBUG
                objReturn = new XslCompiledTransform(true);
#else
                objReturn = new XslCompiledTransform();
#endif
                if (blnSync)
                {
                    objReturn.Load(strXslFilePath);
                    // ReSharper disable once MethodHasAsyncOverload
                    s_dicCompiledTransforms.Remove(strXslFilePath);
                    // ReSharper disable once MethodHasAsyncOverload
                    s_dicCompiledTransforms.TryAdd(
                        strXslFilePath, new Tuple <DateTime, XslCompiledTransform>(datLastWriteTimeUtc, objReturn));
                }
                else
                {
                    await Task.Run(() => objReturn.Load(strXslFilePath));

                    await s_dicCompiledTransforms.RemoveAsync(strXslFilePath);

                    await s_dicCompiledTransforms.TryAddAsync(
                        strXslFilePath, new Tuple <DateTime, XslCompiledTransform>(datLastWriteTimeUtc, objReturn));
                }
            }
            else
            {
                objReturn = tupCachedData.Item2;
            }

            return(objReturn);
        }
Exemple #7
0
        private void lstItems_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (_blnSkipRefresh)
            {
                return;
            }
            using (new CursorWait(this))
            {
                if (lstItems.SelectedValue is MasterIndexEntry objEntry)
                {
                    lblSourceLabel.Visible         = true;
                    lblSource.Visible              = true;
                    lblSourceClickReminder.Visible = true;
                    lblSource.Text        = objEntry.DisplaySource.ToString();
                    lblSource.ToolTipText = objEntry.DisplaySource.LanguageBookTooltip;
                    if (!_dicCachedNotes.TryGetValue(objEntry, out string strNotes))
                    {
                        strNotes = CommonFunctions.GetTextFromPdf(objEntry.Source.ToString(), objEntry.EnglishNameOnPage);

                        if (string.IsNullOrEmpty(strNotes) &&
                            !GlobalSettings.Language.Equals(GlobalSettings.DefaultLanguage, StringComparison.OrdinalIgnoreCase) &&
                            (objEntry.TranslatedNameOnPage != objEntry.EnglishNameOnPage ||
                             objEntry.Source.Page != objEntry.DisplaySource.Page))
                        {
                            // don't check again it is not translated
                            strNotes = CommonFunctions.GetTextFromPdf(objEntry.DisplaySource.ToString(), objEntry.TranslatedNameOnPage);
                        }

                        _dicCachedNotes.TryAdd(objEntry, strNotes);
                    }

                    txtNotes.Text    = strNotes;
                    txtNotes.Visible = true;
                }
                else
                {
                    lblSourceLabel.Visible         = false;
                    lblSource.Visible              = false;
                    lblSourceClickReminder.Visible = false;
                    txtNotes.Visible = false;
                }
            }
        }
Exemple #8
0
        public CursorWait(Control objControl = null, bool blnAppStarting = false)
        {
            if (objControl.IsNullOrDisposed())
            {
                _objControl = null;
                lock (s_ObjApplicationWaitCursorsLock)
                {
                    ++_intApplicationWaitCursors;
                    if (_intApplicationWaitCursors > 0)
                    {
                        Application.UseWaitCursor = true;
                    }
                }
                return;
            }
            _objTimer.Start();
            Log.Trace("CursorWait for Control \"" + objControl + "\" started with Guid \"" + _guidInstance + "\".");
            _objControl = objControl;
            Form frmControl = _objControl as Form;

            CursorToUse = blnAppStarting ? Cursors.AppStarting : Cursors.WaitCursor;
            if (frmControl?.IsMdiChild != false)
            {
                if (frmControl != null)
                {
                    _frmControlTopParent = frmControl.MdiParent;
                }
                else if (_objControl is UserControl objUserControl)
                {
                    _frmControlTopParent = objUserControl.ParentForm;
                }
                else
                {
                    for (Control objLoop = _objControl?.Parent; objLoop != null; objLoop = objLoop.Parent)
                    {
                        if (objLoop is Form objLoopForm)
                        {
                            _frmControlTopParent = objLoopForm;
                            break;
                        }
                    }
                }
            }
            ThreadSafeList <CursorWait> lstNew = new ThreadSafeList <CursorWait>(1);

            while (_objControl != null && !s_DicWaitingControls.TryAdd(_objControl, lstNew))
            {
                if (!s_DicWaitingControls.TryGetValue(_objControl, out ThreadSafeList <CursorWait> lstExisting))
                {
                    continue;
                }
                lstNew.Dispose();
                CursorWait objLastCursorWait = null;
                // Need this pattern because the size of lstExisting might change in between fetching lstExisting.Count and lstExisting[]
                bool blnDoLoop = true;
                while (blnDoLoop)
                {
                    blnDoLoop = false;
                    int intIndex = lstExisting.Count - 1;
                    if (intIndex >= 0)
                    {
                        try
                        {
                            objLastCursorWait = lstExisting[intIndex];
                        }
                        catch (ArgumentOutOfRangeException)
                        {
                            blnDoLoop = true;
                        }
                    }
                }
                lstExisting.Add(this);
                if (blnAppStarting)
                {
                    if (objLastCursorWait == null)
                    {
                        SetControlCursor(CursorToUse);
                    }
                    else if (objLastCursorWait.CursorToUse == Cursors.WaitCursor)
                    {
                        CursorToUse = Cursors.WaitCursor;
                    }
                }
                else if (objLastCursorWait == null || objLastCursorWait.CursorToUse == Cursors.AppStarting)
                {
                    SetControlCursor(CursorToUse);
                }
                return;
            }
            // Here for safety purposes
            if (_objControl.IsNullOrDisposed())
            {
                _objControl          = null;
                _frmControlTopParent = null;
                lock (s_ObjApplicationWaitCursorsLock)
                {
                    ++_intApplicationWaitCursors;
                    if (_intApplicationWaitCursors > 0)
                    {
                        Application.UseWaitCursor = true;
                    }
                }
                return;
            }
            lstNew.Add(this);
            SetControlCursor(CursorToUse);
        }
Exemple #9
0
        private async ValueTask DoXsltUpdate()
        {
            if (!_blnLoading)
            {
                if (_objCharacterXml != null)
                {
                    _strXslt = cboXSLT.Text;
                    if (!string.IsNullOrEmpty(_strXslt))
                    {
                        using (new CursorWait(this))
                        {
                            await txtText.DoThreadSafeAsync(
                                () => txtText.Text = LanguageManager.GetString("String_Generating_Data"));

                            if (_dicCache.TryGetValue(new Tuple <string, string>(_strExportLanguage, _strXslt),
                                                      out Tuple <string, string> strBoxText))
                            {
                                await txtText.DoThreadSafeAsync(() => txtText.Text = strBoxText.Item2);
                            }
                            else
                            {
                                if (_objXmlGeneratorCancellationTokenSource != null)
                                {
                                    _objXmlGeneratorCancellationTokenSource.Cancel(false);
                                    _objXmlGeneratorCancellationTokenSource.Dispose();
                                }

                                _objXmlGeneratorCancellationTokenSource = new CancellationTokenSource();
                                try
                                {
                                    if (_tskXmlGenerator?.IsCompleted == false)
                                    {
                                        await _tskXmlGenerator;
                                    }
                                }
                                catch (TaskCanceledException)
                                {
                                    // Swallow this
                                }

                                _tskXmlGenerator = _strXslt == "Export JSON"
                                    ? Task.Run(GenerateJson, _objXmlGeneratorCancellationTokenSource.Token)
                                    : Task.Run(GenerateXml, _objXmlGeneratorCancellationTokenSource.Token);
                            }
                        }
                    }
                }
                else
                {
                    if (_objCharacterXmlGeneratorCancellationTokenSource != null)
                    {
                        _objCharacterXmlGeneratorCancellationTokenSource.Cancel(false);
                        _objCharacterXmlGeneratorCancellationTokenSource.Dispose();
                    }

                    _objCharacterXmlGeneratorCancellationTokenSource = new CancellationTokenSource();
                    try
                    {
                        if (_tskCharacterXmlGenerator?.IsCompleted == false)
                        {
                            await _tskCharacterXmlGenerator;
                        }
                    }
                    catch (TaskCanceledException)
                    {
                        // Swallow this
                    }

                    _tskCharacterXmlGenerator
                        = Task.Run(GenerateCharacterXml, _objCharacterXmlGeneratorCancellationTokenSource.Token);
                }
            }
        }
Exemple #10
0
        /// <summary>
        /// Generates a character cache, which prevents us from repeatedly loading XmlNodes or caching a full character.
        /// </summary>
        /// <param name="strFile"></param>
        private TreeNode CacheCharacters(string strFile)
        {
            if (!File.Exists(strFile))
            {
                Program.MainForm.ShowMessageBox(
                    this,
                    string.Format(GlobalSettings.CultureInfo,
                                  LanguageManager.GetString("Message_File_Cannot_Be_Accessed"), strFile));
                return(null);
            }

            using (ThreadSafeList <XPathNavigator> lstCharacterXmlStatblocks = new ThreadSafeList <XPathNavigator>(3))
            {
                try
                {
                    using (ZipArchive zipArchive
                               = ZipFile.Open(strFile, ZipArchiveMode.Read, Encoding.GetEncoding(850)))
                    {
                        Parallel.ForEach(zipArchive.Entries, entry =>
                        {
                            string strEntryFullName = entry.FullName;
                            if (strEntryFullName.EndsWith(".xml", StringComparison.OrdinalIgnoreCase) &&
                                strEntryFullName.StartsWith("statblocks_xml", StringComparison.Ordinal))
                            {
                                // If we run into any problems loading the character cache, fail out early.
                                try
                                {
                                    XPathDocument xmlSourceDoc;
                                    using (StreamReader sr = new StreamReader(entry.Open(), true))
                                        using (XmlReader objXmlReader
                                                   = XmlReader.Create(sr, GlobalSettings.SafeXmlReaderSettings))
                                            xmlSourceDoc = new XPathDocument(objXmlReader);
                                    XPathNavigator objToAdd = xmlSourceDoc.CreateNavigator();
                                    // ReSharper disable once AccessToDisposedClosure
                                    lstCharacterXmlStatblocks.Add(objToAdd);
                                }
                                // If we run into any problems loading the character cache, fail out early.
                                catch (IOException)
                                {
                                    Utils.BreakIfDebug();
                                }
                                catch (XmlException)
                                {
                                    Utils.BreakIfDebug();
                                }
                            }
                            else if (strEntryFullName.StartsWith("images", StringComparison.Ordinal) &&
                                     strEntryFullName.Contains('.'))
                            {
                                string strKey = Path.GetFileName(strEntryFullName);
                                using (Bitmap bmpMugshot = new Bitmap(entry.Open(), true))
                                {
                                    Bitmap bmpNewMugshot = bmpMugshot.PixelFormat == PixelFormat.Format32bppPArgb
                                        ? bmpMugshot.Clone() as Bitmap // Clone makes sure file handle is closed
                                        : bmpMugshot.ConvertPixelFormat(PixelFormat.Format32bppPArgb);
                                    while (!_dicImages.TryAdd(strKey, bmpNewMugshot))
                                    {
                                        if (_dicImages.TryRemove(strKey, out Bitmap bmpOldMugshot))
                                        {
                                            bmpOldMugshot?.Dispose();
                                        }
                                    }
                                }
                            }
                        });
                    }
                }
                catch (IOException)
                {
                    Program.MainForm.ShowMessageBox(
                        this,
                        string.Format(GlobalSettings.CultureInfo,
                                      LanguageManager.GetString("Message_File_Cannot_Be_Accessed"), strFile));
                    return(null);
                }
                catch (NotSupportedException)
                {
                    Program.MainForm.ShowMessageBox(
                        this,
                        string.Format(GlobalSettings.CultureInfo,
                                      LanguageManager.GetString("Message_File_Cannot_Be_Accessed"), strFile));
                    return(null);
                }
                catch (UnauthorizedAccessException)
                {
                    Program.MainForm.ShowMessageBox(
                        this, LanguageManager.GetString("Message_Insufficient_Permissions_Warning"));
                    return(null);
                }

                string strFileText
                    = strFile.CheapReplace(Utils.GetStartupPath, () => '<' + Application.ProductName + '>');
                TreeNode nodRootNode = new TreeNode
                {
                    Text        = strFileText,
                    ToolTipText = strFileText
                };

                XPathNavigator xmlMetatypesDocument = XmlManager.LoadXPath("metatypes.xml");
                foreach (XPathNavigator xmlCharacterDocument in lstCharacterXmlStatblocks)
                {
                    XPathNavigator xmlBaseCharacterNode
                        = xmlCharacterDocument.SelectSingleNode("/document/public/character");
                    if (xmlBaseCharacterNode != null)
                    {
                        HeroLabCharacterCache objCache = new HeroLabCharacterCache
                        {
                            PlayerName = xmlBaseCharacterNode.SelectSingleNode("@playername")?.Value ?? string.Empty
                        };
                        string strNameString = xmlBaseCharacterNode.SelectSingleNode("@name")?.Value ?? string.Empty;
                        objCache.CharacterId = strNameString;
                        if (!string.IsNullOrEmpty(strNameString))
                        {
                            int intAsIndex = strNameString.IndexOf(" as ", StringComparison.Ordinal);
                            if (intAsIndex != -1)
                            {
                                objCache.CharacterName = strNameString.Substring(0, intAsIndex);
                                objCache.CharacterAlias
                                    = strNameString.Substring(intAsIndex).TrimStart(" as ").Trim('\'');
                            }
                            else
                            {
                                objCache.CharacterName = strNameString;
                            }
                        }

                        string strRaceString = xmlBaseCharacterNode.SelectSingleNode("race/@name")?.Value;
                        if (strRaceString == "Metasapient")
                        {
                            strRaceString = "A.I.";
                        }
                        if (!string.IsNullOrEmpty(strRaceString))
                        {
                            foreach (XPathNavigator xmlMetatype in xmlMetatypesDocument.Select(
                                         "/chummer/metatypes/metatype"))
                            {
                                string strMetatypeName = xmlMetatype.SelectSingleNode("name")?.Value ?? string.Empty;
                                if (strMetatypeName == strRaceString)
                                {
                                    objCache.Metatype    = strMetatypeName;
                                    objCache.Metavariant = "None";
                                    break;
                                }

                                foreach (XPathNavigator xmlMetavariant in
                                         xmlMetatype.SelectAndCacheExpression("metavariants/metavariant"))
                                {
                                    string strMetavariantName
                                        = xmlMetavariant.SelectSingleNode("name")?.Value ?? string.Empty;
                                    if (strMetavariantName == strRaceString)
                                    {
                                        objCache.Metatype    = strMetatypeName;
                                        objCache.Metavariant = strMetavariantName;
                                        break;
                                    }
                                }
                            }
                        }

                        objCache.Description = xmlBaseCharacterNode.SelectSingleNode("personal/description")?.Value;
                        objCache.Karma       = xmlBaseCharacterNode.SelectSingleNode("karma/@total")?.Value ?? "0";
                        objCache.Essence     = xmlBaseCharacterNode
                                               .SelectSingleNode("attributes/attribute[@name = \"Essence\"]/@text")?.Value;
                        objCache.BuildMethod
                            = xmlBaseCharacterNode.SelectSingleNode("creation/bp/@total")?.Value == "25"
                                ? nameof(CharacterBuildMethod.Priority)
                                : nameof(CharacterBuildMethod.Karma);

                        objCache.Created = objCache.Karma != "0";
                        if (!objCache.Created)
                        {
                            XPathNodeIterator xmlJournalEntries = xmlBaseCharacterNode.SelectAndCacheExpression("journals/journal");
                            if (xmlJournalEntries?.Count > 1)
                            {
                                objCache.Created = true;
                            }
                            else if (xmlJournalEntries?.Count == 1 &&
                                     xmlJournalEntries.Current?.SelectSingleNode("@name")?.Value != "Title")
                            {
                                objCache.Created = true;
                            }
                        }

                        string strImageString = xmlBaseCharacterNode.SelectSingleNode("images/image/@filename")?.Value;
                        if (!string.IsNullOrEmpty(strImageString) &&
                            _dicImages.TryGetValue(strImageString, out Bitmap objTemp))
                        {
                            objCache.Mugshot = objTemp;
                        }

                        objCache.FilePath = strFile;
                        TreeNode objNode = new TreeNode
                        {
                            Text        = CalculatedName(objCache),
                            ToolTipText = strFile.CheapReplace(Utils.GetStartupPath,
                                                               () => '<' + Application.ProductName + '>')
                        };
                        nodRootNode.Nodes.Add(objNode);

                        _lstCharacterCache.Add(objCache);
                        objNode.Tag = _lstCharacterCache.IndexOf(objCache);
                    }
                }

                nodRootNode.Expand();
                return(nodRootNode);
            }
        }