/* * Main menu and button * * Copyright (C) 2017 Patrick McDermott * * This file is part of Marquee. * * Marquee 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. * * Marquee 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 Marquee. If not, see . */ #include #include #include #include "main-menu.h" #include "tab.h" #include "find-toolbar.h" #include "web-view.h" struct _MqMainMenu { GtkToolButton parent_instance; MqTab *tab; MqFindToolbar *find_toolbar; MqWebView *web_view; GtkWidget *popover; }; enum { PROP_TAB = 1, PROP_FIND_TOOLBAR, PROP_WEB_VIEW, N_PROPERTIES }; static GParamSpec *obj_properties[N_PROPERTIES] = {NULL,}; struct _MqMainMenuClass { GtkToolButtonClass parent_class; }; G_DEFINE_TYPE(MqMainMenu, mq_main_menu, GTK_TYPE_TOOL_BUTTON) static void zoom_out_clicked_cb(GtkButton G_GNUC_UNUSED *button, MqMainMenu *main_menu) { mq_web_view_zoom_out(main_menu->web_view); } static void zoom_reset_clicked_cb(GtkButton G_GNUC_UNUSED *button, MqMainMenu *main_menu) { mq_web_view_zoom_reset(main_menu->web_view); } static void zoom_in_clicked_cb(GtkButton G_GNUC_UNUSED *button, MqMainMenu *main_menu) { mq_web_view_zoom_in(main_menu->web_view); } static void find_clicked_cb(GtkButton G_GNUC_UNUSED *button, MqMainMenu *main_menu) { gtk_widget_hide(main_menu->popover); mq_find_toolbar_reveal(main_menu->find_toolbar); } static void fullscreen_clicked_cb(GtkButton G_GNUC_UNUSED *button, MqMainMenu *main_menu) { gtk_widget_hide(main_menu->popover); mq_window_toggle_fullscreen(mq_tab_get_window(main_menu->tab)); } static void developer_tools_clicked_cb(GtkButton G_GNUC_UNUSED *button, MqMainMenu *main_menu) { gtk_widget_hide(main_menu->popover); webkit_web_inspector_show(webkit_web_view_get_inspector( WEBKIT_WEB_VIEW(main_menu->web_view))); } static void preferences_clicked_cb(GtkButton G_GNUC_UNUSED *button, MqMainMenu *main_menu) { gtk_widget_hide(main_menu->popover); mq_tab_new("about:preferences", main_menu->tab); /* TODO: Hack: */ gtk_notebook_next_page(GTK_NOTEBOOK(main_menu->tab->window->notebook)); } static void about_clicked_cb(GtkButton G_GNUC_UNUSED *button, MqMainMenu *main_menu) { gtk_widget_hide(main_menu->popover); mq_tab_new("about:", main_menu->tab); /* TODO: Hack: */ gtk_notebook_next_page(GTK_NOTEBOOK(main_menu->tab->window->notebook)); } static void quit_clicked_cb(GtkButton G_GNUC_UNUSED *button, MqMainMenu *main_menu) { /* mq_tab_quit() just calls mq_window_quit(), which just calls * mq_application_quit(), which is asynchronous. So close the menu. */ gtk_widget_hide(main_menu->popover); mq_tab_quit(main_menu->tab); } #define BUTTON_ROWS 6 #define BUTTON_COLS 3 #define NEW_BUTTON(Y, X, ICON, TOOLTIP) \ do { \ buttons[Y * BUTTON_COLS + X] = gtk_button_new_from_icon_name(\ ICON, GTK_ICON_SIZE_BUTTON); \ gtk_widget_set_tooltip_text(buttons[Y * BUTTON_COLS + X], \ TOOLTIP); \ gtk_grid_attach(GTK_GRID(grid), buttons[Y * BUTTON_COLS + X], \ X, Y, 1, 1); \ } while (0) #define CLICKED_CB(Y, X, CB) \ g_signal_connect(buttons[Y * BUTTON_COLS + X], "clicked", \ G_CALLBACK(CB), main_menu) static void menu_clicked_cb(MqMainMenu *main_menu) { GtkWidget *grid; GtkWidget *buttons[BUTTON_ROWS * BUTTON_COLS]; /* Set up the grid. */ grid = gtk_grid_new(); NEW_BUTTON(0, 0, "zoom-out", "Zoom out"); NEW_BUTTON(0, 1, "zoom-original", "Reset zoom"); NEW_BUTTON(0, 2, "zoom-in", "Zoom in"); NEW_BUTTON(1, 0, "document-open", "Open file"); NEW_BUTTON(1, 1, "document-save-as", "Save page"); NEW_BUTTON(1, 2, "mail-message-new", "E-mail link"); NEW_BUTTON(2, 0, "edit-find", "Find"); NEW_BUTTON(2, 1, "document-print-preview", "Print preview"); NEW_BUTTON(2, 2, "document-print", "Print"); NEW_BUTTON(3, 0, "bookmark-new", "Bookmarks"); NEW_BUTTON(3, 1, "document-open-recent", "History"); NEW_BUTTON(3, 2, "document-save", "Downloads"); NEW_BUTTON(4, 0, "view-fullscreen", "Full screen"); NEW_BUTTON(4, 1, "document-properties", "Developer tools"); NEW_BUTTON(4, 2, "system-run", "Preferences"); NEW_BUTTON(5, 0, "help-about", "About Marquee"); NEW_BUTTON(5, 2, "application-exit", "Quit"); CLICKED_CB(0, 0, zoom_out_clicked_cb); CLICKED_CB(0, 1, zoom_reset_clicked_cb); CLICKED_CB(0, 2, zoom_in_clicked_cb); /* TODO: 1, 0: Open file */ /* TODO: 1, 1: Save page */ /* TODO: 1, 2: E-mail link */ CLICKED_CB(2, 0, find_clicked_cb); /* TODO: 2, 1: Print preview */ /* TODO: 2, 2: Print */ /* TODO: 3, 0: Bookmarks */ /* TODO: 3, 1: History */ /* TODO: 3, 2: Downloads */ CLICKED_CB(4, 0, fullscreen_clicked_cb); CLICKED_CB(4, 1, developer_tools_clicked_cb); CLICKED_CB(4, 2, preferences_clicked_cb); CLICKED_CB(5, 0, about_clicked_cb); CLICKED_CB(5, 2, quit_clicked_cb); /* Set up the popover. */ main_menu->popover = gtk_popover_new(GTK_WIDGET(main_menu)); gtk_container_add(GTK_CONTAINER(main_menu->popover), grid); /* NB: gtk_popover_popup() is new in GTK+ 3.22. */ gtk_widget_show_all(main_menu->popover); } #undef BUTTON_ROWS #undef BUTTON_COLS #undef NEW_BUTTON static void get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { MqMainMenu *main_menu; main_menu = MQ_MAIN_MENU(object); switch (property_id) { case PROP_TAB: g_value_set_pointer(value, main_menu->tab); break; case PROP_FIND_TOOLBAR: g_value_set_object(value, main_menu->find_toolbar); break; case PROP_WEB_VIEW: g_value_set_object(value, main_menu->web_view); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); break; } } static void set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { MqMainMenu *main_menu; main_menu = MQ_MAIN_MENU(object); switch (property_id) { case PROP_TAB: main_menu->tab = g_value_get_pointer(value); break; case PROP_FIND_TOOLBAR: main_menu->find_toolbar = g_value_get_object(value); break; case PROP_WEB_VIEW: main_menu->web_view = g_value_get_object(value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); break; } } static void mq_main_menu_class_init(MqMainMenuClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS(klass); object_class->get_property = get_property; object_class->set_property = set_property; obj_properties[PROP_TAB] = g_param_spec_pointer( "tab", "MqTab", "The ancestral MqTab instance", G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB); obj_properties[PROP_FIND_TOOLBAR] = g_param_spec_object( "find-toolbar", "MqFindToolbar", "The associated MqFindToolbar instance", MQ_TYPE_FIND_TOOLBAR, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB); obj_properties[PROP_WEB_VIEW] = g_param_spec_object( "web-view", "MqWebView", "The associated MqWebView instance", MQ_TYPE_WEB_VIEW, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB); g_object_class_install_properties(object_class, N_PROPERTIES, obj_properties); } static void mq_main_menu_init(MqMainMenu *main_menu) { gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(main_menu), gtk_image_new_from_icon_name("open-menu-symbolic", GTK_ICON_SIZE_SMALL_TOOLBAR)); gtk_tool_button_set_label(GTK_TOOL_BUTTON(main_menu), "Menu"); gtk_widget_set_tooltip_text(GTK_WIDGET(main_menu), "Open menu"); g_signal_connect(main_menu, "clicked", G_CALLBACK(menu_clicked_cb), NULL); } GtkToolItem * mq_main_menu_new(MqTab *tab, MqFindToolbar *find_toolbar, MqWebView *web_view) { return g_object_new(MQ_TYPE_MAIN_MENU, "tab", tab, "find-toolbar", find_toolbar, "web-view", web_view, NULL); }