~tristan957/harvest-almanac

2010865506ba1f4e2ef4f72e5d84041b7b8fdb89 — Tristan Partin 1 year, 11 months ago 9a1a093
harvest-almanac: removed view switchers in favor of leaflets
M data/hal-resources.gresource.xml => data/hal-resources.gresource.xml +2 -1
@@ 1,4 1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<?xml version="1.0" encoding="UTF-8" ?>
<gresources>
	<gresource prefix="/io/partin/tristan/HarvestAlmanac">
		<file preprocess="xml-stripblanks">ui/hal-preferences-window.ui</file>


@@ 6,5 6,6 @@
		<file preprocess="xml-stripblanks">ui/hal-time-entry.ui</file>
		<file preprocess="xml-stripblanks">ui/hal-time-tracker.ui</file>
		<file preprocess="xml-stripblanks">ui/hal-window.ui</file>
		<file compressed="true">ui/style.css</file>
	</gresource>
</gresources>

M data/ui/hal-window.ui => data/ui/hal-window.ui +127 -64
@@ 1,8 1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<?xml version="1.0" encoding="UTF-8" ?>
<!-- Generated with glade 3.22.0 -->
<interface>
  <requires lib="gtk+" version="3.20"/>
  <requires lib="libhandy" version="0.0"/>
  <requires lib="gtk+" version="3.20" />
  <requires lib="libhandy" version="0.0" />
  <object class="GtkSizeGroup">
    <property name="mode">horizontal</property>
    <widgets>
      <widget name="header_bar" />
      <widget name="sidebar" />
    </widgets>
  </object>
  <object class="GtkSizeGroup">
    <property name="mode">horizontal</property>
    <widgets>
      <widget name="sub_header_bar" />
      <widget name="stack" />
    </widgets>
  </object>
  <object class="HdyHeaderGroup" id="header_group">
    <headerbars>
      <headerbar name="header_bar" />
      <headerbar name="sub_header_bar" />
    </headerbars>
  </object>
  <object class="GtkPopoverMenu" id="actions_popover">
    <property name="can_focus">False</property>
    <child>


@@ 61,91 81,134 @@
    </child>
  </object>
  <template class="HalWindow" parent="GtkApplicationWindow">
    <property name="title">Harvest Almanac</property>
    <property name="can_focus">False</property>
    <child>
      <object class="GtkBox">
        <property name="visible">True</property>
        <property name="can_focus">False</property>
        <property name="orientation">vertical</property>
        <child>
          <object class="GtkStack" id="function_stack">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <property name="transition_type">slide-left-right</property>
          </object>
          <packing>
            <property name="expand">True</property>
            <property name="fill">True</property>
            <property name="position">0</property>
          </packing>
        </child>
        <child>
          <object class="HdyViewSwitcherBar" id="function_switcher_bar">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <property name="stack">function_stack</property>
            <property name="reveal">True</property>
          </object>
        </child>
      </object>
    </child>
    <child type="titlebar">
      <object class="HdyHeaderBar">
      <object class="HdyTitleBar">
        <property name="visible">True</property>
        <property name="centering_policy">strict</property>
        <property name="can_focus">False</property>
        <property name="show_close_button">True</property>
        <property name="title">Harvest Almanac</property>
        <child type="title">
          <object class="HdySqueezer" id="function_squeezer">
        <child>
          <object class="HdyLeaflet" id="header_leaflet">
            <property name="visible">True</property>
            <property name="transition-type">crossfade</property>
            <property name="mode-transition-type">slide</property>
            <property name="child-transition-type">slide</property>
            <property name="visible-child-name" bind-source="content_leaflet" bind-property="visible-child-name" bind-flags="sync-create" />
            <signal name="notify::visible-child" handler="header_leaflet_notify_visible_child_cb" swapped="no" object="HalWindow" />
            <signal name="notify::fold" handler="header_leaflet_notify_fold_cb" after="yes" swapped="no" object="HalWindow" />
            <child>
              <object class="HdyViewSwitcher" id="function_wide_switcher">
              <object class="GtkHeaderBar" id="header_bar">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="halign">center</property>
                <property name="policy">wide</property>
                <property name="stack">function_stack</property>
                <property name="title">Harvest Almanac</property>
                <property name="show_close_button">True</property>
                <child>
                  <object class="GtkMenuButton">
                    <property name="visible">True</property>
                    <property name="can_focus">True</property>
                    <property name="focus_on_click">False</property>
                    <property name="popover">actions_popover</property>
                    <child>
                      <object class="GtkImage">
                        <property name="visible">True</property>
                        <property name="can_focus">False</property>
                        <property name="icon_name">open-menu-symbolic</property>
                      </object>
                    </child>
                  </object>
                  <packing>
                    <property name="pack_type">end</property>
                  </packing>
                </child>
              </object>
              <packing>
                <property name="name">sidebar</property>
              </packing>
            </child>
            <child>
              <object class="HdyViewSwitcher" id="function_narrow_switcher">
              <object class="GtkSeparator">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="halign">center</property>
                <property name="policy">narrow</property>
                <property name="stack">function_stack</property>
                <property name="orientation">vertical</property>
                <style>
                  <class name="sidebar" />
                </style>
              </object>
            </child>
            <child>
              <object class="GtkLabel" id="title_label">
              <object class="GtkHeaderBar" id="sub_header_bar">
                <property name="visible">True</property>
                <property name="halign">center</property>
                <property name="label">Harvest Almanac</property>
                <style>
                  <class name="title"/>
                </style>
                <property name="expand">True</property>
                <property name="show_close_button">True</property>
                <child>
                  <object class="GtkButton" id="back_button">
                    <property name="can_focus">False</property>
                    <property name="receives_default">False</property>
                    <property name="valign">center</property>
                    <property name="use-underline">True</property>
                    <property name="visible" bind-source="header_leaflet" bind-property="folded" bind-flags="sync-create" />
                    <signal name="clicked" handler="back_button_clicked_cb" swapped="no" object="HalWindow" />
                    <style>
                      <class name="image-button" />
                    </style>
                    <child internal-child="accessible">
                      <object class="AtkObject" id="a11y-back-button">
                        <property name="accessible-name" translatable="yes">Back</property>
                      </object>
                    </child>
                    <child>
                      <object class="GtkImage">
                        <property name="visible">True</property>
                        <property name="can_focus">False</property>
                        <property name="icon_name">go-previous-symbolic</property>
                        <property name="icon_size">1</property>
                      </object>
                    </child>
                  </object>
                </child>
              </object>
              <packing>
                <property name="name">content</property>
              </packing>
            </child>
          </object>
        </child>
      </object>
    </child>
    <child>
      <object class="HdyLeaflet" id="content_leaflet">
        <property name="visible">True</property>
        <property name="can_focus">False</property>
        <property name="mode_transition_type">slide</property>
        <property name="child_transition_type">slide</property>
        <child>
          <object class="GtkMenuButton">
          <object class="GtkStackSidebar" id="sidebar">
            <property name="width_request">270</property>
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <property name="receives_default">True</property>
            <property name="popover">actions_popover</property>
            <child>
              <object class="GtkImage">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="icon_name">open-menu-symbolic</property>
              </object>
            </child>
            <property name="can_focus">False</property>
            <property name="stack">stack</property>
          </object>
          <packing>
            <property name="name">sidebar</property>
          </packing>
        </child>
        <child>
          <object class="GtkSeparator">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <property name="orientation">vertical</property>
            <style>
              <class name="sidebar" />
            </style>
          </object>
        </child>
        <child>
          <object class="GtkStack" id="stack">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <property name="transition_type">slide-up-down</property>
            <signal name="notify::visible-child" handler="stack_notify_visible_child_cb" after="yes" swapped="no" object="HalWindow" />
          </object>
          <packing>
            <property name="pack_type">end</property>
            <property name="name">content</property>
          </packing>
        </child>
      </object>

A data/ui/style.css => data/ui/style.css +8 -0
@@ 0,0 1,8 @@
stacksidebar list {
	border-left-width: 0px;
	border-right-width: 0px;
  }

  hdypaginator.horizontal .paginator-icon {
	-gtk-icon-transform: rotate(90deg);
  }

M harvest-almanac/hal-application.c => harvest-almanac/hal-application.c +10 -3
@@ 106,10 106,17 @@ hal_application_activate(GApplication *app)
			construct_client(self, access_token, account_id, contact_email);
			secret_password_free(access_token);
		}
	}

	g_object_set(gtk_settings_get_default(), "gtk-application-prefer-dark-theme",
		g_settings_get_boolean(self->settings, "prefer-dark-theme"), NULL);
		g_object_set(gtk_settings_get_default(), "gtk-application-prefer-dark-theme",
			g_settings_get_boolean(self->settings, "prefer-dark-theme"), NULL);

		g_autoptr(GtkCssProvider) css_provider = gtk_css_provider_new();
		gtk_css_provider_load_from_resource(
			css_provider, "/io/partin/tristan/HarvestAlmanac/ui/style.css");
		gtk_style_context_add_provider_for_screen(
			gtk_window_get_screen(GTK_WINDOW(priv->main_window)), GTK_STYLE_PROVIDER(css_provider),
			GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
	}

	gtk_window_present(GTK_WINDOW(priv->main_window));
}

M harvest-almanac/hal-window.c => harvest-almanac/hal-window.c +86 -69
@@ 13,91 13,107 @@
struct _HalWindow
{
	GtkApplicationWindow parent_instance;

	/**
	 * user_validated keeps the view switchers from being visible when the user is not validated.
	 */
	gboolean user_validated : 1;
};

typedef struct HalWindowPrivate
{
	GtkStack *function_stack;
	HdySqueezer *function_squeezer;
	HdyViewSwitcherBar *function_switcher_bar;
	HdyViewSwitcher *function_wide_switcher;
	HdyViewSwitcher *function_narrow_switcher;
	GtkLabel *title_label;
	HdyHeaderGroup *header_group;
	HdyLeaflet *content_leaflet;
	HdyLeaflet *header_leaflet;
	GtkHeaderBar *header_bar;
	GtkHeaderBar *sub_header_bar;
	GtkStack *stack;
	GtkStackSidebar *sidebar;
	GtkButton *back_button;
	HalTimeTracker *time_tracker;
	HalProfile *profile;
} HalWindowPrivate;

G_DEFINE_TYPE_WITH_PRIVATE(HalWindow, hal_window, GTK_TYPE_APPLICATION_WINDOW)

void
hal_window_show_content(HalWindow *self)
static void
update_header_bar_title(HalWindow *self)
{
	HalWindowPrivate *priv = hal_window_get_instance_private(self);

	/**
	 * There should probably be a check to make sure the access token is actually
	 * valid using the me endpoint.
	 */
	GtkWidget *child = gtk_stack_get_visible_child(priv->stack);
	GValue title	 = G_VALUE_INIT;
	g_value_init(&title, G_TYPE_STRING);
	gtk_container_child_get_property(GTK_CONTAINER(priv->stack), child, "title", &title);
	gtk_header_bar_set_title(priv->sub_header_bar, g_value_get_string(&title));
}

	self->user_validated = TRUE;
static void
update_focus(HalWindow *self) // update
{
	HalWindowPrivate *priv = hal_window_get_instance_private(self);

	gtk_stack_set_visible_child_name(GTK_STACK(priv->profile), "profile");
	GtkWidget *header_child = hdy_leaflet_get_visible_child(priv->header_leaflet);
	const HdyFold fold		= hdy_leaflet_get_fold(priv->header_leaflet);

	g_assert(header_child == NULL || GTK_IS_HEADER_BAR(header_child));

	hdy_header_group_set_focus(
		priv->header_group, fold == HDY_FOLD_FOLDED ? GTK_HEADER_BAR(header_child) : NULL);
}

void
hal_window_hide_content(HalWindow *self)
static void
stack_notify_visible_child_cb(
	G_GNUC_UNUSED GObject *obj, G_GNUC_UNUSED GParamSpec *pspec, gpointer user_data)
{
	HalWindowPrivate *priv = hal_window_get_instance_private(self);
	HalWindow *self = HAL_WINDOW(user_data);

	gtk_stack_set_visible_child_name(priv->function_stack, "profile");
	gtk_stack_set_visible_child_name(GTK_STACK(priv->profile), "harvest-api-access-token");
	update_header_bar_title(self);
}

static void
hal_window_finalize(GObject *obj)
header_leaflet_notify_visible_child_cb(
	G_GNUC_UNUSED GObject *obj, G_GNUC_UNUSED GParamSpec *pspec, gpointer user_data)
{
	G_OBJECT_CLASS(hal_window_parent_class)->finalize(obj);
	HalWindow *self = HAL_WINDOW(user_data);

	update_focus(self);
}

static void
hal_window_size_allocate(GtkWidget *widget, GtkAllocation *allocation)
header_leaflet_notify_fold_cb(
	G_GNUC_UNUSED GObject *obj, G_GNUC_UNUSED GParamSpec *pspec, gpointer user_data)
{
	HalWindow *self		   = HAL_WINDOW(widget);
	HalWindowPrivate *priv = hal_window_get_instance_private(self);
	HalWindow *self = HAL_WINDOW(user_data);

	if (self->user_validated) {
		hdy_squeezer_set_child_enabled(priv->function_squeezer,
			GTK_WIDGET(priv->function_wide_switcher), allocation->width > 600);
		hdy_squeezer_set_child_enabled(priv->function_squeezer,
			GTK_WIDGET(priv->function_narrow_switcher), allocation->width > 400);
	} else {
		hdy_squeezer_set_child_enabled(
			priv->function_squeezer, GTK_WIDGET(priv->title_label), TRUE);
		hdy_squeezer_set_child_enabled(
			priv->function_squeezer, GTK_WIDGET(priv->function_wide_switcher), FALSE);
		hdy_squeezer_set_child_enabled(
			priv->function_squeezer, GTK_WIDGET(priv->function_narrow_switcher), FALSE);
	}

	GTK_WIDGET_CLASS(hal_window_parent_class)->size_allocate(widget, allocation);
	update_focus(self);
}

static gboolean
hal_window_is_title_label_visible(
	G_GNUC_UNUSED GBinding *binding, const GValue *from_value, GValue *to_value, gpointer user_data)
static void
back_button_clicked_cb(G_GNUC_UNUSED GtkButton *widget, gpointer user_data)
{
	HalWindow *self		   = HAL_WINDOW(user_data);
	HalWindowPrivate *priv = hal_window_get_instance_private(self);

	g_value_set_boolean(
		to_value, g_value_get_object(from_value) == priv->title_label && self->user_validated);
	hdy_leaflet_set_visible_child_name(priv->content_leaflet, "sidebar");
}

	return TRUE;
void
hal_window_show_content(HalWindow *self)
{
	HalWindowPrivate *priv = hal_window_get_instance_private(self);

	gtk_stack_set_visible_child_name(GTK_STACK(priv->profile), "profile");
}

void
hal_window_hide_content(HalWindow *self)
{
	HalWindowPrivate *priv = hal_window_get_instance_private(self);

	gtk_stack_set_visible_child_name(priv->stack, "profile");
	gtk_stack_set_visible_child_name(GTK_STACK(priv->profile), "harvest-api-access-token");
}

static void
hal_window_finalize(GObject *obj)
{
	G_OBJECT_CLASS(hal_window_parent_class)->finalize(obj);
}

static void


@@ 108,16 124,20 @@ hal_window_class_init(HalWindowClass *klass)

	object_class->finalize = hal_window_finalize;

	wid_class->size_allocate = hal_window_size_allocate;

	gtk_widget_class_set_template_from_resource(
		wid_class, "/io/partin/tristan/HarvestAlmanac/ui/hal-window.ui");
	gtk_widget_class_bind_template_child_private(wid_class, HalWindow, function_stack);
	gtk_widget_class_bind_template_child_private(wid_class, HalWindow, function_squeezer);
	gtk_widget_class_bind_template_child_private(wid_class, HalWindow, function_switcher_bar);
	gtk_widget_class_bind_template_child_private(wid_class, HalWindow, function_wide_switcher);
	gtk_widget_class_bind_template_child_private(wid_class, HalWindow, function_narrow_switcher);
	gtk_widget_class_bind_template_child_private(wid_class, HalWindow, title_label);
	gtk_widget_class_bind_template_child_private(wid_class, HalWindow, header_group);
	gtk_widget_class_bind_template_child_private(wid_class, HalWindow, content_leaflet);
	gtk_widget_class_bind_template_child_private(wid_class, HalWindow, header_leaflet);
	gtk_widget_class_bind_template_child_private(wid_class, HalWindow, header_bar);
	gtk_widget_class_bind_template_child_private(wid_class, HalWindow, sub_header_bar);
	gtk_widget_class_bind_template_child_private(wid_class, HalWindow, stack);
	gtk_widget_class_bind_template_child_private(wid_class, HalWindow, sidebar);
	gtk_widget_class_bind_template_child_private(wid_class, HalWindow, back_button);
	gtk_widget_class_bind_template_callback(wid_class, header_leaflet_notify_fold_cb);
	gtk_widget_class_bind_template_callback(wid_class, header_leaflet_notify_visible_child_cb);
	gtk_widget_class_bind_template_callback(wid_class, stack_notify_visible_child_cb);
	gtk_widget_class_bind_template_callback(wid_class, back_button_clicked_cb);
}

static void


@@ 130,19 150,16 @@ hal_window_init(HalWindow *self)
	priv->profile	   = hal_profile_new();
	priv->time_tracker = hal_time_tracker_new();

	gtk_stack_add_titled(priv->function_stack, GTK_WIDGET(priv->profile), "profile", "Profile");
	gtk_stack_add_titled(
		priv->function_stack, GTK_WIDGET(priv->time_tracker), "time-tracker", "Time");
	gtk_container_child_set(GTK_CONTAINER(priv->function_stack), GTK_WIDGET(priv->profile),
		"icon-name", "user-info-symbolic", NULL);
	gtk_container_child_set(GTK_CONTAINER(priv->function_stack), GTK_WIDGET(priv->time_tracker),
		"icon-name", "document-open-recent-symbolic", NULL);
	gtk_stack_add_titled(priv->stack, GTK_WIDGET(priv->profile), "profile", "Profile");
	gtk_stack_add_titled(priv->stack, GTK_WIDGET(priv->time_tracker), "time-tracker", "Time");
	gtk_container_child_set(GTK_CONTAINER(priv->stack), GTK_WIDGET(priv->profile), "icon-name",
		"user-info-symbolic", NULL);
	gtk_container_child_set(GTK_CONTAINER(priv->stack), GTK_WIDGET(priv->time_tracker), "icon-name",
		"document-open-recent-symbolic", NULL);

	self->user_validated = FALSE;
	update_header_bar_title(self);

	g_object_bind_property_full(priv->function_squeezer, "visible-child",
		priv->function_switcher_bar, "reveal", G_BINDING_SYNC_CREATE,
		hal_window_is_title_label_visible, NULL, self, NULL);
	hdy_leaflet_set_visible_child_name(priv->content_leaflet, "content");
}

HalWindow *

M harvest-almanac/main.c => harvest-almanac/main.c +1 -1
@@ 21,7 21,7 @@ main(int argc, char *argv[])

	const gboolean success = hdy_init(&argc, &argv);
	if (!success) {
		g_log(G_LOG_DOMAIN, G_LOG_LEVEL_ERROR, "Unable to initialize libhandy");
		g_critical("Unable to initialize libhandy");
		return 1;
	}