/* ide-run-button.c * * Copyright 2016-2019 Christian Hergert * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #define G_LOG_DOMAIN "ide-run-button" #include "config.h" #include #include #include #include "ide-gui-global.h" #include "ide-run-button.h" #include "ide-run-manager-private.h" struct _IdeRunButton { GtkBox parent_instance; GtkButton *button; GtkImage *button_image; DzlMenuButton *menu_button; GtkShortcutsShortcut *run_shortcut; GtkLabel *run_tooltip_message; DzlShortcutTooltip *tooltip; char *run_handler_icon_name; }; G_DEFINE_FINAL_TYPE (IdeRunButton, ide_run_button, GTK_TYPE_BOX) static void ide_run_button_handler_set (IdeRunButton *self, GParamSpec *pspec, IdeRunManager *run_manager) { const GList *list; const GList *iter; const gchar *handler; g_assert (IDE_IS_RUN_BUTTON (self)); g_assert (IDE_IS_RUN_MANAGER (run_manager)); handler = ide_run_manager_get_handler (run_manager); list = _ide_run_manager_get_handlers (run_manager); for (iter = list; iter; iter = iter->next) { const IdeRunHandlerInfo *info = iter->data; if (g_strcmp0 (info->id, handler) == 0) { self->run_handler_icon_name = g_strdup (info->icon_name); g_object_set (self->button_image, "icon-name", info->icon_name, NULL); break; } } } static void on_run_busy_state_changed_cb (IdeRunButton *self, GParamSpec *pspec, IdeRunManager *run_manager) { const char *icon_name; const char *action_name; g_assert (IDE_IS_RUN_BUTTON (self)); g_assert (IDE_IS_RUN_MANAGER (run_manager)); if (!ide_run_manager_get_busy (run_manager)) { icon_name = self->run_handler_icon_name; action_name = "run-manager.run"; } else { icon_name = "builder-run-stop-symbolic"; action_name = "run-manager.stop"; } g_object_set (self->button_image, "icon-name", icon_name, NULL); gtk_actionable_set_action_name (GTK_ACTIONABLE (self->button), action_name); } static void ide_run_button_load (IdeRunButton *self, IdeContext *context) { IdeRunManager *run_manager; g_assert (IDE_IS_RUN_BUTTON (self)); g_assert (IDE_IS_CONTEXT (context)); run_manager = ide_run_manager_from_context (context); g_signal_connect_object (run_manager, "notify::busy", G_CALLBACK (on_run_busy_state_changed_cb), self, G_CONNECT_SWAPPED); g_signal_connect_object (run_manager, "notify::handler", G_CALLBACK (ide_run_button_handler_set), self, G_CONNECT_SWAPPED); ide_run_button_handler_set (self, NULL, run_manager); } static void ide_run_button_context_set (GtkWidget *widget, IdeContext *context) { IdeRunButton *self = (IdeRunButton *)widget; g_assert (IDE_IS_RUN_BUTTON (self)); g_assert (!context || IDE_IS_CONTEXT (context)); if (context != NULL) ide_run_button_load (self, context); } static gboolean ide_run_button_query_tooltip (IdeRunButton *self, gint x, gint y, gboolean keyboard_tooltip, GtkTooltip *tooltip, GtkButton *button) { IdeRunManager *run_manager; const GList *list; const GList *iter; const gchar *handler; IdeContext *context; g_assert (IDE_IS_RUN_BUTTON (self)); g_assert (GTK_IS_TOOLTIP (tooltip)); g_assert (GTK_IS_BUTTON (button)); context = ide_widget_get_context (GTK_WIDGET (self)); run_manager = ide_run_manager_from_context (context); handler = ide_run_manager_get_handler (run_manager); list = _ide_run_manager_get_handlers (run_manager); if (ide_run_manager_get_busy (run_manager)) { gtk_tooltip_set_text (tooltip, _("Stop running")); return TRUE; } for (iter = list; iter; iter = iter->next) { const IdeRunHandlerInfo *info = iter->data; if (g_strcmp0 (info->id, handler) == 0) { gboolean enabled; /* Figure out if the run action is enabled. If it * is not, then we should inform the user that * the project cannot be run yet because the * build pipeline is not yet configured. */ g_action_group_query_action (G_ACTION_GROUP (run_manager), "run", &enabled, NULL, NULL, NULL, NULL); if (!enabled) { gtk_tooltip_set_custom (tooltip, GTK_WIDGET (self->run_tooltip_message)); return TRUE; } /* The shortcut tooltip will set this up after us */ dzl_shortcut_tooltip_set_accel (self->tooltip, info->accel); dzl_shortcut_tooltip_set_title (self->tooltip, info->title); } } return FALSE; } static void ide_run_button_class_init (IdeRunButtonClass *klass) { GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/libide-gui/ui/ide-run-button.ui"); gtk_widget_class_bind_template_child (widget_class, IdeRunButton, button); gtk_widget_class_bind_template_child (widget_class, IdeRunButton, button_image); gtk_widget_class_bind_template_child (widget_class, IdeRunButton, menu_button); gtk_widget_class_bind_template_child (widget_class, IdeRunButton, run_shortcut); gtk_widget_class_bind_template_child (widget_class, IdeRunButton, run_tooltip_message); gtk_widget_class_bind_template_child (widget_class, IdeRunButton, tooltip); } static void ide_run_button_init (IdeRunButton *self) { gtk_widget_init_template (GTK_WIDGET (self)); g_signal_connect_object (self->button, "query-tooltip", G_CALLBACK (ide_run_button_query_tooltip), self, G_CONNECT_SWAPPED); ide_widget_set_context_handler (self, ide_run_button_context_set); }