예제 #1
0
 /// <summary>
 /// Internal constructor.
 /// </summary>
 /// <param name="ccpCharacter">The CCP character.</param>
 internal EveMailMessageCollection(CCPCharacter ccpCharacter)
 {
     m_ccpCharacter = ccpCharacter;
 }
예제 #2
0
 /// <summary>
 /// Internal constructor.
 /// </summary>
 /// <param name="character">The character.</param>
 internal MarketOrderCollection(CCPCharacter character)
 {
     m_character = character;
 }
예제 #3
0
        /// <summary>
        /// Initializes a new instance of the <see cref="CharacterDataQuerying"/> class.
        /// </summary>
        /// <param name="ccpCharacter">The CCP character.</param>
        internal CharacterDataQuerying(CCPCharacter ccpCharacter)
        {
            var notifiers = EveMonClient.Notifications;

            m_ccpCharacter           = ccpCharacter;
            m_characterQueryMonitors = new List <IQueryMonitorEx>();

            // Add the monitors in an order as they will appear in the throbber menu
            m_charSheetMonitor = new CharacterQueryMonitor <EsiAPICharacterSheet>(ccpCharacter,
                                                                                  ESIAPICharacterMethods.CharacterSheet, OnCharacterSheetUpdated,
                                                                                  notifiers.NotifyCharacterSheetError);
            m_characterQueryMonitors.Add(m_charSheetMonitor);
            m_characterQueryMonitors.Add(new CharacterQueryMonitor <EsiAPISkillQueue>(
                                             ccpCharacter, ESIAPICharacterMethods.SkillQueue, OnSkillQueueUpdated,
                                             notifiers.NotifySkillQueueError));
            m_characterQueryMonitors.Add(new CharacterQueryMonitor <EsiAPIStandings>(
                                             ccpCharacter, ESIAPICharacterMethods.Standings, OnStandingsUpdated,
                                             notifiers.NotifyCharacterStandingsError)
            {
                QueryOnStartup = true
            });
            m_characterQueryMonitors.Add(new CharacterQueryMonitor <EsiAPIContactsList>(
                                             ccpCharacter, ESIAPICharacterMethods.ContactList, OnContactsUpdated,
                                             notifiers.NotifyCharacterContactsError)
            {
                QueryOnStartup = true
            });
            m_characterQueryMonitors.Add(new CharacterQueryMonitor <EsiAPIFactionalWarfareStats>(
                                             ccpCharacter, ESIAPICharacterMethods.FactionalWarfareStats,
                                             OnFactionalWarfareStatsUpdated, notifiers.
                                             NotifyCharacterFactionalWarfareStatsError)
            {
                QueryOnStartup = true
            });
            m_characterQueryMonitors.Add(new CharacterQueryMonitor <EsiAPIMedals>(ccpCharacter,
                                                                                  ESIAPICharacterMethods.Medals, OnMedalsUpdated,
                                                                                  notifiers.NotifyCharacterMedalsError)
            {
                QueryOnStartup = true
            });
            m_characterQueryMonitors.Add(new CharacterQueryMonitor <EsiAPIKillLog>(ccpCharacter,
                                                                                   ESIAPICharacterMethods.KillLog, OnKillLogUpdated,
                                                                                   notifiers.NotifyCharacterKillLogError)
            {
                QueryOnStartup = true
            });
            m_characterQueryMonitors.Add(new CharacterQueryMonitor <EsiAPIAssetList>(ccpCharacter,
                                                                                     ESIAPICharacterMethods.AssetList, OnAssetsUpdated,
                                                                                     notifiers.NotifyCharacterAssetsError)
            {
                QueryOnStartup = true
            });
            m_charMarketOrdersMonitor = new CharacterQueryMonitor <EsiAPIMarketOrders>(
                ccpCharacter, ESIAPICharacterMethods.MarketOrders, OnMarketOrdersUpdated,
                notifiers.NotifyCharacterMarketOrdersError)
            {
                QueryOnStartup = true
            };
            m_characterQueryMonitors.Add(m_charMarketOrdersMonitor);
            m_charContractsMonitor = new CharacterQueryMonitor <EsiAPIContracts>(ccpCharacter,
                                                                                 ESIAPICharacterMethods.Contracts, OnContractsUpdated,
                                                                                 notifiers.NotifyCharacterContractsError)
            {
                QueryOnStartup = true
            };
            m_characterQueryMonitors.Add(m_charContractsMonitor);
            m_characterQueryMonitors.Add(new CharacterQueryMonitor <EsiAPIWalletJournal>(
                                             ccpCharacter, ESIAPICharacterMethods.WalletJournal, OnWalletJournalUpdated,
                                             notifiers.NotifyCharacterWalletJournalError)
            {
                QueryOnStartup = true
            });
            m_characterQueryMonitors.Add(new CharacterQueryMonitor <EsiAPIWalletTransactions>(
                                             ccpCharacter, ESIAPICharacterMethods.WalletTransactions,
                                             OnWalletTransactionsUpdated, notifiers.NotifyCharacterWalletTransactionsError)
            {
                QueryOnStartup = true
            });
            m_charIndustryJobsMonitor = new CharacterQueryMonitor <EsiAPIIndustryJobs>(
                ccpCharacter, ESIAPICharacterMethods.IndustryJobs, OnIndustryJobsUpdated,
                notifiers.NotifyCharacterIndustryJobsError)
            {
                QueryOnStartup = true
            };
            m_characterQueryMonitors.Add(m_charIndustryJobsMonitor);
            m_characterQueryMonitors.Add(new CharacterQueryMonitor <EsiAPIResearchPoints>(
                                             ccpCharacter, ESIAPICharacterMethods.ResearchPoints, OnResearchPointsUpdated,
                                             notifiers.NotifyCharacterResearchPointsError)
            {
                QueryOnStartup = true
            });
            m_characterQueryMonitors.Add(new CharacterQueryMonitor <EsiAPIMailMessages>(
                                             ccpCharacter, ESIAPICharacterMethods.MailMessages, OnEVEMailMessagesUpdated,
                                             notifiers.NotifyEVEMailMessagesError)
            {
                QueryOnStartup = true
            });
            m_characterQueryMonitors.Add(new CharacterQueryMonitor <EsiAPINotifications>(
                                             ccpCharacter, ESIAPICharacterMethods.Notifications, OnEVENotificationsUpdated,
                                             notifiers.NotifyEVENotificationsError)
            {
                QueryOnStartup = true
            });
            m_characterQueryMonitors.Add(new CharacterQueryMonitor <EsiAPICalendarEvents>(
                                             ccpCharacter, ESIAPICharacterMethods.UpcomingCalendarEvents,
                                             OnUpcomingCalendarEventsUpdated, notifiers.
                                             NotifyCharacterUpcomingCalendarEventsError)
            {
                QueryOnStartup = true
            });
            m_characterQueryMonitors.Add(new CharacterQueryMonitor <EsiAPIPlanetaryColoniesList>(
                                             ccpCharacter, ESIAPICharacterMethods.PlanetaryColonies,
                                             OnPlanetaryColoniesUpdated, notifiers.
                                             NotifyCharacterPlanetaryColoniesError)
            {
                QueryOnStartup = true
            });
            m_characterQueryMonitors.ForEach(monitor => ccpCharacter.QueryMonitors.Add(monitor));

            // Enumerate the basic feature monitors into a separate list
            m_basicFeaturesMonitors = new List <IQueryMonitorEx>(m_characterQueryMonitors.Count);
            long basicFeatures = (long)CCPAPIMethodsEnum.BasicCharacterFeatures;

            foreach (var monitor in m_characterQueryMonitors)
            {
                long method = (long)(ESIAPICharacterMethods)monitor.Method;
                if (method == (method & basicFeatures))
                {
                    m_basicFeaturesMonitors.Add(monitor);
                    // If force update is selected, update basic features only
                    if (ccpCharacter.ForceUpdateBasicFeatures)
                    {
                        monitor.ForceUpdate(true);
                    }
                }
            }

            EveMonClient.TimerTick += EveMonClient_TimerTick;
        }
예제 #4
0
 /// <summary>
 /// Internal constructor.
 /// </summary>
 /// <param name="character">The character.</param>
 internal LoyaltyCollection(CCPCharacter character)
 {
     m_character = character;
 }
예제 #5
0
 /// <summary>
 /// Internal constructor.
 /// </summary>
 /// <param name="character">The character.</param>
 internal AssetCollection(CCPCharacter character)
 {
     m_character = character;
 }
예제 #6
0
 /// <summary>
 /// Internal constructor.
 /// </summary>
 /// <param name="character">The character.</param>
 internal UpcomingCalendarEventCollection(CCPCharacter character)
 {
     m_character    = character;
     m_eventCounter = 0;
     m_counterLock  = new object();
 }
예제 #7
0
        /// <summary>
        /// Draws the texts.
        /// </summary>
        /// <param name="top">The top.</param>
        /// <param name="g">The g.</param>
        /// <param name="esiKey">The ESI key.</param>
        /// <param name="left">The left.</param>
        /// <param name="fontBrush">The font brush.</param>
        /// <param name="icon">The icon.</param>
        private void DrawTexts(Graphics g, ESIKey esiKey, int left, int top, Brush fontBrush, Image icon)
        {
            // Draws the texts on the upper third
            left += icon.Width + Margin.Left;

            // Api key ID
            string apiKeyId = esiKey.ID.ToString(CultureConstants.InvariantCulture);

            g.DrawString(apiKeyId, m_boldFont, fontBrush, new Point(left, top + 2));
            int indentedLeft = left + g.MeasureString(apiKeyId, m_boldFont).ToSize().Width + Margin.Left * 2;

            // Api key verification code
            string tokenText = string.IsNullOrEmpty(esiKey.AccessToken) ? "No access token" : "Access token present";

            g.DrawString(tokenText, Font, fontBrush, new Point(indentedLeft, top));
            indentedLeft += g.MeasureString(esiKey.AccessToken, Font).ToSize().Width + Margin.Left * 2;

            // Draw the texts on the middle third
            top += g.MeasureString(apiKeyId, Font).ToSize().Height;

#if false
            // Account header
            string accountHeader = "Account";
            g.DrawString(accountHeader, m_boldFont, fontBrush, new Point(left, top));
            indentedLeft = left + g.MeasureString(accountHeader, m_boldFont).ToSize().Width + Margin.Left * 2;

            // Account created
            string accountCreatedText = esiKey.AccountCreated != DateTime.MinValue
                ? esiKey.AccountCreated.ToLocalTime().ToString(CultureConstants.DefaultCulture)
                : "-";
            string accountCreated = $"Created: {accountCreatedText}";

            g.DrawString(accountCreated, m_middleFont, fontBrush, new Point(indentedLeft, top));
            indentedLeft += g.MeasureString(accountCreated, m_middleFont).ToSize().Width + Margin.Left * 2;

            // Account paid until
            string accountPaidUntilText = esiKey.AccountExpires != DateTime.MinValue
                ? esiKey.AccountExpires.ToLocalTime().ToString(CultureConstants.DefaultCulture)
                : "-";
            string accountPaidUntil = $"Paid Until: {accountPaidUntilText}";
            g.DrawString(accountPaidUntil, m_middleFont, fontBrush, new Point(indentedLeft, top));
            indentedLeft += g.MeasureString(accountPaidUntil, m_middleFont).ToSize().Width + Margin.Left * 2;

            // Account status header
            string accountStatusHeader = "Status: ";
            g.DrawString(accountStatusHeader, m_middleFont, fontBrush, new Point(indentedLeft, top));
            indentedLeft += g.MeasureString(accountStatusHeader, m_middleFont).ToSize().Width;

            // Account status body
            string accountStatusBody = esiKey.AccountExpires != DateTime.MinValue
                ? esiKey.AccountExpires > DateTime.UtcNow
                    ? "Active"
                    : "Expired"
                : "-";
            Brush accountStatusBrush = esiKey.AccountExpires != DateTime.MinValue
                ? new SolidBrush(esiKey.AccountExpires > DateTime.UtcNow ? Color.DarkGreen : Color.Red)
                : fontBrush;
            g.DrawString(accountStatusBody, m_middleFont, accountStatusBrush, new Point(indentedLeft, top));

            // Draws the texts on the lower third
            top += g.MeasureString(accountCreated, m_middleFont).ToSize().Height;
#endif
            bool isFirst = true;

            foreach (CharacterIdentity identity in esiKey.CharacterIdentities)
            {
                // Draws "; " between ids
                if (!isFirst)
                {
                    g.DrawString("; ", m_smallFont, fontBrush, new Point(left, top));
                    left += g.MeasureString("; ", Font).ToSize().Width;
                }
                isFirst = false;

                // Selects font
                Font         font         = m_smallFont;
                CCPCharacter ccpCharacter = identity.CCPCharacter;
                if (ccpCharacter != null && ccpCharacter.Monitored)
                {
                    font = m_smallBoldFont;
                }

                // Draws character's name
                g.DrawString(identity.CharacterName, font, fontBrush, new Point(left, top));
                left += g.MeasureString(identity.CharacterName, font).ToSize().Width;
            }
        }
예제 #8
0
 /// <summary>
 /// Internal constructor.
 /// </summary>
 /// <param name="character">The character.</param>
 internal UpcomingCalendarEventCollection(CCPCharacter character)
 {
     m_character = character;
 }
예제 #9
0
 /// <summary>
 /// Internal constructor.
 /// </summary>
 /// <param name="ccpCharacter">The CCP character.</param>
 internal EveMailingListCollection(CCPCharacter ccpCharacter)
 {
     m_ccpCharacter = ccpCharacter;
 }
 /// <summary>
 /// Internal constructor.
 /// </summary>
 /// <param name="character">The character.</param>
 internal WalletTransactionsCollection(CCPCharacter character)
 {
     m_character = character;
 }
예제 #11
0
 /// <summary>
 /// Internal constructor.
 /// </summary>
 /// <param name="ccpCharacter">The CCP character.</param>
 internal KillLogCollection(CCPCharacter ccpCharacter)
 {
     m_ccpCharacter    = ccpCharacter;
     m_killMailCounter = 0;
     m_counterLock     = new object();
 }
예제 #12
0
 /// <summary>
 /// Initializes a new instance of the <see cref="WalletJournalChartWindow"/> class.
 /// </summary>
 /// <param name="ccpCharacter">The CCP character.</param>
 public WalletJournalChartWindow(CCPCharacter ccpCharacter)
     : this()
 {
     m_ccpCharacter = ccpCharacter;
 }
예제 #13
0
 /// <summary>
 /// Internal constructor.
 /// </summary>
 /// <param name="character">The character.</param>
 internal WalletJournalCollection(CCPCharacter character)
 {
     m_character = character;
 }
예제 #14
0
 /// <summary>
 /// On skill completion, switch to the display of the proper message.
 /// </summary>
 internal void SkillCompleted(Character character, int skillCount)
 {
     CurrentCharacter = character as CCPCharacter;
     m_completedSkills = skillCount;
     SwitchState(LcdState.SkillComplete);
 }
예제 #15
0
 /// <summary>
 /// On skill completion, switch to the display of the proper message.
 /// </summary>
 internal void SkillCompleted(Character character, int skillCount)
 {
     CurrentCharacter  = character as CCPCharacter;
     m_completedSkills = skillCount;
     SwitchState(LcdState.SkillComplete);
 }
예제 #16
0
 /// <summary>
 /// Constructor.
 /// </summary>
 /// <param name="character">The character to monitor.</param>
 /// <param name="method">The method to use.</param>
 /// <param name="onSuccess">The callback to use on success or failure.</param>
 internal CCPQueryMonitorBase(CCPCharacter character, Enum method,
                              Action <EsiResult <T> > callback) : base(method, callback)
 {
     m_character = character;
 }
예제 #17
0
        /// <summary>
        /// Moves the selection to the next character.
        /// </summary>
        private void MoveToNextChar()
        {
            if (!MonitoredCharacters.Any())
                return;

            // Move to next char
            int index = MonitoredCharacters.IndexOf(CurrentCharacter);
            if (++index >= MonitoredCharacters.Count())
                index = 0;

            CurrentCharacter = MonitoredCharacters.ElementAt(index);

            // Requests new data
            CurrentCharacterChanged?.ThreadSafeInvoke(this, new CharacterChangedEventArgs(CurrentCharacter));
        }
예제 #18
0
        /// <summary>
        /// Draws the texts.
        /// </summary>
        /// <param name="top">The top.</param>
        /// <param name="g">The g.</param>
        /// <param name="apiKey">The API key.</param>
        /// <param name="left">The left.</param>
        /// <param name="fontBrush">The font brush.</param>
        /// <param name="icon">The icon.</param>
        private void DrawTexts(Graphics g, APIKey apiKey, int left, int top, Brush fontBrush, Image icon)
        {
            // Draws the texts on the upper third
            left += icon.Width + Margin.Left;

            // Api key ID
            string apiKeyId = apiKey.ID.ToString(CultureConstants.InvariantCulture);

            g.DrawString(apiKeyId, m_boldFont, fontBrush, new Point(left, top + 2));
            int indentedLeft = left + g.MeasureString(apiKeyId, m_boldFont).ToSize().Width + Margin.Left * 2;

            // Api key verification code
            g.DrawString(apiKey.VerificationCode, Font, fontBrush, new Point(indentedLeft, top));
            indentedLeft += g.MeasureString(apiKey.VerificationCode, Font).ToSize().Width + Margin.Left * 2;

            // Api key expiration date
            string expirationDateText = apiKey.Expiration != DateTime.MinValue
                ? apiKey.Expiration.ToLocalTime().ToString(CultureConstants.DefaultCulture)
                : "Never";
            string apiKeyExpiration = $"Expires: {expirationDateText}";

            g.DrawString(apiKeyExpiration, Font, fontBrush, new Point(indentedLeft, top));

            // Draw the texts on the middle third
            top += g.MeasureString(apiKeyExpiration, Font).ToSize().Height;

            // Account header
            string accountHeader = "Account";

            g.DrawString(accountHeader, m_boldFont, fontBrush, new Point(left, top));
            indentedLeft = left + g.MeasureString(accountHeader, m_boldFont).ToSize().Width + Margin.Left * 2;

            // Account created
            string accountCreatedText = apiKey.AccountCreated != DateTime.MinValue
                ? apiKey.AccountCreated.ToLocalTime().ToString(CultureConstants.DefaultCulture)
                : "-";
            string accountCreated = $"Created: {accountCreatedText}";

            g.DrawString(accountCreated, m_middleFont, fontBrush, new Point(indentedLeft, top));
            indentedLeft += g.MeasureString(accountCreated, m_middleFont).ToSize().Width + Margin.Left * 2;

            // Account paid until
            string accountPaidUntilText = apiKey.AccountExpires != DateTime.MinValue
                ? apiKey.AccountExpires.ToLocalTime().ToString(CultureConstants.DefaultCulture)
                : "-";
            string accountPaidUntil = $"Paid Until: {accountPaidUntilText}";

            g.DrawString(accountPaidUntil, m_middleFont, fontBrush, new Point(indentedLeft, top));
            indentedLeft += g.MeasureString(accountPaidUntil, m_middleFont).ToSize().Width + Margin.Left * 2;

            // Account status header
            string accountStatusHeader = "Status: ";

            g.DrawString(accountStatusHeader, m_middleFont, fontBrush, new Point(indentedLeft, top));
            indentedLeft += g.MeasureString(accountStatusHeader, m_middleFont).ToSize().Width;

            // Account status body
            string accountStatusBody = apiKey.AccountExpires != DateTime.MinValue
                ? apiKey.AccountExpires > DateTime.UtcNow
                    ? "Active"
                    : "Expired"
                : "-";
            Brush accountStatusBrush = apiKey.AccountExpires != DateTime.MinValue
                ? new SolidBrush(apiKey.AccountExpires > DateTime.UtcNow ? Color.DarkGreen : Color.Red)
                : fontBrush;

            g.DrawString(accountStatusBody, m_middleFont, accountStatusBrush, new Point(indentedLeft, top));

            // Draws the texts on the lower third
            top += g.MeasureString(accountCreated, m_middleFont).ToSize().Height;
            bool isFirst = true;

            foreach (CharacterIdentity identity in apiKey.CharacterIdentities)
            {
                // Draws "; " between ids
                if (!isFirst)
                {
                    g.DrawString("; ", m_smallFont, fontBrush, new Point(left, top));
                    left += g.MeasureString("; ", Font).ToSize().Width;
                }
                isFirst = false;

                // Selects font
                Font         font         = m_smallFont;
                CCPCharacter ccpCharacter = identity.CCPCharacter;
                if (apiKey.IdentityIgnoreList.Contains(identity))
                {
                    font = m_strikeoutFont;
                }
                else if (ccpCharacter != null && ccpCharacter.Monitored)
                {
                    font = m_smallBoldFont;
                }

                // Draws character's name
                g.DrawString(identity.CharacterName, font, fontBrush, new Point(left, top));
                left += g.MeasureString(identity.CharacterName, font).ToSize().Width;
            }
        }
예제 #19
0
 /// <summary>
 /// Internal constructor.
 /// </summary>
 /// <param name="ccpCharacter">The CCP character.</param>
 internal EveNotificationCollection(CCPCharacter ccpCharacter)
 {
     m_ccpCharacter = ccpCharacter;
 }
예제 #20
0
        /// <summary>
        /// Update the controls.
        /// </summary>
        private void UpdateContent()
        {
            if (!Visible)
            {
                return;
            }

            // Update character's 'Adorned Name' and 'Portrait' in case they have changed
            lblCharName.Text = Character.AdornedName;
            pbCharacterPortrait.Character = Character;
            lblTotalSkillPoints.Text      = $@"{Character.SkillPoints:N0} SP";

            FormatBalance();

            CCPCharacter ccpCharacter = Character as CCPCharacter;

            // Character in training ? We have labels to fill
            if (Character.IsTraining || (ccpCharacter != null && ccpCharacter.SkillQueue.IsPaused))
            {
                // Update the skill in training label
                QueuedSkill trainingSkill = Character.CurrentlyTrainingSkill;
                lblSkillInTraining.Text = trainingSkill.ToString();
                DateTime endTime = trainingSkill.EndTime.ToLocalTime();

                // Updates the time remaining label
                lblRemainingTime.Text = ccpCharacter != null && ccpCharacter.SkillQueue.IsPaused
                    ? "Paused"
                    : trainingSkill.RemainingTime.ToDescriptiveText(DescriptiveTextOptions.IncludeCommas);

                // Update the completion time
                lblCompletionTime.Text = ccpCharacter != null && ccpCharacter.SkillQueue.IsPaused
                    ? String.Empty
                    : $"{endTime:ddd} {endTime:G}";

                // Changes the completion time color on scheduling block
                string blockingEntry;
                bool   isAutoBlocking;
                bool   isBlocking = Scheduler.SkillIsBlockedAt(endTime, out blockingEntry, out isAutoBlocking);
                lblCompletionTime.ForeColor =
                    m_showConflicts && isBlocking &&
                    (ccpCharacter == null || ccpCharacter.SkillQueue.Count == 1 || !isAutoBlocking)
                        ? Color.Red
                        : m_settingsForeColor;

                // Update the skill queue training time label
                UpdateSkillQueueTrainingTime();

                // Show the training labels
                m_hasSkillInTraining        = true;
                m_hasCompletionTime         = true;
                m_hasRemainingTime          = true;
                m_hasSkillQueueTrainingTime = true;
            }
            else
            {
                // Hide the training labels
                m_hasSkillInTraining        = false;
                m_hasCompletionTime         = false;
                m_hasRemainingTime          = false;
                m_hasSkillQueueTrainingTime = false;
            }

            // Adjusts all the controls layout
            PerformCustomLayout(m_isTooltip);
        }
예제 #21
0
파일: OverviewItem.cs 프로젝트: wbSD/evemon
        /// <summary>
        /// Update the controls.
        /// </summary>
        private void UpdateContent()
        {
            if (!Visible)
            {
                return;
            }

            // Update character's 'Adorned Name' and 'Portrait' in case they have changed
            lblCharName.Text = Character.LabelPrefix + Character.AdornedName;
            pbCharacterPortrait.Character = Character;
            lblTotalSkillPoints.Text      = string.Format("{0:N0} SP", Character.SkillPoints);

            FormatBalance();

            CCPCharacter ccpCharacter  = Character as CCPCharacter;
            QueuedSkill  trainingSkill = Character.CurrentlyTrainingSkill;

            // Character in training ? We have labels to fill
            if (Character.IsTraining || (ccpCharacter != null && trainingSkill != null &&
                                         ccpCharacter.SkillQueue.IsPaused))
            {
                // Update the skill in training label
                lblSkillInTraining.Text = trainingSkill.ToString();
                DateTime endTime = trainingSkill.EndTime.ToLocalTime();

                // Updates the time remaining label
                lblRemainingTime.Text = (ccpCharacter != null && ccpCharacter.SkillQueue.
                                         IsPaused) ? "Paused" : trainingSkill.RemainingTime.ToDescriptiveText(
                    DescriptiveTextOptions.IncludeCommas);

                // Update the completion time
                lblCompletionTime.Text = (ccpCharacter != null && ccpCharacter.SkillQueue.
                                          IsPaused) ? string.Empty : $"{endTime:ddd} {endTime:G}";

                // Changes the completion time color on scheduling block
                string blockingEntry;
                bool   isAutoBlocking;
                bool   isBlocking = Scheduler.SkillIsBlockedAt(endTime, out blockingEntry,
                                                               out isAutoBlocking);
                lblCompletionTime.ForeColor = (m_showConflicts && isBlocking &&
                                               (ccpCharacter == null || ccpCharacter.SkillQueue.Count == 1 ||
                                                !isAutoBlocking)) ? Color.Red : m_settingsForeColor;

                // Update the skill queue training time label
                UpdateSkillQueueTrainingTime();

                // Show the training labels
                m_hasSkillInTraining        = true;
                m_hasCompletionTime         = true;
                m_hasRemainingTime          = true;
                m_hasSkillQueueTrainingTime = true;
            }
            else
            {
                // Hide the training labels
                m_hasSkillInTraining        = false;
                m_hasCompletionTime         = false;
                m_hasRemainingTime          = false;
                m_hasSkillQueueTrainingTime = false;
            }
            // Determine the character's system location
            int    locID = Character?.LastKnownLocation?.SolarSystemID ?? 0;
            string locText;

            if (locID == 0)
            {
                locText = EveMonConstants.UnknownText + " Location";
            }
            else
            {
                locText = StaticGeography.GetSolarSystemName(locID);
            }
            lblLocation.Text = locText;
            // Adjusts all the controls layout
            PerformCustomLayout(m_isTooltip);
        }
예제 #22
0
        /// <summary>
        /// Updates the skill queue training time.
        /// </summary>
        /// <returns></returns>
        private void UpdateSkillQueueTrainingTime()
        {
            CCPCharacter ccpCharacter = Character as CCPCharacter;

            // Current character isn't a CCP character, so can't have a Queue
            if (ccpCharacter == null)
            {
                return;
            }

            if (ccpCharacter.SkillQueue.IsPaused)
            {
                lblSkillQueueTrainingTime.Text = String.Empty;
                return;
            }

            TimeSpan skillQueueEndTime = ccpCharacter.SkillQueue.EndTime.Subtract(DateTime.UtcNow);
            TimeSpan timeLeft          = SkillQueue.WarningThresholdTimeSpan.Subtract(skillQueueEndTime);

            // Negative time ?
            // Skill queue is populated with more than a day
            if (timeLeft < TimeSpan.Zero)
            {
                // More than one entry in queue ? Display total queue remaining time
                if (ccpCharacter.SkillQueue.Count > 1)
                {
                    lblSkillQueueTrainingTime.ForeColor = m_settingsForeColor;
                    lblSkillQueueTrainingTime.Text      =
                        $"Queue ends in {ccpCharacter.SkillQueue.EndTime.ToRemainingTimeShortDescription(DateTimeKind.Utc)}";

                    return;
                }

                // We don't display anything
                lblSkillQueueTrainingTime.Text = String.Empty;
                return;
            }

            // Training completed ?
            if (timeLeft == TimeSpan.Zero)
            {
                // We don't display anything
                lblSkillQueueTrainingTime.Text = String.Empty;
                return;
            }

            // Skill queue is empty ?
            if (timeLeft > SkillQueue.WarningThresholdTimeSpan)
            {
                lblSkillQueueTrainingTime.Text = @"Skill queue is empty";
                return;
            }

            // Less than one minute ? Display seconds else display time without seconds
            string endTimeText = skillQueueEndTime < TimeSpan.FromMinutes(1)
                ? skillQueueEndTime.ToDescriptiveText(DescriptiveTextOptions.IncludeCommas)
                : skillQueueEndTime.ToDescriptiveText(DescriptiveTextOptions.IncludeCommas, includeSeconds: false);

            lblSkillQueueTrainingTime.ForeColor = Color.Red;
            lblSkillQueueTrainingTime.Text      = $"Queue ends in {endTimeText}";
        }
예제 #23
0
 /// <summary>
 /// Internal constructor.
 /// </summary>
 /// <param name="character">The character.</param>
 internal IndustryJobCollection(CCPCharacter character)
 {
     m_ccpCharacter          = character;
     EveMonClient.TimerTick += EveMonClient_TimerTick;
 }
예제 #24
0
        /// <summary>
        /// Sends a mail alert for a skill completion
        /// </summary>
        /// <param name="queueList">Current Skill Queue</param>
        /// <param name="skill">Skill that has just completed</param>
        /// <param name="character">Character affected</param>
        /// <exception cref="System.ArgumentNullException">
        /// </exception>
        public static void SendSkillCompletionMail(IList <QueuedSkill> queueList, QueuedSkill skill, Character character)
        {
            s_isTestMail = false;

            queueList.ThrowIfNull(nameof(queueList));

            skill.ThrowIfNull(nameof(skill));

            CCPCharacter ccpCharacter = character as CCPCharacter;

            // Current character isn't a CCP character, so can't have a Queue.
            if (ccpCharacter == null)
            {
                return;
            }

            string skillLevelText = $"{skill.SkillName} {Skill.GetRomanFromInt(skill.Level)}";
            string subjectText    = $"{character.Name} has finished training {skillLevelText}.";

            // Message's first line
            StringBuilder body = new StringBuilder();

            body
            .AppendLine(subjectText)
            .AppendLine();

            // Next skills in queue
            if (queueList[0] != null)
            {
                string plural = queueList.Count > 1 ? "s" : string.Empty;
                body.AppendLine($"Next skill{plural} in queue:");

                foreach (QueuedSkill qskill in queueList)
                {
                    body.AppendLine($"- {qskill}");
                }
                body.AppendLine();
            }
            else
            {
                body
                .AppendLine("Character is not training.")
                .AppendLine();
            }

            // Skill queue less than a day
            if (ccpCharacter.SkillQueue.LessThanWarningThreshold)
            {
                TimeSpan skillQueueEndTime = ccpCharacter.SkillQueue.EndTime.Subtract(DateTime.UtcNow);
                TimeSpan timeLeft          = SkillQueue.WarningThresholdTimeSpan.Subtract(skillQueueEndTime);

                // Skill queue empty?
                if (timeLeft > SkillQueue.WarningThresholdTimeSpan)
                {
                    body.AppendLine("Skill queue is empty.");
                }
                else
                {
                    string timeLeftText = skillQueueEndTime < TimeSpan.FromMinutes(1)
                        ? skillQueueEndTime.ToDescriptiveText(DescriptiveTextOptions.IncludeCommas)
                        : skillQueueEndTime.ToDescriptiveText(DescriptiveTextOptions.IncludeCommas, false);

                    body.AppendLine($"Queue ends in {timeLeftText}.");
                }
            }

            // Short format (also for SMS)
            if (Settings.Notifications.UseEmailShortFormat)
            {
                SendMail(Settings.Notifications,
                         $"[STC] {character.Name} :: {skillLevelText}",
                         body.ToString());

                return;
            }

            // Long format
            if (character.Plans.Count > 0)
            {
                body.AppendLine("Next skills listed in plans:")
                .AppendLine();
            }

            foreach (Plan plan in character.Plans)
            {
                if (plan.Count <= 0)
                {
                    continue;
                }

                // Print plan name
                CharacterScratchpad scratchpad = new CharacterScratchpad(character);
                body.AppendLine($"{plan.Name}:");

                // Scroll through entries
                int i       = 0;
                int minDays = 1;
                foreach (PlanEntry entry in plan)
                {
                    TimeSpan trainTime = scratchpad.GetTrainingTime(entry.Skill, entry.Level,
                                                                    TrainingOrigin.FromPreviousLevelOrCurrent);

                    // Only print the first three skills, and the very long skills
                    // (first limit is one day, then we add skills duration)
                    if (++i > 3 && trainTime.Days <= minDays)
                    {
                        continue;
                    }

                    if (i > 3)
                    {
                        // Print long message once
                        if (minDays == 1)
                        {
                            body.AppendLine().Append($"Longer skills from {plan.Name}:").AppendLine();
                        }

                        minDays = trainTime.Days + minDays;
                    }
                    body.Append($"\t{entry}");

                    // Notes
                    if (!string.IsNullOrEmpty(entry.Notes))
                    {
                        body.Append($" ({entry.Notes})");
                    }

                    // Training time
                    body
                    .Append(trainTime.Days > 0 ? $" - {trainTime.Days}d, {trainTime}" : $" - {trainTime}")
                    .AppendLine();
                }
                body.AppendLine();
            }

            SendMail(Settings.Notifications, subjectText, body.ToString());
        }
예제 #25
0
 /// <summary>
 /// Internal constructor.
 /// </summary>
 /// <param name="ccpCharacter">The CCP character.</param>
 internal KillLogCollection(CCPCharacter ccpCharacter)
 {
     m_ccpCharacter = ccpCharacter;
 }
예제 #26
0
 /// <summary>
 /// Initializes a new instance of the <see cref="WalletJournalChartWindow"/> class.
 /// </summary>
 /// <param name="ccpCharacter">The CCP character.</param>
 public WalletJournalChartWindow(CCPCharacter ccpCharacter)
     : this()
 {
     m_ccpCharacter = ccpCharacter;
 }
예제 #27
0
 /// <summary>
 /// Internal constructor.
 /// </summary>
 /// <param name="ccpCharacter">The CCP character.</param>
 internal KillLogCollection(CCPCharacter ccpCharacter)
 {
     m_ccpCharacter    = ccpCharacter;
     m_killMailCounter = 0;
     m_pendingItems    = new List <KillLog>(32);
 }
예제 #28
0
 /// <summary>
 /// Internal constructor.
 /// </summary>
 /// <param name="character">The character.</param>
 internal ResearchPointCollection(CCPCharacter character)
 {
     m_character = character;
 }
예제 #29
0
        /// <summary>
        /// Internal constructor.
        /// </summary>
        /// <param name="ccpCharacter">The CCP character.</param>
        internal PlanetaryColonyCollection(CCPCharacter ccpCharacter)
        {
            m_ccpCharacter = ccpCharacter;

            EveMonClient.TimerTick += EveMonClient_TimerTick;
        }
예제 #30
0
 /// <summary>
 /// Internal constructor.
 /// </summary>
 /// <param name="character">The character.</param>
 internal StandingCollection(CCPCharacter character)
 {
     m_character = character;
 }
예제 #31
0
        /// <summary>
        /// Occurs when some of the G15 screen buttons are pressed.
        /// </summary>
        /// <returns></returns>
        private void ButtonPressedCheckTimerOnElapsed(object sender, ElapsedEventArgs elapsedEventArgs)
        {
            var pressedButtons = 0;

            if (LcdInterface.ReadSoftButton((int)LogitechLcdConstants.LogiLcdMonoButton.Button0))
            {
                pressedButtons |= (int)LogitechLcdConstants.LogiLcdMonoButton.Button0;
            }

            if (LcdInterface.ReadSoftButton((int)LogitechLcdConstants.LogiLcdMonoButton.Button1))
            {
                pressedButtons |= (int)LogitechLcdConstants.LogiLcdMonoButton.Button1;
            }

            if (LcdInterface.ReadSoftButton((int)LogitechLcdConstants.LogiLcdMonoButton.Button2))
            {
                pressedButtons |= (int)LogitechLcdConstants.LogiLcdMonoButton.Button2;
            }

            if (LcdInterface.ReadSoftButton((int)LogitechLcdConstants.LogiLcdMonoButton.Button3))
            {
                pressedButtons |= (int)LogitechLcdConstants.LogiLcdMonoButton.Button3;
            }

            if (m_oldButtonState == pressedButtons)
            {
                return;
            }

            // Gets all buttons who haven't been pressed last time
            int press = (m_oldButtonState ^ pressedButtons) & pressedButtons;

            // Displays the characters' list or move to the next char if the list is already displayed.
            if ((press & (int)LogitechLcdConstants.LogiLcdMonoButton.Button0) != 0)
            {
                DisplayCharactersList();
            }

            // Move to the first character to complete his training
            if ((press & (int)LogitechLcdConstants.LogiLcdMonoButton.Button1) != 0)
            {
                // Select next skill ready char
                if (!MonitoredCharacters.Any())
                {
                    return;
                }

                CurrentCharacter = FirstCharacterToCompleteSkill;

                AutoCycleChanged?.ThreadSafeInvoke(this, new CycleEventArgs(false));

                SwitchState(LcdState.Character);
            }

            // Forces a refresh from CCP
            if ((press & (int)LogitechLcdConstants.LogiLcdMonoButton.Button2) != 0)
            {
                if (m_state == LcdState.Character || m_state == LcdState.CharacterList)
                {
                    m_refreshCharacter = CurrentCharacter;
                    ApiUpdateRequested?.ThreadSafeInvoke(this, new CharacterChangedEventArgs(m_refreshCharacter));

                    SwitchState(LcdState.Refreshing);
                }
            }

            // Switch autocycle ON/OFF
            if ((press & (int)LogitechLcdConstants.LogiLcdMonoButton.Button3) != 0)
            {
                // Switch autocycle on/off
                SwitchCycle();

                AutoCycleChanged?.ThreadSafeInvoke(this, new CycleEventArgs(Cycle));

                SwitchState(LcdState.CycleSettings);
                m_cycleTime = DateTime.Now;
            }

            m_oldButtonState = pressedButtons;
        }
예제 #32
0
        /// <summary>
        /// Initializes a new instance of the <see cref="CharacterDataQuerying"/> class.
        /// </summary>
        /// <param name="ccpCharacter">The CCP character.</param>
        internal CharacterDataQuerying(CCPCharacter ccpCharacter)
        {
            var notifiers = EveMonClient.Notifications;

            m_ccpCharacter           = ccpCharacter;
            m_characterQueryMonitors = new List <IQueryMonitorEx>();
            m_attrResponse           = null;
            m_lastQueue = null;

            // Add the monitors in an order as they will appear in the throbber menu
            m_charSheetMonitor = new CharacterQueryMonitor <EsiAPICharacterSheet>(ccpCharacter,
                                                                                  ESIAPICharacterMethods.CharacterSheet, OnCharacterSheetUpdated,
                                                                                  notifiers.NotifyCharacterSheetError);
            m_characterQueryMonitors.Add(m_charSheetMonitor);
            // Location
            m_characterQueryMonitors.Add(new CharacterQueryMonitor <EsiAPILocation>(
                                             ccpCharacter, ESIAPICharacterMethods.Location, OnCharacterLocationUpdated,
                                             notifiers.NotifyCharacterLocationError));
            // Clones
            m_characterQueryMonitors.Add(new CharacterQueryMonitor <EsiAPIClones>(
                                             ccpCharacter, ESIAPICharacterMethods.Clones, OnCharacterClonesUpdated,
                                             notifiers.NotifyCharacterClonesError));
            // Implants
            m_characterQueryMonitors.Add(new CharacterQueryMonitor <List <int> >(
                                             ccpCharacter, ESIAPICharacterMethods.Implants, OnCharacterImplantsUpdated,
                                             OnCharacterImplantsFailed));
            // Ship
            m_characterQueryMonitors.Add(new CharacterQueryMonitor <EsiAPIShip>(
                                             ccpCharacter, ESIAPICharacterMethods.Ship, OnCharacterShipUpdated,
                                             notifiers.NotifyCharacterShipError));
            // Skills
            m_charSkillsMonitor = new CharacterQueryMonitor <EsiAPISkills>(
                ccpCharacter, ESIAPICharacterMethods.Skills, OnCharacterSkillsUpdated,
                notifiers.NotifyCharacterSkillsError);
            m_characterQueryMonitors.Add(m_charSkillsMonitor);
            // Skill queue
            m_charSkillQueueMonitor = new CharacterQueryMonitor <EsiAPISkillQueue>(
                ccpCharacter, ESIAPICharacterMethods.SkillQueue, OnSkillQueueUpdated,
                notifiers.NotifySkillQueueError);
            m_characterQueryMonitors.Add(m_charSkillQueueMonitor);
            // Employment history
            m_characterQueryMonitors.Add(new CharacterQueryMonitor <EsiAPIEmploymentHistory>(
                                             ccpCharacter, ESIAPICharacterMethods.EmploymentHistory,
                                             OnCharacterEmploymentUpdated, notifiers.NotifyCharacterEmploymentError));
            // Standings
            m_characterQueryMonitors.Add(new PagedQueryMonitor <EsiAPIStandings,
                                                                EsiStandingsListItem>(new CharacterQueryMonitor <EsiAPIStandings>(
                                                                                          ccpCharacter, ESIAPICharacterMethods.Standings, OnStandingsUpdated,
                                                                                          notifiers.NotifyCharacterStandingsError)
            {
                QueryOnStartup = true
            }));
            // Contacts
            m_characterQueryMonitors.Add(new PagedQueryMonitor <EsiAPIContactsList,
                                                                EsiContactListItem>(new CharacterQueryMonitor <EsiAPIContactsList>(ccpCharacter,
                                                                                                                                   ESIAPICharacterMethods.ContactList, OnContactsUpdated,
                                                                                                                                   notifiers.NotifyCharacterContactsError)
            {
                QueryOnStartup = true
            }));
            // Factional warfare
            m_characterQueryMonitors.Add(new CharacterQueryMonitor <EsiAPIFactionalWarfareStats>(
                                             ccpCharacter, ESIAPICharacterMethods.FactionalWarfareStats,
                                             OnFactionalWarfareStatsUpdated, notifiers.
                                             NotifyCharacterFactionalWarfareStatsError)
            {
                QueryOnStartup = true
            });
            // Medals
            m_characterQueryMonitors.Add(new PagedQueryMonitor <EsiAPIMedals,
                                                                EsiMedalsListItem>(new CharacterQueryMonitor <EsiAPIMedals>(ccpCharacter,
                                                                                                                            ESIAPICharacterMethods.Medals, OnMedalsUpdated,
                                                                                                                            notifiers.NotifyCharacterMedalsError)
            {
                QueryOnStartup = true
            }));
            // Kill log
            m_characterQueryMonitors.Add(new PagedQueryMonitor <EsiAPIKillLog,
                                                                EsiKillLogListItem>(new CharacterQueryMonitor <EsiAPIKillLog>(ccpCharacter,
                                                                                                                              ESIAPICharacterMethods.KillLog, OnKillLogUpdated,
                                                                                                                              notifiers.NotifyCharacterKillLogError)
            {
                QueryOnStartup = true
            }));
            // Assets
            m_characterQueryMonitors.Add(new PagedQueryMonitor <EsiAPIAssetList,
                                                                EsiAssetListItem>(new CharacterQueryMonitor <EsiAPIAssetList>(ccpCharacter,
                                                                                                                              ESIAPICharacterMethods.AssetList, OnAssetsUpdated,
                                                                                                                              notifiers.NotifyCharacterAssetsError)
            {
                QueryOnStartup = true
            }));
            // Market orders
            m_charMarketOrdersMonitor = new CharacterQueryMonitor <EsiAPIMarketOrders>(
                ccpCharacter, ESIAPICharacterMethods.MarketOrders, OnMarketOrdersUpdated,
                notifiers.NotifyCharacterMarketOrdersError)
            {
                QueryOnStartup = true
            };
            m_characterQueryMonitors.Add(m_charMarketOrdersMonitor);
            // Contracts
            m_charContractsMonitor = new PagedQueryMonitor <EsiAPIContracts,
                                                            EsiContractListItem>(new CharacterQueryMonitor <EsiAPIContracts>(ccpCharacter,
                                                                                                                             ESIAPICharacterMethods.Contracts, OnContractsUpdated,
                                                                                                                             notifiers.NotifyCharacterContractsError)
            {
                QueryOnStartup = true
            });
            m_characterQueryMonitors.Add(m_charContractsMonitor);
            // Wallet journal
            m_characterQueryMonitors.Add(new PagedQueryMonitor <EsiAPIWalletJournal,
                                                                EsiWalletJournalListItem>(new CharacterQueryMonitor <EsiAPIWalletJournal>(
                                                                                              ccpCharacter, ESIAPICharacterMethods.WalletJournal, OnWalletJournalUpdated,
                                                                                              notifiers.NotifyCharacterWalletJournalError)
            {
                QueryOnStartup = true
            }));
            // Wallet balance
            m_characterQueryMonitors.Add(new CharacterQueryMonitor <string>(
                                             ccpCharacter, ESIAPICharacterMethods.AccountBalance, OnWalletBalanceUpdated,
                                             notifiers.NotifyCharacterBalanceError));
            // Wallet transactions
            m_characterQueryMonitors.Add(new PagedQueryMonitor <EsiAPIWalletTransactions,
                                                                EsiWalletTransactionsListItem>(new CharacterQueryMonitor <
                                                                                                   EsiAPIWalletTransactions>(ccpCharacter, ESIAPICharacterMethods.
                                                                                                                             WalletTransactions, OnWalletTransactionsUpdated, notifiers.
                                                                                                                             NotifyCharacterWalletTransactionsError)
            {
                QueryOnStartup = true
            }));
            // Industry
            m_charIndustryJobsMonitor = new CharacterQueryMonitor <EsiAPIIndustryJobs>(
                ccpCharacter, ESIAPICharacterMethods.IndustryJobs, OnIndustryJobsUpdated,
                notifiers.NotifyCharacterIndustryJobsError)
            {
                QueryOnStartup = true
            };
            m_characterQueryMonitors.Add(m_charIndustryJobsMonitor);
            // Research points
            m_characterQueryMonitors.Add(new CharacterQueryMonitor <EsiAPIResearchPoints>(
                                             ccpCharacter, ESIAPICharacterMethods.ResearchPoints, OnResearchPointsUpdated,
                                             notifiers.NotifyCharacterResearchPointsError)
            {
                QueryOnStartup = true
            });
            // Mail
            m_characterQueryMonitors.Add(new CharacterQueryMonitor <EsiAPIMailMessages>(
                                             ccpCharacter, ESIAPICharacterMethods.MailMessages, OnEVEMailMessagesUpdated,
                                             notifiers.NotifyEVEMailMessagesError)
            {
                QueryOnStartup = true
            });
            // Mailing lists
            m_characterQueryMonitors.Add(new CharacterQueryMonitor <EsiAPIMailingLists>(
                                             ccpCharacter, ESIAPICharacterMethods.MailingLists, OnEveMailingListsUpdated,
                                             notifiers.NotifyMailingListsError));
            // Notifications
            m_characterQueryMonitors.Add(new CharacterQueryMonitor <EsiAPINotifications>(
                                             ccpCharacter, ESIAPICharacterMethods.Notifications, OnEVENotificationsUpdated,
                                             notifiers.NotifyEVENotificationsError)
            {
                QueryOnStartup = true
            });
            // Calendar
            m_characterQueryMonitors.Add(new CharacterQueryMonitor <EsiAPICalendarEvents>(
                                             ccpCharacter, ESIAPICharacterMethods.UpcomingCalendarEvents,
                                             OnUpcomingCalendarEventsUpdated, notifiers.
                                             NotifyCharacterUpcomingCalendarEventsError)
            {
                QueryOnStartup = true
            });
            // PI
            m_characterQueryMonitors.Add(new CharacterQueryMonitor <EsiAPIPlanetaryColoniesList>(
                                             ccpCharacter, ESIAPICharacterMethods.PlanetaryColonies,
                                             OnPlanetaryColoniesUpdated, notifiers.
                                             NotifyCharacterPlanetaryColoniesError)
            {
                QueryOnStartup = true
            });
            m_characterQueryMonitors.ForEach(monitor => ccpCharacter.QueryMonitors.Add(monitor));

            // Enumerate the basic feature monitors into a separate list
            m_basicFeaturesMonitors = new List <IQueryMonitorEx>(m_characterQueryMonitors.Count);
            long basicFeatures = (long)CCPAPIMethodsEnum.BasicCharacterFeatures;

            foreach (var monitor in m_characterQueryMonitors)
            {
                long method = (long)(ESIAPICharacterMethods)monitor.Method;
                if (method == (method & basicFeatures))
                {
                    m_basicFeaturesMonitors.Add(monitor);
                    // If force update is selected, update basic features only
                    if (ccpCharacter.ForceUpdateBasicFeatures)
                    {
                        monitor.ForceUpdate(true);
                    }
                }
            }

            EveMonClient.TimerTick += EveMonClient_TimerTick;
        }
예제 #33
0
 /// <summary>
 /// Internal constructor.
 /// </summary>
 /// <param name="character">The character.</param>
 internal ContractBidCollection(CCPCharacter character)
 {
     m_character = character;
 }
예제 #34
0
        /// <summary>
        /// Occurs when some of the G15 screen buttons are pressed.
        /// </summary>
        /// <returns></returns>
        private void ButtonPressedCheckTimerOnElapsed(object sender, ElapsedEventArgs elapsedEventArgs)
        {
            var pressedButtons = 0;

            if (LcdInterface.ReadSoftButton((int)LogitechLcdConstants.LogiLcdMonoButton.Button0))
                pressedButtons |= (int)LogitechLcdConstants.LogiLcdMonoButton.Button0;

            if (LcdInterface.ReadSoftButton((int)LogitechLcdConstants.LogiLcdMonoButton.Button1))
                pressedButtons |= (int)LogitechLcdConstants.LogiLcdMonoButton.Button1;

            if (LcdInterface.ReadSoftButton((int)LogitechLcdConstants.LogiLcdMonoButton.Button2))
                pressedButtons |= (int)LogitechLcdConstants.LogiLcdMonoButton.Button2;

            if (LcdInterface.ReadSoftButton((int)LogitechLcdConstants.LogiLcdMonoButton.Button3))
                pressedButtons |= (int)LogitechLcdConstants.LogiLcdMonoButton.Button3;

            if (m_oldButtonState == pressedButtons)
                return;

            // Gets all buttons who haven't been pressed last time
            int press = (m_oldButtonState ^ pressedButtons) & pressedButtons;

            // Displays the characters' list or move to the next char if the list is already displayed.
            if ((press & (int)LogitechLcdConstants.LogiLcdMonoButton.Button0) != 0)
                DisplayCharactersList();

            // Move to the first character to complete his training
            if ((press & (int)LogitechLcdConstants.LogiLcdMonoButton.Button1) != 0)
            {
                // Select next skill ready char
                if (!MonitoredCharacters.Any())
                    return;

                CurrentCharacter = FirstCharacterToCompleteSkill;

                AutoCycleChanged?.ThreadSafeInvoke(this, new CycleEventArgs(false));

                SwitchState(LcdState.Character);
            }

            // Forces a refresh from CCP
            if ((press & (int)LogitechLcdConstants.LogiLcdMonoButton.Button2) != 0)
            {
                if (m_state == LcdState.Character || m_state == LcdState.CharacterList)
                {
                    m_refreshCharacter = CurrentCharacter;
                    ApiUpdateRequested?.ThreadSafeInvoke(this, new CharacterChangedEventArgs(m_refreshCharacter));

                    SwitchState(LcdState.Refreshing);
                }
            }

            // Switch autocycle ON/OFF
            if ((press & (int)LogitechLcdConstants.LogiLcdMonoButton.Button3) != 0)
            {
                // Switch autocycle on/off
                SwitchCycle();

                AutoCycleChanged?.ThreadSafeInvoke(this, new CycleEventArgs(Cycle));

                SwitchState(LcdState.CycleSettings);
                m_cycleTime = DateTime.Now;
            }

            m_oldButtonState = pressedButtons;
        }