From ddfa75d5d09ac13ff554193204a31e10e505e1db Mon Sep 17 00:00:00 2001 From: esitarski Date: Thu, 25 Apr 2024 16:43:10 -0400 Subject: [PATCH 1/5] Added ability to set early bell from Chart screen. --- Gantt.py | 46 ++++++++++++++++++++++++++++++++++++++++++++++ GanttChartPanel.py | 37 ++++++++++++++++++++++++++++++++++--- SetLaps.py | 2 +- 3 files changed, 81 insertions(+), 4 deletions(-) diff --git a/Gantt.py b/Gantt.py index a8acb673..9aea70c9 100644 --- a/Gantt.py +++ b/Gantt.py @@ -8,8 +8,37 @@ from Undo import undo import EditEntry from NumberEntryDialog import NumberEntryDialog +from HighPrecisionTimeEdit import HighPrecisionTimeEdit from bisect import bisect_right +class EarlyBellDialog( wx.Dialog ): + def __init__( self, parent, category, earlyBellTime=None, id=wx.ID_ANY ): + super().__init__( parent, id, _("Early Bell Time"), + style=wx.DEFAULT_DIALOG_STYLE|wx.TAB_TRAVERSAL|wx.STAY_ON_TOP ) + + title = wx.StaticText(self, label=category.fullname) + title.SetFont( wx.Font( wx.FontInfo(14) ) ) + + self.earlyBellTimeLabel = wx.StaticText(self, label=_('Early Bell Time')) + self.earlyBellTime = HighPrecisionTimeEdit( self, allow_none=True, display_milliseconds=False ) + self.earlyBellTime.SetSeconds( earlyBellTime or None ) + + nes = wx.BoxSizer( wx.HORIZONTAL ) + nes.Add( self.earlyBellTimeLabel, flag=wx.ALIGN_CENTRE_VERTICAL ) + nes.Add( self.earlyBellTime, 1, flag=wx.LEFT|wx.EXPAND, border=4 ) + + bs = self.CreateButtonSizer( wx.OK | wx.CANCEL ) + + mainSizer = wx.BoxSizer( wx.VERTICAL ) + mainSizer.Add( title, flag=wx.ALL|wx.EXPAND, border=4 ) + mainSizer.Add( nes, flag=wx.ALL|wx.EXPAND, border=4 ) + mainSizer.Add( bs, flag=wx.ALL|wx.EXPAND, border=4 ) + + self.SetSizerAndFit( mainSizer ) + + def GetEarlyBellTime( self ): + return self.earlyBellTime.GetSeconds() + def UpdateSetNum( num ): if num is None: return @@ -143,6 +172,7 @@ def onRightClick( self, xPos, yPos, num, iRider, iLap ): (None, None, None, None), (_('RiderDetail') + '...', _('Show RiderDetail Dialog'), self.OnPopupRiderDetail, allCases), (_('Results'), _('Switch to Results tab'), self.OnPopupResults, allCases), + (_('Set Early Bell') + '...', _('Set Early Bell Time'), self.OnPopupEarlyBell, allCases), ] self.splitMenuInfo = [ @@ -501,6 +531,22 @@ def OnPopupPhotos( self, event ): mainWin.photoDialog.Show( True ) mainWin.photoDialog.refresh( self.numSelect, self.entryEnd.t if self.entryEnd else None ) + def OnPopupEarlyBell( self, event ): + race = Model.race + if not race or not self.numSelect: + return + category = race.getCategory( self.numSelect ) + if not category: + return + earlyBellTime = getattr( self.ganttChart, 'tCursor', None ) + if not earlyBellTime: + return + with EarlyBellDialog( self, category=category, earlyBellTime=earlyBellTime ) as dlg: + if dlg.ShowModal() == wx.ID_OK and category.earlyBellTime != dlg.GetEarlyBellTime(): + category.earlyBellTime = dlg.GetEarlyBellTime() + race.setChanged() + wx.CallAfter( Utils.getMainWin().refreshAll ) + def updateStats( self, results ): s = '' if results: diff --git a/GanttChartPanel.py b/GanttChartPanel.py index d536e350..54206c9a 100644 --- a/GanttChartPanel.py +++ b/GanttChartPanel.py @@ -231,7 +231,7 @@ def OnMove( self, event ): self.xMove, self.yMove = event.GetPosition() redrawRequired = (self.moveIRider is not None) self.moveIRider, self.moveLap = None, None - self.moveTimer.Start( 100, True ) + self.moveTimer.Start( 25, True ) # If the timer is already running, it will be stopped and restarted. def OnMoveTimer( self, event ): self.moveIRider, self.moveLap = self.getRiderLapXY( self.xMove, self.yMove ) @@ -303,6 +303,7 @@ def Draw( self, dc ): dc.Clear() tooSmall = (width < 50 or height < 24) + self.tCursor = None if not self.data or self.dataMax == 0 or tooSmall: self.empty = True @@ -417,6 +418,7 @@ def Draw( self, dc ): fontLegend = wx.Font( (0,int(barHeight*.75)), wx.FONTFAMILY_SWISS, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL ) fontNote = wx.Font( (0,int(barHeight*.8)), wx.FONTFAMILY_SWISS, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL ) + self.fontLegend = fontLegend dc.SetFont( fontLegend ) textWidth, textHeight = dc.GetTextExtent( '00:00' if self.dataMax < 60*60 else '00:00:00' ) @@ -516,9 +518,11 @@ def overlaps( d ): tLeaderLast = None dy = 0 - + def tToX( t ): return int(labelsWidthLeft + (t-tAdjust) * xFactor) + # Set inverse function to get from screen x coords to time. + self.xToT = lambda x: (x-labelsWidthLeft) / xFactor + tAdjust for i, s in enumerate(self.data): # Record the leader's last x position. @@ -729,7 +733,7 @@ def getStarPath( ctx, numPoints, radius, radiusInner ): # Draw the now timeline. timeLineTime = self.nowTime if self.nowTime and self.nowTime < self.dataMax else tLeaderLast nowTimeStr = Utils.formatTime( timeLineTime ) - labelWidth, labelHeight = dc.GetTextExtent( nowTimeStr ) + labelWidth, labelHeight = dc.GetTextExtent( nowTimeStr ) x = int(labelsWidthLeft + (timeLineTime - tAdjust) * xFactor) if xLeft <= x < xRight: ntColour = '#339966' @@ -751,6 +755,33 @@ def getStarPath( ctx, numPoints, radius, radiusInner ): if not self.minimizeLabels: dc.DrawText( nowTimeStr, x - labelWidth // 2, yLast + 2 ) + # Draw the vertical line tracker. + if xLeft <= self.xMove < xRight: + x = self.xMove + self.tCursor = self.xToT( self.xMove ) + + tStr = Utils.formatTime( self.tCursor ) + labelWidth, labelHeight = dc.GetTextExtent( nowTimeStr ) + + ctColour = '#CF9FFF' + dc.SetPen( wx.Pen(ctColour, 3) ) + dc.DrawLine( x, barHeight - 4, x, yLast + 4 ) + dc.SetPen( wx.Pen(wx.WHITE, 1) ) + dc.DrawLine( x, barHeight - 4, x, yLast + 4 ) + + dc.SetBrush( wx.Brush(ctColour) ) + dc.SetPen( wx.Pen(ctColour,1) ) + rect = wx.Rect( x - labelWidth//2-2, 0, labelWidth+4, labelHeight ) + dc.DrawRectangle( rect ) + if not self.minimizeLabels: + rect.SetY( yLast+2 ) + dc.DrawRectangle( rect ) + + dc.SetTextForeground( wx.BLACK ) + dc.DrawText( tStr, x - labelWidth // 2, 0 ) + if not self.minimizeLabels: + dc.DrawText( tStr, x - labelWidth // 2, yLast + 2 ) + # Store the drawing scale parameters. self.xFactor = xFactor self.barHeight = barHeight diff --git a/SetLaps.py b/SetLaps.py index b0fe76f6..bcac9362 100644 --- a/SetLaps.py +++ b/SetLaps.py @@ -11,7 +11,7 @@ class SetLaps( wx.Dialog ): updateInterval = 5314 - def __init__( self, parent, category, id = wx.ID_ANY ): + def __init__( self, parent, category, id=wx.ID_ANY ): super().__init__( parent, id, _("Set Laps"), style=wx.DEFAULT_DIALOG_STYLE|wx.TAB_TRAVERSAL ) From 1ece027c6d23ca9a9e970c1d0abbcc3665d45d07 Mon Sep 17 00:00:00 2001 From: esitarski Date: Thu, 25 Apr 2024 17:48:23 -0400 Subject: [PATCH 2/5] Update Chart help to explain the Early Bell feature. --- helptxt/Chart.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/helptxt/Chart.md b/helptxt/Chart.md index 6fc7fac2..04ed03bf 100644 --- a/helptxt/Chart.md +++ b/helptxt/Chart.md @@ -60,6 +60,18 @@ Swap with Rider before|Swap current rider's finish time with preceeding rider's Swap with Rider after|Swap current rider's finish time with the following rider's finish time Show Lap Details...|Shows the details of the lap. This includes the lap start, end, time, time down, and any reasons for changes to the start or end of the lap. RiderDetail|Opens RiderDetail dialog for current rider +Set Early Bell Time|Opens a Dialog to set the Early Bell Time for this category at the time under the cursor. Results|Jumps to Results tab with current rider highlighed Remember, Ctrl-Z is undo! (Ctrl-Y is redo). + +__Notes:__ + +__Set Early Bell Time:__ Allows you to set the __Early Bell Time__ directly from the display. +The Early Bell Time is the time when all all riders in a category are given the bell. + +The Chart screen makes it easy to decide when to schedule an Early Bell. Check if there is a +natural break between riders in contention (who you wish to finish a lap early) and riders who are close to the leader in the Start Wave. +Move the cursor to where you want the Early Bell time, select __Set Early Bell Time__, and click OK. +To remove an __Early Bell Time__, set it to blank. + From c0c2d71f60da017b5ed56d06c03433d1446803be Mon Sep 17 00:00:00 2001 From: esitarski Date: Fri, 26 Apr 2024 07:45:39 -0400 Subject: [PATCH 3/5] Added horizontal line to the cursor in the Chart screen. --- GanttChartPanel.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/GanttChartPanel.py b/GanttChartPanel.py index 54206c9a..1a9070b6 100644 --- a/GanttChartPanel.py +++ b/GanttChartPanel.py @@ -755,20 +755,24 @@ def getStarPath( ctx, numPoints, radius, radiusInner ): if not self.minimizeLabels: dc.DrawText( nowTimeStr, x - labelWidth // 2, yLast + 2 ) - # Draw the vertical line tracker. - if xLeft <= self.xMove < xRight: + # Draw the cursor crosshair. + if self.moveIRider is not None and xLeft <= self.xMove < xRight: x = self.xMove self.tCursor = self.xToT( self.xMove ) tStr = Utils.formatTime( self.tCursor ) labelWidth, labelHeight = dc.GetTextExtent( nowTimeStr ) - ctColour = '#CF9FFF' + # Draw the vertical and horizontal lines. + ctColour = '#3F3F3F' + ctTextColour = wx.WHITE + dc.SetPen( wx.Pen(ctColour, 3) ) dc.DrawLine( x, barHeight - 4, x, yLast + 4 ) - dc.SetPen( wx.Pen(wx.WHITE, 1) ) - dc.DrawLine( x, barHeight - 4, x, yLast + 4 ) + if self.data[self.moveIRider]: + dc.DrawLine( xLeft-4, self.yMove, xRight+4, self.yMove ) + # Draw the time text. dc.SetBrush( wx.Brush(ctColour) ) dc.SetPen( wx.Pen(ctColour,1) ) rect = wx.Rect( x - labelWidth//2-2, 0, labelWidth+4, labelHeight ) @@ -777,7 +781,7 @@ def getStarPath( ctx, numPoints, radius, radiusInner ): rect.SetY( yLast+2 ) dc.DrawRectangle( rect ) - dc.SetTextForeground( wx.BLACK ) + dc.SetTextForeground( ctTextColour ) dc.DrawText( tStr, x - labelWidth // 2, 0 ) if not self.minimizeLabels: dc.DrawText( tStr, x - labelWidth // 2, yLast + 2 ) From 548d741bc1410dda6800d64579524595a2dd2c04 Mon Sep 17 00:00:00 2001 From: esitarski Date: Fri, 26 Apr 2024 07:46:13 -0400 Subject: [PATCH 4/5] Bumped version. --- Version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Version.py b/Version.py index 041ccd94..154e4f3f 100644 --- a/Version.py +++ b/Version.py @@ -1 +1 @@ -AppVerName="CrossMgr 3.1.50-private" +AppVerName="CrossMgr 3.1.51-private" From 1406c6cbe16723bfb65f99216b13cd7cfcde1572 Mon Sep 17 00:00:00 2001 From: esitarski Date: Fri, 26 Apr 2024 07:56:11 -0400 Subject: [PATCH 5/5] Added separator to dialog. --- Gantt.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Gantt.py b/Gantt.py index 9aea70c9..631fd51e 100644 --- a/Gantt.py +++ b/Gantt.py @@ -27,12 +27,13 @@ def __init__( self, parent, category, earlyBellTime=None, id=wx.ID_ANY ): nes.Add( self.earlyBellTimeLabel, flag=wx.ALIGN_CENTRE_VERTICAL ) nes.Add( self.earlyBellTime, 1, flag=wx.LEFT|wx.EXPAND, border=4 ) - bs = self.CreateButtonSizer( wx.OK | wx.CANCEL ) + bs = self.CreateSeparatedButtonSizer( wx.OK | wx.CANCEL ) mainSizer = wx.BoxSizer( wx.VERTICAL ) mainSizer.Add( title, flag=wx.ALL|wx.EXPAND, border=4 ) mainSizer.Add( nes, flag=wx.ALL|wx.EXPAND, border=4 ) - mainSizer.Add( bs, flag=wx.ALL|wx.EXPAND, border=4 ) + if bs: + mainSizer.Add( bs, flag=wx.ALL|wx.EXPAND, border=4 ) self.SetSizerAndFit( mainSizer )