Add refreshing indicator to ActivitiesView
This commit is contained in:
parent
17629f1db7
commit
019bdf9ce6
@ -2,15 +2,18 @@ namespace StudySystemClient {
|
|||||||
public class ActivitiesView : Gtk.Box {
|
public class ActivitiesView : Gtk.Box {
|
||||||
private Client client;
|
private Client client;
|
||||||
private Gtk.FlowBox card_container;
|
private Gtk.FlowBox card_container;
|
||||||
|
private RefreshingIndicator refreshing_indicator;
|
||||||
|
|
||||||
public ActivitiesView(Client client) {
|
public ActivitiesView(Client client) {
|
||||||
margin_top = margin_bottom = margin_start = margin_end = 0;
|
Object(orientation: Gtk.Orientation.VERTICAL,
|
||||||
this.client = client;
|
hexpand: true,
|
||||||
|
vexpand: true,
|
||||||
|
margin_top: 0,
|
||||||
|
margin_bottom: 0,
|
||||||
|
margin_start: 0,
|
||||||
|
margin_end: 0);
|
||||||
|
|
||||||
var scrolled_window = new Gtk.ScrolledWindow();
|
this.client = client;
|
||||||
scrolled_window.hscrollbar_policy = Gtk.PolicyType.NEVER;
|
|
||||||
scrolled_window.vexpand = true;
|
|
||||||
scrolled_window.add_css_class("card-container");
|
|
||||||
|
|
||||||
card_container = new Gtk.FlowBox();
|
card_container = new Gtk.FlowBox();
|
||||||
card_container.homogeneous = true;
|
card_container.homogeneous = true;
|
||||||
@ -18,9 +21,20 @@ namespace StudySystemClient {
|
|||||||
card_container.max_children_per_line = 1;
|
card_container.max_children_per_line = 1;
|
||||||
card_container.selection_mode = Gtk.SelectionMode.NONE;
|
card_container.selection_mode = Gtk.SelectionMode.NONE;
|
||||||
card_container.valign = Gtk.Align.START;
|
card_container.valign = Gtk.Align.START;
|
||||||
|
|
||||||
|
var scrolled_window = new Gtk.ScrolledWindow();
|
||||||
|
scrolled_window.hscrollbar_policy = Gtk.PolicyType.NEVER;
|
||||||
|
scrolled_window.hexpand = true;
|
||||||
|
scrolled_window.vexpand = true;
|
||||||
|
scrolled_window.add_css_class("card-container");
|
||||||
scrolled_window.set_child(card_container);
|
scrolled_window.set_child(card_container);
|
||||||
|
|
||||||
this.append(scrolled_window);
|
var overlay = new Gtk.Overlay();
|
||||||
|
overlay.hexpand = overlay.vexpand = true;
|
||||||
|
overlay.set_child(scrolled_window);
|
||||||
|
this.append(overlay);
|
||||||
|
|
||||||
|
refreshing_indicator = new RefreshingIndicator(overlay);
|
||||||
|
|
||||||
refresh.begin((obj, res) => {
|
refresh.begin((obj, res) => {
|
||||||
refresh.end(res);
|
refresh.end(res);
|
||||||
@ -28,6 +42,7 @@ namespace StudySystemClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async void refresh() {
|
private async void refresh() {
|
||||||
|
refreshing_indicator.show();
|
||||||
try {
|
try {
|
||||||
var activities = yield client.list_activities();
|
var activities = yield client.list_activities();
|
||||||
card_container.remove_all();
|
card_container.remove_all();
|
||||||
@ -40,6 +55,7 @@ namespace StudySystemClient {
|
|||||||
stderr.printf("Error refreshing activities: %s\n",
|
stderr.printf("Error refreshing activities: %s\n",
|
||||||
e.message);
|
e.message);
|
||||||
}
|
}
|
||||||
|
refreshing_indicator.hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void log_session(string subject, ActivityType type,
|
private async void log_session(string subject, ActivityType type,
|
||||||
@ -53,88 +69,38 @@ namespace StudySystemClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ActivityCard : Gtk.Frame {
|
private class RefreshingIndicator {
|
||||||
public signal void session_logged(string subject, ActivityType type,
|
private Gtk.Overlay overlay;
|
||||||
int minutes);
|
private Gtk.Frame frame;
|
||||||
|
|
||||||
public ActivityCard(Activity activity) {
|
public RefreshingIndicator(Gtk.Overlay overlay) {
|
||||||
add_css_class("card");
|
this.overlay = overlay;
|
||||||
|
|
||||||
var content = new Gtk.Box(Gtk.Orientation.HORIZONTAL, 12);
|
var label = new Gtk.Label("Refreshing");
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
var log_session_popover = new LogSessionPopover();
|
|
||||||
log_session_popover.set_parent(button);
|
|
||||||
button.clicked.connect(() => log_session_popover.popup());
|
|
||||||
log_session_popover.session_logged.connect((minutes) => {
|
|
||||||
session_logged(activity.subject, activity.type, minutes);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class LogSessionPopover : Gtk.Popover {
|
|
||||||
public signal void session_logged(int minutes);
|
|
||||||
|
|
||||||
private const int DEFAULT_LENGTH = 30;
|
|
||||||
|
|
||||||
private Gtk.SpinButton input;
|
|
||||||
|
|
||||||
public LogSessionPopover() {
|
|
||||||
var content = new Gtk.Box(Gtk.Orientation.HORIZONTAL, 6);
|
|
||||||
|
|
||||||
var label = new Gtk.Label("Minutes");
|
|
||||||
label.halign = Gtk.Align.START;
|
label.halign = Gtk.Align.START;
|
||||||
|
|
||||||
|
var spinner = new Gtk.Spinner();
|
||||||
|
spinner.start();
|
||||||
|
|
||||||
|
var content = new Gtk.Box(Gtk.Orientation.HORIZONTAL, 6);
|
||||||
|
content.margin_top = content.margin_bottom
|
||||||
|
= content.margin_start = content.margin_end = 12;
|
||||||
content.append(label);
|
content.append(label);
|
||||||
|
content.append(spinner);
|
||||||
|
|
||||||
var adjustment
|
frame = new Gtk.Frame(null);
|
||||||
= new Gtk.Adjustment(DEFAULT_LENGTH, 10, 480, 10, 10, 0);
|
frame.halign = Gtk.Align.CENTER;
|
||||||
input = new Gtk.SpinButton(adjustment, 1, 0);
|
frame.valign = Gtk.Align.START;
|
||||||
input.numeric = true;
|
frame.add_css_class("osd");
|
||||||
content.append(input);
|
frame.set_child(content);
|
||||||
|
|
||||||
var button = new Gtk.Button.from_icon_name("emblem-ok-symbolic");
|
|
||||||
button.halign = Gtk.Align.END;
|
|
||||||
button.set_tooltip_text("Submit");
|
|
||||||
button.add_css_class("suggested-action");
|
|
||||||
button.clicked.connect(submit);
|
|
||||||
content.append(button);
|
|
||||||
|
|
||||||
set_child(content);
|
|
||||||
|
|
||||||
closed.connect(reset);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void submit() {
|
public void show() {
|
||||||
session_logged((int)input.value);
|
overlay.add_overlay(frame);
|
||||||
reset();
|
|
||||||
popdown();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void reset() {
|
public void hide() {
|
||||||
input.value = DEFAULT_LENGTH;
|
overlay.remove_overlay(frame);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
86
client/src/activity_card.vala
Normal file
86
client/src/activity_card.vala
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
namespace StudySystemClient {
|
||||||
|
public class ActivityCard : Gtk.Frame {
|
||||||
|
public signal void session_logged(string subject, ActivityType type,
|
||||||
|
int minutes);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
var log_session_popover = new LogSessionPopover();
|
||||||
|
log_session_popover.set_parent(button);
|
||||||
|
button.clicked.connect(() => log_session_popover.popup());
|
||||||
|
log_session_popover.session_logged.connect((minutes) => {
|
||||||
|
session_logged(activity.subject, activity.type, minutes);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class LogSessionPopover : Gtk.Popover {
|
||||||
|
public signal void session_logged(int minutes);
|
||||||
|
|
||||||
|
private const int DEFAULT_LENGTH = 30;
|
||||||
|
|
||||||
|
private Gtk.SpinButton input;
|
||||||
|
|
||||||
|
public LogSessionPopover() {
|
||||||
|
var content = new Gtk.Box(Gtk.Orientation.HORIZONTAL, 6);
|
||||||
|
|
||||||
|
var label = new Gtk.Label("Minutes");
|
||||||
|
label.halign = Gtk.Align.START;
|
||||||
|
content.append(label);
|
||||||
|
|
||||||
|
var adjustment
|
||||||
|
= new Gtk.Adjustment(DEFAULT_LENGTH, 10, 480, 10, 10, 0);
|
||||||
|
input = new Gtk.SpinButton(adjustment, 1, 0);
|
||||||
|
input.numeric = true;
|
||||||
|
content.append(input);
|
||||||
|
|
||||||
|
var button = new Gtk.Button.from_icon_name("emblem-ok-symbolic");
|
||||||
|
button.halign = Gtk.Align.END;
|
||||||
|
button.set_tooltip_text("Submit");
|
||||||
|
button.add_css_class("suggested-action");
|
||||||
|
button.clicked.connect(submit);
|
||||||
|
content.append(button);
|
||||||
|
|
||||||
|
set_child(content);
|
||||||
|
|
||||||
|
closed.connect(reset);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void submit() {
|
||||||
|
session_logged((int)input.value);
|
||||||
|
reset();
|
||||||
|
popdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void reset() {
|
||||||
|
input.value = DEFAULT_LENGTH;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -10,8 +10,9 @@ configure_file(
|
|||||||
lib = library(
|
lib = library(
|
||||||
'study-system-client',
|
'study-system-client',
|
||||||
sources: files(
|
sources: files(
|
||||||
'activity.vala',
|
|
||||||
'activities_view.vala',
|
'activities_view.vala',
|
||||||
|
'activity.vala',
|
||||||
|
'activity_card.vala',
|
||||||
'client.vala',
|
'client.vala',
|
||||||
'connection.vala',
|
'connection.vala',
|
||||||
'der.vala',
|
'der.vala',
|
||||||
|
@ -23,3 +23,12 @@
|
|||||||
margin-top: -2px;
|
margin-top: -2px;
|
||||||
margin-left: 3px;
|
margin-left: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Couldn't find a built-in way to get the common OSD overlay style of
|
||||||
|
* rounding the bottom corners but not the top ones, so doing this
|
||||||
|
* myself with this CSS rule.
|
||||||
|
*/
|
||||||
|
overlay > frame.osd {
|
||||||
|
border-radius: 0 0 8px 8px;
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user