Skip to content
This repository has been archived by the owner on Feb 16, 2023. It is now read-only.

W8G05A #11

Open
wants to merge 14 commits into
base: main
Choose a base branch
from
139 changes: 139 additions & 0 deletions W8G05A/TUITodo/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
using System.Linq.Expressions;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Kompakt & effektív házi. Egy dologba tudok belekötni: A felelősségek szétválasztása. Az MVVM-et és a MVC-t nem véletlen találták ki. Jelen esetben a programod 1:1-ben függ a konzolos GUI rendszeredtől és a komponenseid így nem Single Responsible-ök, mert logikát csinálnak ÉS megjelenítenek. Jelen egyetemi házi keretében Okés, de tipik nem így szokás a való életben.

using System.Text;
using Terminal.Gui;
using Terminal.Gui.Trees;
using TUITodo.Utils;
using TUITodo.Views;

namespace TUITodo
{
internal class Program
{
#region Views
public static View MainWindow { get; } = new Window("Task list")
{
X = 0,
Y = 1,
Width = Dim.Fill(),
Height = Dim.Fill() - 3
};


public static TaskListView TaskListView { get; } = new()
{
X = 1,
Y = 1,
Width = Dim.Fill(),
Height = Dim.Fill(2) - 2
};

public static EditorView EditorView { get; } = new()
{
X = 1,
Y = 1,
Width = Dim.Fill(),
Height = Dim.Fill() - 2
};


public static Label statusBarMessage { get; } = new()
{
X = 1,
Y = Pos.Bottom(MainWindow),
Width = Dim.Fill(),
Height = 2,
};

#endregion


public static async void DisplayStatusNotification(string message, int expireSeconds = 2)
{
statusBarMessage.Text = message;
if(expireSeconds > 0)
{
await Task.Delay(TimeSpan.FromSeconds(expireSeconds));
statusBarMessage.Text = "";
}

}

static StatusBar? activeStatusbar;
static void SetStatusBar(StatusBar statusBar)
{
Application.Top.Remove(activeStatusbar);
activeStatusbar = statusBar;
Application.Top.Add(activeStatusbar);
}


private static void SwitchToView(View view)
{
MainWindow.RemoveAll();
MainWindow.Add(view);
}

public static void EnterEditMode(TodoItem editedItem)
{
SwitchToView(EditorView);
SetStatusBar(EditorView.statusBar);
EditorView.StartEditing(editedItem);
}

public static void ShowTaskListView()
{
SetStatusBar(TaskListView.statusBar);
SwitchToView(TaskListView);
}

static void Main()
{

Application.Init();

Application.MainLoop.Invoke(async () =>
{
await TaskListView.LoadSavedTasks();
});

#region Color scheme, style setup
Colors.Base.Normal = Application.Driver.MakeAttribute(Color.Green, Color.Black);
Colors.Base.HotNormal = Application.Driver.MakeAttribute(Color.Brown, Color.Black);

#endregion

#region MenuBar

var menu = new MenuBar(new MenuBarItem[] {
new MenuBarItem ("_File", new MenuItem [] {
new MenuItem ("_Quit", "", () => {
Application.RequestStop();
}),
new MenuItem ("_Save", "", () => {
SaveTasks();
})
}),
});

#endregion
//TaskListView.LoadSavedTasks(savedTodos);
ShowTaskListView();

Application.Top.Add(menu, MainWindow, statusBarMessage);

Application.Driver.SetCursorVisibility(CursorVisibility.Invisible);
Application.Run();

Application.Shutdown();
}

public static void SaveTasks()
{
DisplayStatusNotification("Saving...", 0);
Task.Run(async () => {
await TaskListView.SaveTasks();
DisplayStatusNotification("Saved");
});
}
}
}
14 changes: 14 additions & 0 deletions W8G05A/TUITodo/TUITodo.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Terminal.Gui" Version="1.8.2" />
</ItemGroup>

</Project>
97 changes: 97 additions & 0 deletions W8G05A/TUITodo/TodoItem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
using System.Xml.Linq;
using Terminal.Gui.Trees;

namespace TUITodo
{


internal record class TodoItem : ITreeNode
{
private const string Unchecked = "O";
private const string Checked = "X";

public TodoItem? parentTask { get; protected set; }

public bool Done { get; protected set; }
[JsonInclude]
public string name;
[JsonInclude]
public string description;

public List<TodoItem> Subtasks { get; set; }
public TodoItem(string name, string description = "") : this(name, description, new List<TodoItem>()) { }

public TodoItem(string name, string description, List<TodoItem> subtasks)
{
this.Done = false;
this.name = name;
this.description = description;

this.Subtasks = new();
subtasks.ForEach(AddSubtask);

}

[JsonConstructor]
public TodoItem()
{
Done = false; ;
this.name = "";
this.description = "";
Subtasks = new List<TodoItem>();
}

[JsonIgnore]
public string Text
{
get => $"{(Done ? Checked : Unchecked)} {name}"; set { name = value; }
}

[JsonIgnore]
public IList<ITreeNode> Children => Subtasks.Cast<ITreeNode>().ToList();

[JsonIgnore]
public object Tag
{
get => name; set { name = (string)value; }
}

/// <param name="chainToSubtasks"> Make every subtask recursively inherit the done value</param>
public void ToggleDone(bool chainToSubtasks = true)
{
SetDone(!Done, chainToSubtasks);
}

/// <param name="chainToSubtasks"> Make every subtask recursively inherit the done value</param>
public void SetDone(bool value, bool chainToSubtasks = true)
{
Done = value;
if (chainToSubtasks)
Subtasks.ForEach(t => t.SetDone(value, chainToSubtasks));

//complete parent task if all of its subtasks are done
if (parentTask != null)
parentTask.SetDone(parentTask.Subtasks.All(t => t.Done), chainToSubtasks:false);

}

public void AddSubtask(TodoItem task)
{
Subtasks.Add(task);
task.parentTask = this;
}

public void RemoveSubtask(TodoItem task)
{
task.parentTask = null;
Subtasks.Remove(task);
}
}
}
54 changes: 54 additions & 0 deletions W8G05A/TUITodo/Utils/TodoItemSerializer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Diagnostics;

namespace TUITodo.Utils
{
internal static class TodoItemSerializer
{
static JsonSerializerOptions options = new()
{
ReferenceHandler = ReferenceHandler.Preserve,
WriteIndented = true
};

public static async Task Serialize(IList<TodoItem> items, string path = "todos.json")
{
string json = JsonSerializer.Serialize(items, options);
//Trace.WriteLine(json);
using (StreamWriter writer = File.CreateText(path))
{
await writer.WriteAsync(json);
Program.DisplayStatusNotification($"Saved");
}
}

public async static Task<List<TodoItem>?> Deserialize(string path = "todos.json")
{
if (!File.Exists(path)) return null;

try
{
using (StreamReader sr = new StreamReader(path))
{
string json = await sr.ReadToEndAsync();

return JsonSerializer.Deserialize<List<TodoItem>>(json, options);

}
}
catch (Exception e)
{
Program.DisplayStatusNotification($"Could not deserialize: {e}");
return null;
}

}

}
}
Loading