Last active
March 20, 2021 18:18
-
-
Save sebastiaanfranken/01010337cbef9313d908 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| const Gtk = imports.gi.Gtk; | |
| const Gdk = imports.gi.Gdk; | |
| const Lang = imports.lang; | |
| const Webkit = imports.gi.WebKit; | |
| const Gio = imports.gi.Gio; | |
| const GLib = imports.gi.GLib; | |
| const GObject = imports.gi.GObject; | |
| const Json = imports.gi.Json; | |
| const Clutter = imports.gi.Clutter; | |
| const URL = 'https://google.nl/'; | |
| const Webbrowser = new Lang.Class({ | |
| Name: "webbrowser", | |
| /* | |
| * Initializes the application, creates the | |
| * entry points and hooks for use later on | |
| */ | |
| _init: function() { | |
| this.application = new Gtk.Application({ | |
| application_id: "nl.sebastiaanfranken.webbrowser", | |
| flags: Gio.ApplicationFlags.FLAGS_NONE | |
| }); | |
| GLib.set_prgname('Browser'); | |
| /* | |
| * Connect the "activate" signal to a handler | |
| */ | |
| this.application.connect('activate', Lang.bind(this, this.handlers.applicationActivateHandler)); | |
| /* | |
| * Connect the "startup" signal to a handler | |
| */ | |
| this.application.connect('startup', Lang.bind(this, this.handlers.applicationStartupHandler)); | |
| }, | |
| /* | |
| * Houses all application/signal handlers | |
| */ | |
| handlers: { | |
| /* | |
| * Handles the application 'activate' signal | |
| */ | |
| applicationActivateHandler: function() { | |
| this.window.present(); | |
| }, | |
| /* | |
| * Handles the application 'startup' signal | |
| */ | |
| applicationStartupHandler: function() { | |
| this.buildUserInterface(); | |
| }, | |
| /* | |
| * Handles the webview 'load_committed' signal | |
| */ | |
| webviewLoadCommittedHandler: function(source, frame) { | |
| this.btnReload.sensitive = true; | |
| this.btnBack.sensitive = this.webview.can_go_back(); | |
| this.btnForward.sensitive = this.webview.can_go_forward(); | |
| }, | |
| /* | |
| * Handles the webview 'load-error' signal | |
| */ | |
| webviewLoadErrorHandler: function(source, frame) { | |
| this.btnReload.sensitive = false; | |
| this.headerBar.set_title('Browser'); | |
| this.headerBar.set_subtitle('Zo te zien ging er iets niet helemaal goed'); | |
| }, | |
| /* | |
| * Handles the webview 'load-progress-changed' signal | |
| */ | |
| webviewLoadProgressChangedHandler: function(source, progress) { | |
| if(progress < 100) { | |
| let value = progress / 100; | |
| this.progressBar.show(); | |
| this.progressBar.set_fraction(value); | |
| } | |
| else { | |
| this.progressBar.set_fraction(0); | |
| this.progressBar.hide(); | |
| } | |
| }, | |
| /* | |
| * Handles the webview 'title-changed' signal | |
| */ | |
| webviewTitleChangedHandler: function(source, frame, title) { | |
| if(title.length > 0) { | |
| this.headerBar.set_title(title + ' - Browser'); | |
| this.headerBar.set_subtitle(frame.get_uri()); | |
| } | |
| else { | |
| this.headerBar.set_title('Browser'); | |
| this.headerBar.set_subtitle(null); | |
| } | |
| }, | |
| /* | |
| * Handles the btnBack 'clicked' signal | |
| */ | |
| btnBackClickedHandler: function() { | |
| this.webview.go_back(); | |
| }, | |
| /* | |
| * Handles the btnForward 'clicked' signal | |
| */ | |
| btnForwardClickedHandler: function() { | |
| this.webview.go_forward(); | |
| }, | |
| /* | |
| * Handles the btnForward 'clicked' signal | |
| */ | |
| btnReloadClickedHandler: function() { | |
| this.webview.reload(); | |
| }, | |
| /* | |
| * Handles the btnNewTab 'clicked' signal | |
| */ | |
| btnNewTabClickedHandler: function() { | |
| log('new tab button clicked'); | |
| }, | |
| /* | |
| * Handles the btnSearch 'clicked' signal | |
| */ | |
| btnSearchClickedHandler: function(source) { | |
| let hb = this.headerBar; | |
| let width = this.window.get_allocated_width() / 100 * 10; | |
| let widthChars = (width < 80) ? width : 80; | |
| if(source.active) { | |
| let box = new Gtk.Box({ | |
| orientation: Gtk.Orientation.HORIZONTAL | |
| }); | |
| box.get_style_context().add_class('linked'); | |
| let entry = new Gtk.SearchEntry({ | |
| vexpand: true, | |
| width_chars: widthChars, | |
| text: hb.get_subtitle() | |
| }); | |
| entry.connect('key-press-event', Lang.bind(this, function(textview, event) { | |
| let btn = event.get_keyval()[1]; | |
| log(btn); | |
| })); | |
| let submit = new Gtk.Button({ | |
| label: 'Gaan' | |
| }); | |
| submit.connect('clicked', Lang.bind(this, function() { | |
| let url = entry.get_text(); | |
| this.webview.load_uri(url); | |
| })); | |
| box.add(entry); | |
| box.add(submit); | |
| hb.set_custom_title(box); | |
| box.show_all(); | |
| } | |
| else { | |
| hb.set_custom_title(null); | |
| } | |
| } | |
| }, | |
| /* | |
| * Builds the application UI | |
| */ | |
| buildUserInterface: function() { | |
| /* | |
| * Determines UI scaling for our monitor, so the | |
| * app gets displayed as it should on a 4K monitor. | |
| */ | |
| let w = new Gtk.Window(), | |
| s = w.get_screen(), | |
| m = s.get_monitor_at_window(s.get_active_window()), | |
| mon = s.get_monitor_geometry(m), | |
| screenHeight = mon.height, | |
| screenWidth = mon.width, | |
| applicationHeightRequest = ((screenHeight / 100) * 75), | |
| applicationWidthRequest = ((screenWidth / 100) * 75); | |
| /* | |
| * Defines the application window (main) | |
| */ | |
| this.window = new Gtk.ApplicationWindow({ | |
| application: this.application, | |
| window_position: Gtk.WindowPosition.CENTER, | |
| border_width: 0, | |
| width_request: applicationWidthRequest, | |
| height_request: applicationHeightRequest, | |
| title: 'Web' | |
| }); | |
| this.window.set_icon_name('application-x-executable'); | |
| /* | |
| * We use a Gtk.HeaderBar here, so set that up now | |
| */ | |
| this.headerBar = new Gtk.HeaderBar({ | |
| hexpand: true, | |
| show_close_button: true, | |
| title: 'Browser' | |
| }); | |
| let css = new Gtk.CssProvider(); | |
| css.load_from_data('GtkHeaderBar { background-color: #232323; }'); | |
| this.headerBar.get_style_context().add_provider(css, 0); | |
| this.btnBack = new Gtk.Button({ | |
| image: new Gtk.Image({ | |
| icon_name: 'go-previous-symbolic' | |
| }), | |
| sensitive: false | |
| }); | |
| this.btnBack.connect('clicked', Lang.bind(this, this.handlers.btnBackClickedHandler)); | |
| this.btnForward = new Gtk.Button({ | |
| image: new Gtk.Image({ | |
| icon_name: 'go-next-symbolic' | |
| }), | |
| sensitive: false | |
| }); | |
| this.btnForward.connect('clicked', Lang.bind(this, this.handlers.btnForwardClickedHandler)); | |
| this.btnReload = new Gtk.Button({ | |
| image: new Gtk.Image({ | |
| icon_name: 'view-refresh-symbolic' | |
| }), | |
| sensitive: false | |
| }); | |
| this.btnReload.connect('clicked', Lang.bind(this, this.handlers.btnReloadClickedHandler)); | |
| this.btnNewTab = new Gtk.Button({ | |
| image: new Gtk.Image({ | |
| icon_name: 'tab-new-symbolic' | |
| }), | |
| sensitive: true | |
| }); | |
| this.btnNewTab.connect('clicked', Lang.bind(this, this.handlers.btnNewTabClickedHandler)); | |
| this.btnSearch = new Gtk.ToggleButton({ | |
| image: new Gtk.Image({ | |
| icon_name: 'edit-find-symbolic' | |
| }), | |
| sensitive: true | |
| }); | |
| this.btnSearch.connect('clicked', Lang.bind(this, this.handlers.btnSearchClickedHandler)); | |
| /* | |
| * Menu | |
| */ | |
| this.btnMenu = new Gtk.MenuButton({ | |
| image: new Gtk.Image({ | |
| icon_name: 'open-menu-symbolic' | |
| }) | |
| }); | |
| let popMenu = new Gtk.Popover(); | |
| popMenu.set_size_request(-1, -1); | |
| this.btnMenu.set_popover(popMenu); | |
| this.btnMenu.set_menu_model(this.createMenu()); | |
| /* | |
| * General progress bar | |
| */ | |
| this.progressBar = new Gtk.ProgressBar({ | |
| valign: Gtk.Align.CENTER | |
| }); | |
| /* | |
| * This Gtk.Box is used to store the back and forward | |
| * buttons in | |
| */ | |
| let buttonContainer = new Gtk.Box({ | |
| orientation: Gtk.Orientation.HORIZONTAL | |
| }); | |
| buttonContainer.get_style_context().add_class('linked'); | |
| /* | |
| * Add the buttons to the container | |
| */ | |
| buttonContainer.add(this.btnBack); | |
| buttonContainer.add(this.btnForward); | |
| /* | |
| * Add the button container to the Gtk.HeaderBar with | |
| * the reload button following it | |
| */ | |
| this.headerBar.pack_start(buttonContainer); | |
| this.headerBar.pack_start(this.btnReload); | |
| this.headerBar.pack_start(this.btnNewTab); | |
| this.headerBar.pack_end(this.btnMenu); | |
| this.headerBar.pack_end(this.btnSearch); | |
| this.headerBar.pack_end(this.progressBar); | |
| /* | |
| * Set the Gtk.HeaderBar to be the Gtk.Window's titlebar | |
| */ | |
| this.window.set_titlebar(this.headerBar); | |
| /* | |
| * DUMMY CODE: add a single tab to the stack | |
| */ | |
| this.scrolled = new Gtk.ScrolledWindow({ | |
| hscrollbar_policy: Gtk.PolicyType.AUTOMATIC, | |
| vscrollbar_policy: Gtk.PolicyType.AUTOMATIC, | |
| shadow_type: Gtk.ShadowType.NONE | |
| }); | |
| this.webview = new Webkit.WebView(); | |
| this.webview.load_uri(URL); | |
| /* | |
| * Connect the 'load_committed' signal to a handler | |
| */ | |
| this.webview.connect('load-committed', Lang.bind(this, this.handlers.webviewLoadCommittedHandler)); | |
| /* | |
| * Connect the 'load-error' signal to a handler | |
| */ | |
| this.webview.connect('load-error', Lang.bind(this, this.handlers.webviewLoadErrorHandler)); | |
| /* | |
| * Connect the 'load-progress-changed' signal to a handler | |
| */ | |
| this.webview.connect('load-progress-changed', Lang.bind(this, this.handlers.webviewLoadProgressChangedHandler)); | |
| /* | |
| * Connect the 'title-changed' signal to a handler | |
| */ | |
| this.webview.connect('title-changed', Lang.bind(this, this.handlers.webviewTitleChangedHandler)); | |
| /* | |
| * Add the webview to the scrolled window, | |
| * and add the scrolled window to the stack | |
| */ | |
| this.scrolled.add(this.webview); | |
| /* | |
| * Add the stack to the main window, and set the | |
| * Gtk.HeaderBar title to be the stack switcher | |
| */ | |
| this.window.add(this.scrolled); | |
| /* | |
| * Show all children and the main window | |
| */ | |
| this.window.show_all(); | |
| /* | |
| * Hide the main progress bar | |
| */ | |
| this.progressBar.hide(); | |
| }, | |
| /* | |
| * Create a menu in the HeaderBar | |
| */ | |
| createMenu: function() { | |
| let menu, section, submenu; | |
| menu = new Gio.Menu(); | |
| section = new Gio.Menu(); | |
| submenu = new Gio.Menu(); | |
| section.append_submenu('Favorieten', submenu); | |
| submenu.append('Site toevoegen aan favorieten', 'app.addSiteToFavorites'); | |
| submenu.append('Beheer favorieten', 'app.manageFavorites'); | |
| menu.append_section(null, section); | |
| section = new Gio.Menu(); | |
| section.append('Nachtmodus', 'app.nightmode'); | |
| section.append('Over', 'app.about'); | |
| menu.append_section(null, section); | |
| /* | |
| * Add site to favorites handler | |
| */ | |
| let actionAddSiteToFavorites = new Gio.SimpleAction({ | |
| name: 'addSiteToFavorites', | |
| state: new GLib.Variant('b', false) | |
| }); | |
| actionAddSiteToFavorites.connect('activate', Lang.bind(this, function(action) { | |
| action.set_state(new GLib.Variant('b', !action.get_state().get_boolean())); | |
| })); | |
| this.application.add_action(actionAddSiteToFavorites); | |
| /* | |
| * Dark/night mode handler | |
| */ | |
| let actionNightmode = new Gio.SimpleAction({ | |
| name: 'nightmode', | |
| state: new GLib.Variant('b', this.window.get_settings().gtk_application_prefer_dark_theme) | |
| }); | |
| actionNightmode.connect('activate', Lang.bind(this, function(action) { | |
| this.window.get_settings().gtk_application_prefer_dark_theme = !this.window.get_settings().gtk_application_prefer_dark_theme; | |
| action.set_state(new GLib.Variant('b', !action.get_state().get_boolean())); | |
| })); | |
| this.application.add_action(actionNightmode); | |
| return menu; | |
| } | |
| }); | |
| let b = new Webbrowser(); | |
| b.application.run(ARGV); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment