5a96a696b1
- 펌웨어(program), C# 대시보드(TestProgram), 시뮬레이터(Simulator), 프로토콜/문서(Protocol, doc) 전체를 단일 저장소로 통합 - program 폴더의 별도 git 저장소를 제거하고 통합 저장소에 흡수 - 빌드 산출물(program/build, bin/obj, *.o/.elf/.bin/.hex 등) .gitignore 처리 - 사내 Synology NAS Git 원격 연결 예정 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
133 lines
4.8 KiB
C#
133 lines
4.8 KiB
C#
using System;
|
|
using System.Windows;
|
|
using System.Windows.Controls;
|
|
using System.Windows.Input;
|
|
using System.Windows.Media;
|
|
using ErvDashboard.Model;
|
|
|
|
namespace ErvDashboard
|
|
{
|
|
// 스마트수면 시간설정 팝업 (원형 다이얼). 시작/종료 시각을 설정 → 적용 시 메인이 종료 시각에 자동 해제 예약.
|
|
// 대시보드 전용(ERV 프로토콜 무관). 시각은 자정 기준 분(0~1439, 30분 단위).
|
|
public partial class SmartSleepWindow : Window
|
|
{
|
|
readonly MainWindow _owner;
|
|
readonly DashboardState _state;
|
|
|
|
const double CX = 130, CY = 130, R = 104; // DialCanvas(260x260) 중심/반지름
|
|
|
|
int _startMin, _endMin;
|
|
bool _dragStart, _dragEnd, _updating;
|
|
|
|
public SmartSleepWindow(MainWindow owner, DashboardState state)
|
|
{
|
|
InitializeComponent();
|
|
_owner = owner;
|
|
_state = state;
|
|
_startMin = state.SleepStartMin;
|
|
_endMin = state.SleepEndMin;
|
|
|
|
for (int m = 0; m < 1440; m += 30)
|
|
{
|
|
StartCombo.Items.Add(new ComboBoxItem { Content = DashboardState.FmtTime(m), Tag = m });
|
|
EndCombo.Items.Add(new ComboBoxItem { Content = DashboardState.FmtTime(m), Tag = m });
|
|
}
|
|
StartCombo.SelectionChanged += StartCombo_Changed;
|
|
EndCombo.SelectionChanged += EndCombo_Changed;
|
|
|
|
UpdateDial();
|
|
}
|
|
|
|
// ===== 다이얼/콤보 갱신 =====
|
|
void UpdateDial()
|
|
{
|
|
_updating = true;
|
|
SleepArc.Data = BuildArc(_startMin, _endMin);
|
|
PositionHandle(StartHandle, _startMin);
|
|
PositionHandle(EndHandle, _endMin);
|
|
StartRun.Text = DashboardState.FmtTime(_startMin);
|
|
EndRun.Text = DashboardState.FmtTime(_endMin);
|
|
StartCombo.SelectedIndex = _startMin / 30;
|
|
EndCombo.SelectedIndex = _endMin / 30;
|
|
_updating = false;
|
|
}
|
|
|
|
Geometry BuildArc(int s, int e)
|
|
{
|
|
Point p0 = Polar(s / 1440.0 * 360.0);
|
|
Point p1 = Polar(e / 1440.0 * 360.0);
|
|
double sweep = ((e - s + 1440) % 1440) / 1440.0 * 360.0;
|
|
var fig = new System.Windows.Media.PathFigure { StartPoint = p0, IsClosed = false };
|
|
fig.Segments.Add(new ArcSegment(p1, new Size(R, R), 0, sweep > 180.0, SweepDirection.Clockwise, true));
|
|
var g = new PathGeometry();
|
|
g.Figures.Add(fig);
|
|
return g;
|
|
}
|
|
|
|
static Point Polar(double angleDeg) // 0°=위, 시계방향
|
|
{
|
|
double t = angleDeg * Math.PI / 180.0;
|
|
return new Point(CX + R * Math.Sin(t), CY - R * Math.Cos(t));
|
|
}
|
|
|
|
static void PositionHandle(FrameworkElement h, int min)
|
|
{
|
|
Point p = Polar(min / 1440.0 * 360.0);
|
|
Canvas.SetLeft(h, p.X - h.Width / 2);
|
|
Canvas.SetTop(h, p.Y - h.Height / 2);
|
|
}
|
|
|
|
static int AngleToMin(Point p)
|
|
{
|
|
double ang = Math.Atan2(p.X - CX, -(p.Y - CY)) * 180.0 / Math.PI; // 0=위, 시계방향
|
|
if (ang < 0) ang += 360;
|
|
int min = (int)Math.Round(ang / 360.0 * 1440.0 / 30.0) * 30;
|
|
return ((min % 1440) + 1440) % 1440;
|
|
}
|
|
|
|
// ===== 드래그 =====
|
|
void StartHandle_Down(object sender, MouseButtonEventArgs e) { _dragStart = true; StartHandle.CaptureMouse(); e.Handled = true; }
|
|
void EndHandle_Down(object sender, MouseButtonEventArgs e) { _dragEnd = true; EndHandle.CaptureMouse(); e.Handled = true; }
|
|
|
|
void Handle_Move(object sender, MouseEventArgs e)
|
|
{
|
|
if (!_dragStart && !_dragEnd) return;
|
|
int min = AngleToMin(e.GetPosition(DialCanvas));
|
|
if (_dragStart) _startMin = min; else _endMin = min;
|
|
UpdateDial();
|
|
}
|
|
|
|
void Handle_Up(object sender, MouseButtonEventArgs e)
|
|
{
|
|
_dragStart = _dragEnd = false;
|
|
(sender as UIElement)?.ReleaseMouseCapture();
|
|
}
|
|
|
|
// ===== 콤보 =====
|
|
void StartCombo_Changed(object sender, SelectionChangedEventArgs e)
|
|
{
|
|
if (_updating || StartCombo.SelectedItem is not ComboBoxItem it) return;
|
|
_startMin = (int)it.Tag;
|
|
UpdateDial();
|
|
}
|
|
|
|
void EndCombo_Changed(object sender, SelectionChangedEventArgs e)
|
|
{
|
|
if (_updating || EndCombo.SelectedItem is not ComboBoxItem it) return;
|
|
_endMin = (int)it.Tag;
|
|
UpdateDial();
|
|
}
|
|
|
|
// ===== 버튼 =====
|
|
void Apply_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
_state.SleepStartMin = _startMin;
|
|
_state.SleepEndMin = _endMin;
|
|
_owner.ApplySmartSleep();
|
|
Close();
|
|
}
|
|
|
|
void Close_Click(object sender, RoutedEventArgs e) => Close();
|
|
}
|
|
}
|