146 lines
6.8 KiB
C#
146 lines
6.8 KiB
C#
|
|
using Contime.model;
|
|||
|
|
|
|||
|
|
namespace Contime.view {
|
|||
|
|
public partial class MainForm : Form {
|
|||
|
|
// --- Events for the Controller ---
|
|||
|
|
public event Action WorkdayStartStopClicked;
|
|||
|
|
public event Action TaskStartStopClicked;
|
|||
|
|
public event Action GoOutOfContextClicked;
|
|||
|
|
public event Action ToggleTaskStatusClicked;
|
|||
|
|
public event Action AddTaskClicked;
|
|||
|
|
public event Action<long> TaskSelected;
|
|||
|
|
public event Action SaveContextClicked;
|
|||
|
|
public event Action ExportClicked;
|
|||
|
|
|
|||
|
|
// --- Properties for the Controller ---
|
|||
|
|
public string NewTaskName => txtNewTask.Text;
|
|||
|
|
public string ContextText { get => txtContext.Text; set => txtContext.Text = value; }
|
|||
|
|
|
|||
|
|
public MainForm() {
|
|||
|
|
InitializeComponent();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Handles full UI redraws, especially for the task list and summary data
|
|||
|
|
public void UpdateView(TimeTrackerModel model) {
|
|||
|
|
this.SuspendLayout();
|
|||
|
|
|
|||
|
|
UpdateTaskList(model);
|
|||
|
|
UpdateSummaryStats(model);
|
|||
|
|
UpdateTimersAndState(model); // Also call the lighter update to ensure consistency
|
|||
|
|
|
|||
|
|
this.ResumeLayout();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Handles high-frequency updates (timers, button states)
|
|||
|
|
public void UpdateTimersAndState(TimeTrackerModel model) {
|
|||
|
|
lblWorkdayTimer.Text = model.WorkdayTime.ToString(@"hh\:mm\:ss");
|
|||
|
|
lblTaskTimer.Text = model.ActiveTaskTime.ToString(@"hh\:mm\:ss");
|
|||
|
|
lblSelectedTaskTotalTime.Text = model.SelectedTaskTotalTime.ToString(@"hh\:mm\:ss");
|
|||
|
|
|
|||
|
|
lblStatus.Text = GetStatusText(model.CurrentState);
|
|||
|
|
lblStatus.ForeColor = GetStatusColor(model.CurrentState);
|
|||
|
|
|
|||
|
|
lblSelectedTask.Text = model.SelectedTask?.Name ?? "None";
|
|||
|
|
|
|||
|
|
// --- Update Button States and Text ---
|
|||
|
|
btnWorkdayStartStop.Text = (model.CurrentState == TimeTrackerModel.AppState.Idle) ? "Start Workday" : "Stop Workday";
|
|||
|
|
btnWorkdayStartStop.BackColor = (model.CurrentState == TimeTrackerModel.AppState.Idle) ? Color.FromArgb(0, 122, 204) : Color.FromArgb(192, 0, 0);
|
|||
|
|
|
|||
|
|
btnGoOutOfContext.Enabled = model.CurrentState != TimeTrackerModel.AppState.Idle;
|
|||
|
|
btnGoOutOfContext.Text = (model.CurrentState == TimeTrackerModel.AppState.OutOfContext) ? "Return to Work" : "Go Out of Context";
|
|||
|
|
|
|||
|
|
bool taskIsSelectedAndOpen = model.SelectedTask != null && model.SelectedTask.Status == "open";
|
|||
|
|
bool canStartTask = model.CurrentState == TimeTrackerModel.AppState.WorkdayActive && taskIsSelectedAndOpen;
|
|||
|
|
btnTaskStartStop.Enabled = canStartTask || model.CurrentState == TimeTrackerModel.AppState.TaskActive;
|
|||
|
|
btnTaskStartStop.Text = (model.CurrentState == TimeTrackerModel.AppState.TaskActive) ? "Stop Task" : "Start Task";
|
|||
|
|
btnTaskStartStop.BackColor = (model.CurrentState == TimeTrackerModel.AppState.TaskActive) ? Color.FromArgb(220, 53, 69) : Color.FromArgb(40, 167, 69);
|
|||
|
|
|
|||
|
|
btnToggleTaskStatus.Enabled = model.SelectedTask != null && model.CurrentState != TimeTrackerModel.AppState.TaskActive;
|
|||
|
|
btnToggleTaskStatus.Text = model.SelectedTask?.Status == "open" ? "Mark as Finished" : "Re-open Task";
|
|||
|
|
|
|||
|
|
lstTasks.Enabled = model.CurrentState != TimeTrackerModel.AppState.TaskActive;
|
|||
|
|
|
|||
|
|
// Show or hide the 'Out of Context' input fields
|
|||
|
|
bool outOfContext = model.CurrentState == TimeTrackerModel.AppState.OutOfContext;
|
|||
|
|
txtContext.Visible = outOfContext;
|
|||
|
|
btnSaveContext.Visible = outOfContext;
|
|||
|
|
if (outOfContext) ContextText = model.OutOfContextReason;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void UpdateSummaryStats(TimeTrackerModel model) {
|
|||
|
|
lblDayTotal.Text = $"Today: {model.DayTotal:hh\\:mm\\:ss}";
|
|||
|
|
lblWeekTotal.Text = $"This Week: {model.WeekTotal:hh\\:mm\\:ss}";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void LstTasks_SelectedIndexChanged(object sender, EventArgs e) {
|
|||
|
|
if (lstTasks.SelectedItems.Count > 0)
|
|||
|
|
TaskSelected?.Invoke((long)lstTasks.SelectedItems[0].Tag);
|
|||
|
|
else
|
|||
|
|
TaskSelected?.Invoke(-1);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void LstTasks_MouseDoubleClick(object sender, MouseEventArgs e) {
|
|||
|
|
if (lstTasks.SelectedItems.Count == 1) {
|
|||
|
|
var selectedItem = lstTasks.SelectedItems[0];
|
|||
|
|
string taskName = selectedItem.SubItems[0].Text;
|
|||
|
|
string totalTime = selectedItem.SubItems[1].Text;
|
|||
|
|
string status = selectedItem.SubItems[2].Text;
|
|||
|
|
|
|||
|
|
string message = $"Task: {taskName}\nTotal Time: {totalTime}\nStatus: {status}";
|
|||
|
|
MessageBox.Show(message, "Task Details", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void UpdateTaskList(TimeTrackerModel model) {
|
|||
|
|
lstTasks.SelectedIndexChanged -= LstTasks_SelectedIndexChanged; // Unsubscribe to prevent feedback loop
|
|||
|
|
|
|||
|
|
long? selectedTaskId = model.SelectedTask?.Id;
|
|||
|
|
lstTasks.Items.Clear();
|
|||
|
|
|
|||
|
|
foreach (var task in model.Tasks) {
|
|||
|
|
var item = new ListViewItem(new[] { task.Name, task.ElapsedTime.ToString(@"hh\:mm\:ss"), task.Status }) {
|
|||
|
|
Tag = task.Id,
|
|||
|
|
ForeColor = task.Status == "closed" ? Color.Gray : Color.White
|
|||
|
|
};
|
|||
|
|
lstTasks.Items.Add(item);
|
|||
|
|
if (task.Id == selectedTaskId) {
|
|||
|
|
item.Selected = true;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
lstTasks.SelectedIndexChanged += LstTasks_SelectedIndexChanged; // Re-subscribe
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private string GetStatusText(TimeTrackerModel.AppState state) {
|
|||
|
|
switch (state) {
|
|||
|
|
case TimeTrackerModel.AppState.Idle: return "Idle";
|
|||
|
|
case TimeTrackerModel.AppState.WorkdayActive: return "Workday Active";
|
|||
|
|
case TimeTrackerModel.AppState.TaskActive: return "Task in Progress";
|
|||
|
|
case TimeTrackerModel.AppState.OutOfContext: return "Out of Context";
|
|||
|
|
default: return "Unknown";
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private Color GetStatusColor(TimeTrackerModel.AppState state) {
|
|||
|
|
switch (state) {
|
|||
|
|
case TimeTrackerModel.AppState.Idle: return Color.White;
|
|||
|
|
case TimeTrackerModel.AppState.WorkdayActive: return Color.LightSkyBlue;
|
|||
|
|
case TimeTrackerModel.AppState.TaskActive: return Color.LightGreen;
|
|||
|
|
case TimeTrackerModel.AppState.OutOfContext: return Color.Orange;
|
|||
|
|
default: return Color.White;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void ShowNotification(string title, string message) {
|
|||
|
|
notifyIcon.BalloonTipTitle = title;
|
|||
|
|
notifyIcon.BalloonTipText = message;
|
|||
|
|
notifyIcon.ShowBalloonTip(3000);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void BtnExport_Click(object sender, EventArgs e) {
|
|||
|
|
ExportClicked?.Invoke();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|