Create skeleton of main activities view UI in client

This commit is contained in:
Camden Dixie O'Brien 2025-02-27 22:08:16 +00:00
parent 6b53dd1526
commit 5038a24539
7 changed files with 147 additions and 34 deletions

View File

@ -9,6 +9,14 @@ project(
add_project_arguments('-w', language: 'c') add_project_arguments('-w', language: 'c')
gtk_dep = dependency('gtk4') gtk_dep = dependency('gtk4')
gnome = import('gnome')
resources = gnome.compile_resources(
'resources',
'resources.gresource.xml',
source_dir: '.',
c_name: 'resources'
)
subdir('src') subdir('src')
subdir('tests') subdir('tests')

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/sh/wip/studysystemclient">
<file>styles.css</file>
</gresource>
</gresources>

View File

@ -0,0 +1,86 @@
namespace StudySystemClient {
private struct Activity {
public string subject;
public ActivityType type;
}
enum ActivityType {
EXERCISES,
READING;
public string to_string() {
switch (this) {
case EXERCISES:
return "Exercises";
case READING:
return "Reading";
default:
return "Invalid activity type";
}
}
}
public class ActivitiesView : Gtk.Box {
public ActivitiesView() {
margin_top = margin_bottom = margin_start = margin_end = 0;
var scrolled_window = new Gtk.ScrolledWindow();
scrolled_window.hscrollbar_policy = Gtk.PolicyType.NEVER;
scrolled_window.vexpand = true;
var card_container = new Gtk.FlowBox();
card_container.homogeneous = true;
card_container.min_children_per_line = 1;
card_container.max_children_per_line = 1;
card_container.selection_mode = Gtk.SelectionMode.NONE;
card_container.valign = Gtk.Align.START;
scrolled_window.add_css_class("card-container");
var activities = new Activity[] {
{ "Linguistics", ActivityType.EXERCISES },
{ "Cybernetics", ActivityType.EXERCISES },
{ "Linguistics", ActivityType.READING },
{ "Physics", ActivityType.READING },
{ "Cybernetics", ActivityType.READING },
{ "Physics", ActivityType.EXERCISES },
};
foreach (var activity in activities)
card_container.append(new ActivityCard(activity));
scrolled_window.set_child(card_container);
this.append(scrolled_window);
}
}
private class ActivityCard : Gtk.Frame {
public ActivityCard(Activity activity) {
add_css_class("card");
var content = new Gtk.Box(Gtk.Orientation.HORIZONTAL, 12);
var text = new Gtk.Box(Gtk.Orientation.VERTICAL, 6);
text.hexpand = true;
var subject = new Gtk.Label(activity.subject);
subject.halign = Gtk.Align.START;
subject.add_css_class("activity-subject");
text.append(subject);
var type = new Gtk.Label(activity.type.to_string());
type.halign = Gtk.Align.START;
text.append(type);
content.append(text);
var button
= new Gtk.Button.from_icon_name("appointment-new-symbolic");
button.vexpand = false;
button.valign = Gtk.Align.CENTER;
button.set_tooltip_text("Log session");
button.add_css_class("log-session-button");
content.append(button);
set_child(content);
}
}
}

View File

@ -1,5 +1,3 @@
using Gtk;
namespace StudySystemClient { namespace StudySystemClient {
public class App : Gtk.Application { public class App : Gtk.Application {
public App() { public App() {
@ -8,11 +6,18 @@ namespace StudySystemClient {
protected override void activate() { protected override void activate() {
try { try {
var connection = new Connection(Config.CERT_DIR); var css_provider = new Gtk.CssProvider();
new MainWindow(this, connection); css_provider.load_from_resource(
"/sh/wip/studysystemclient/styles.css");
Gtk.StyleContext.add_provider_for_display(
Gdk.Display.get_default(),
css_provider,
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
new MainWindow(this, new Connection(Config.CERT_DIR));
} catch (Error e) { } catch (Error e) {
stderr.printf("Failed to initialize connection: %s\n", stderr.printf("Failed to initialize: %s\n", e.message);
e.message); return;
} }
} }
} }

View File

@ -1,10 +1,6 @@
namespace StudySystemClient { namespace StudySystemClient {
const string title = "Study System Client";
public class MainWindow : Gtk.ApplicationWindow { public class MainWindow : Gtk.ApplicationWindow {
private Connection connection; private Connection connection;
private Gtk.Button send_button;
private Gtk.Label response_label;
public MainWindow(Gtk.Application app, Connection connection) { public MainWindow(Gtk.Application app, Connection connection) {
Object(application: app); Object(application: app);
@ -13,30 +9,15 @@ namespace StudySystemClient {
default_height = 580; default_height = 580;
this.connection = connection; this.connection = connection;
connection.received.connect((msg) => {
var der = Der.decode(msg) as Der.Choice;
var str = der.value as Der.Utf8String;
response_label.label = "Response: " + str.value;
});
var box = new Gtk.Box(Gtk.Orientation.VERTICAL, 10); var header_bar = new Gtk.HeaderBar();
box.margin_start = 10; var title = new Gtk.Label("Study System Client");
box.margin_end = 10; title.add_css_class("title");
box.margin_top = 10; header_bar.title_widget = title;
box.margin_bottom = 10; set_titlebar(header_bar);
send_button = new Gtk.Button.with_label("Send"); var activities_view = new ActivitiesView();
send_button.clicked.connect(() => { set_child(activities_view);
var msg = new Der.Choice(0, new Der.Null());
connection.send(msg.encode());
});
box.append(send_button);
response_label = new Gtk.Label("");
response_label.wrap = true;
box.append(response_label);
set_child(box);
present(); present();
} }

View File

@ -10,12 +10,14 @@ configure_file(
lib = library( lib = library(
'study-system-client', 'study-system-client',
sources: files( sources: files(
'activities_view.vala',
'connection.vala', 'connection.vala',
'der.vala', 'der.vala',
'main_window.vala', 'main_window.vala',
), ) + resources,
dependencies: [gtk_dep], dependencies: [gtk_dep],
vala_vapi: 'study-system-client.vapi' vala_vapi: 'study-system-client.vapi',
vala_args: ['--pkg', 'gtk4']
) )
lib_dep = declare_dependency( lib_dep = declare_dependency(
link_with: lib, link_with: lib,

25
client/styles.css Normal file
View File

@ -0,0 +1,25 @@
.card-container {
background-color: mix(@theme_base_color, @theme_bg_color, 0.7);
padding: 6px;
}
.card {
border: 1px solid alpha(@theme_fg_color, 0.2);
box-shadow: 0 1px 2px alpha(black, 0.15);
background-color: @theme_bg_color;
padding: 12px 16px;
}
.activity-subject {
font-weight: bold;
}
/*
* The visual center (i.e. the center of the clock) of the
* "appointment-new-symbolic" icon is slightly displaced from the
* center of the actual image, so tweak it here.
*/
.log-session-button image {
margin-top: -2px;
margin-left: 3px;
}