B4A=true Group=Default Group ModulesStructureVersion=1 Type=Class Version=13 @EndOfDesignText@ Sub Class_Globals Private xui As XUI Private pnlClock As Panel ' Pannello in cui disegnare l'orologio Private cvsClock As B4XCanvas ' Canvas per disegnare l'orologio Private clockDiameter As Float ' Diametro dell'orologio (in pixel) Private centerX As Float ' Coordinata X del centro dell'orologio Private centerY As Float ' Coordinata Y del centro dell'orologio Private segments As List ' Segmenti cronologici registrati ' Parametri di spessore Private quadrantStrokeWidth As Float = 5dip Private hourTickStrokeWidth As Float = 5dip Private minuteTickStrokeWidth As Float = 2dip Private intervalArcStrokeWidth As Float = 5dip Private hourHandStrokeWidth As Float = 8dip Private minuteHandStrokeWidth As Float = 5dip Private baseDurationMs As Long Private activeDurationMs As Long Private activeColor As Int Private activeIsPause As Boolean Private hasActiveSegment As Boolean End Sub ' Inizializza l'orologio Public Sub Initialize(ParentPanel As Panel, PercentageOfWidth As Float) pnlClock = ParentPanel cvsClock.Initialize(pnlClock) segments.Initialize baseDurationMs = 12 * DateTime.TicksPerHour SetClockSize(PercentageOfWidth) End Sub ' Imposta la durata piena del quadrante. Le pause gialle vengono aggiunte a parte. Public Sub SetBaseDuration(DurationMs As Long) baseDurationMs = DurationMs DrawClock End Sub ' Rimuove tutti i segmenti registrati. Public Sub ClearSegments If segments.IsInitialized = False Then segments.Initialize segments.Clear hasActiveSegment = False activeDurationMs = 0 DrawClock End Sub ' Aggiunge un segmento concluso. Public Sub AddSegment(DurationMs As Long, SegmentColor As Int, IsPause As Boolean) If DurationMs <= 0 Then Return Dim segment As Map segment.Initialize segment.Put("duration", DurationMs) segment.Put("color", SegmentColor) segment.Put("pause", IsPause) segments.Add(segment) DrawClock End Sub ' Imposta il segmento in corso, non ancora concluso. Public Sub SetActiveSegment(DurationMs As Long, SegmentColor As Int, IsPause As Boolean) activeDurationMs = Max(0, DurationMs) activeColor = SegmentColor activeIsPause = IsPause hasActiveSegment = activeDurationMs > 0 DrawClock End Sub Public Sub ClearActiveSegment hasActiveSegment = False activeDurationMs = 0 DrawClock End Sub ' Imposta la dimensione dell'orologio come percentuale della larghezza del pannello Public Sub SetClockSize(PercentageOfWidth As Float) clockDiameter = pnlClock.Width * PercentageOfWidth / 100 centerX = pnlClock.Width / 2 centerY = pnlClock.Height / 2 DrawClock End Sub ' Imposta lo spessore delle varie linee Public Sub SetStrokeWidths(quadrantWidth As Float, hourTickWidth As Float, minuteTickWidth As Float, intervalArcWidth As Float, hourHandWidth As Float, minuteHandWidth As Float) quadrantStrokeWidth = quadrantWidth hourTickStrokeWidth = hourTickWidth minuteTickStrokeWidth = minuteTickWidth intervalArcStrokeWidth = intervalArcWidth hourHandStrokeWidth = hourHandWidth minuteHandStrokeWidth = minuteHandWidth DrawClock End Sub ' Cancella il canvas riempiendolo con un colore specifico Private Sub ClearCanvas(color As Int) cvsClock.DrawRect(cvsClock.TargetRect, color, True, 0) cvsClock.Invalidate End Sub ' Disegna l'orologio Public Sub DrawClock cvsClock.Initialize(pnlClock) ' Cancella il canvas ClearCanvas(Colors.White) ' Disegna il cerchio esterno cvsClock.DrawCircle(centerX, centerY, clockDiameter / 2, Colors.Black, False, quadrantStrokeWidth) ' Disegna i segmenti di lavoro / pausa / straordinario DrawSegments ' Disegna le tacche delle ore e dei minuti DrawTicks ' Disegna le lancette Dim now As Long = DateTime.Now Dim Hours As Int = DateTime.GetHour(now) Mod 12 Dim Minutes As Int = DateTime.GetMinute(now) Dim Seconds As Int = DateTime.GetSecond(now) ' Lancetta ore Dim HourAngle As Float = -90 + Hours * 30 + Minutes / 2 DrawHand(centerX, centerY, clockDiameter * 0.25, HourAngle, hourHandStrokeWidth, Colors.Black) ' Lancetta minuti Dim MinuteAngle As Float = -90 + Minutes * 6 DrawHand(centerX, centerY, clockDiameter * 0.4, MinuteAngle, minuteHandStrokeWidth, Colors.Blue) ' Lancetta secondi Dim SecondAngle As Float = -90 + Seconds * 6 DrawHand(centerX, centerY, clockDiameter * 0.45, SecondAngle, 2dip, Colors.Red) ' Aggiorna il pannello pnlClock.Invalidate End Sub Private Sub DrawSegments If segments.IsInitialized = False Then Return Dim totalPauseMs As Long = 0 Dim totalRecordedMs As Long = 0 For Each segment As Map In segments Dim duration As Long = segment.Get("duration") totalRecordedMs = totalRecordedMs + duration If segment.Get("pause") = True Then totalPauseMs = totalPauseMs + duration Next If hasActiveSegment Then totalRecordedMs = totalRecordedMs + activeDurationMs If activeIsPause Then totalPauseMs = totalPauseMs + activeDurationMs End If Dim totalDisplayMs As Long = Max(baseDurationMs, totalRecordedMs) If totalDisplayMs <= 0 Then Return Dim startAngle As Float = -90 Dim radius As Float = clockDiameter / 2 - 22dip For Each segment As Map In segments Dim sweepAngle As Float = 360 * segment.Get("duration") / totalDisplayMs DrawPieSegment(startAngle, sweepAngle, segment.Get("color"), radius) startAngle = startAngle + sweepAngle Next If hasActiveSegment Then Dim activeSweepAngle As Float = 360 * activeDurationMs / totalDisplayMs DrawPieSegment(startAngle, activeSweepAngle, activeColor, radius) End If End Sub Private Sub DrawPieSegment(startAngle As Float, sweepAngle As Float, color As Int, radius As Float) If sweepAngle <= 0 Then Return Dim steps As Int = Max(2, Ceil(sweepAngle / 4)) Dim path As B4XPath path.Initialize(centerX, centerY) For i = 0 To steps Dim angle As Float = startAngle + sweepAngle * i / steps Dim x As Float = centerX + radius * CosD(angle) Dim y As Float = centerY + radius * SinD(angle) path.LineTo(x, y) Next path.LineTo(centerX, centerY) cvsClock.DrawPath(path, color, True, 0) End Sub ' Disegna una singola lancetta Private Sub DrawHand(x As Float, y As Float, length As Float, angle As Float, width As Float, color As Int) Dim endX As Float = x + length * CosD(angle) Dim endY As Float = y + length * SinD(angle) cvsClock.DrawLine(x, y, endX, endY, color, width) End Sub ' Disegna le tacche delle ore e dei minuti Private Sub DrawTicks For i = 0 To 59 Dim angle As Float = -90 + i * 6 Dim startX As Float Dim startY As Float Dim endX As Float Dim endY As Float If i Mod 5 = 0 Then ' Tacca delle ore startX = centerX + (clockDiameter / 2 - 20dip) * CosD(angle) startY = centerY + (clockDiameter / 2 - 20dip) * SinD(angle) endX = centerX + (clockDiameter / 2 - 5dip) * CosD(angle) endY = centerY + (clockDiameter / 2 - 5dip) * SinD(angle) cvsClock.DrawLine(startX, startY, endX, endY, Colors.Black, hourTickStrokeWidth) Else ' Tacca dei minuti startX = centerX + (clockDiameter / 2 - 10dip) * CosD(angle) startY = centerY + (clockDiameter / 2 - 10dip) * SinD(angle) endX = centerX + (clockDiameter / 2 - 5dip) * CosD(angle) endY = centerY + (clockDiameter / 2 - 5dip) * SinD(angle) cvsClock.DrawLine(startX, startY, endX, endY, Colors.Black, minuteTickStrokeWidth) End If Next End Sub ' Aggiorna l'orologio ogni secondo Public Sub StartClock Dim timer As Timer timer.Initialize("timer", 1000) timer.Enabled = True End Sub ' Evento del timer per aggiornare l'orologio Private Sub timer_Tick DrawClock End Sub