Skip to content

Instantly share code, notes, and snippets.

@sebastiaanfranken
Last active March 20, 2021 18:18
Show Gist options
  • Select an option

  • Save sebastiaanfranken/01010337cbef9313d908 to your computer and use it in GitHub Desktop.

Select an option

Save sebastiaanfranken/01010337cbef9313d908 to your computer and use it in GitHub Desktop.
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