You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
744 lines
25 KiB
744 lines
25 KiB
#include "MainWindow.h" |
|
|
|
#include <config-dev.h> |
|
#include <config-features.h> |
|
#include <config.h> |
|
|
|
#include "control/Control.h" |
|
#include "control/layer/LayerController.h" |
|
#include "gui/GladeSearchpath.h" |
|
#include "gui/scroll/ScrollHandlingGtk.h" |
|
#include "gui/scroll/ScrollHandlingXournalpp.h" |
|
#include "toolbarMenubar/ToolMenuHandler.h" |
|
#include "toolbarMenubar/model/ToolbarData.h" |
|
#include "toolbarMenubar/model/ToolbarModel.h" |
|
#include "widgets/SpinPageAdapter.h" |
|
#include "widgets/XournalWidget.h" |
|
|
|
#include "Layout.h" |
|
#include "MainWindowToolbarMenu.h" |
|
#include "ToolbarDefinitions.h" |
|
#include "ToolitemDragDrop.h" |
|
#include "XojMsgBox.h" |
|
#include "XournalView.h" |
|
#include "i18n.h" |
|
|
|
#ifdef MAC_INTEGRATION |
|
#include <gtkosxapplication.h> |
|
#endif |
|
|
|
#include <utility> |
|
|
|
#include <gdk/gdk.h> |
|
|
|
#include "gui/inputdevices/InputEvents.h" |
|
#include "util/DeviceListHelper.h" |
|
|
|
MainWindow::MainWindow(GladeSearchpath* gladeSearchPath, Control* control): |
|
GladeGui(gladeSearchPath, "main.glade", "mainWindow") { |
|
this->control = control; |
|
this->toolbarWidgets = new GtkWidget*[TOOLBAR_DEFINITIONS_LEN]; |
|
this->toolbarSelectMenu = new MainWindowToolbarMenu(this); |
|
|
|
loadMainCSS(gladeSearchPath, "xournalpp.css"); |
|
|
|
GtkOverlay* overlay = GTK_OVERLAY(get("mainOverlay")); |
|
this->floatingToolbox = new FloatingToolbox(this, overlay); |
|
|
|
|
|
for (int i = 0; i < TOOLBAR_DEFINITIONS_LEN; i++) { |
|
GtkWidget* w = get(TOOLBAR_DEFINITIONS[i].guiName); |
|
g_object_ref(w); |
|
this->toolbarWidgets[i] = w; |
|
} |
|
|
|
initXournalWidget(); |
|
|
|
setSidebarVisible(control->getSettings()->isSidebarVisible()); |
|
|
|
// Window handler |
|
g_signal_connect(this->window, "delete-event", G_CALLBACK(deleteEventCallback), this->control); |
|
g_signal_connect(this->window, "window_state_event", G_CALLBACK(windowStateEventCallback), this); |
|
|
|
g_signal_connect(get("buttonCloseSidebar"), "clicked", G_CALLBACK(buttonCloseSidebarClicked), this); |
|
|
|
|
|
// "watch over" all events |
|
g_signal_connect(this->window, "key-press-event", G_CALLBACK(onKeyPressCallback), this); |
|
|
|
this->toolbar = new ToolMenuHandler(this->control, this, GTK_WINDOW(getWindow())); |
|
|
|
auto file = gladeSearchPath->findFile("", "toolbar.ini"); |
|
|
|
ToolbarModel* tbModel = this->toolbar->getModel(); |
|
|
|
if (!tbModel->parse(file, true)) { |
|
|
|
string msg = FS(_F("Could not parse general toolbar.ini file: {1}\n" |
|
"No Toolbars will be available") % |
|
file.string()); |
|
XojMsgBox::showErrorToUser(control->getGtkWindow(), msg); |
|
} |
|
|
|
file = Util::getConfigFile(TOOLBAR_CONFIG); |
|
if (fs::exists(file)) { |
|
if (!tbModel->parse(file, false)) { |
|
string msg = FS(_F("Could not parse custom toolbar.ini file: {1}\n" |
|
"Toolbars will not be available") % |
|
file.string()); |
|
XojMsgBox::showErrorToUser(control->getGtkWindow(), msg); |
|
} |
|
} |
|
|
|
createToolbarAndMenu(); |
|
|
|
setToolbarVisible(control->getSettings()->isToolbarVisible()); |
|
|
|
GtkWidget* menuViewSidebarVisible = get("menuViewSidebarVisible"); |
|
g_signal_connect(menuViewSidebarVisible, "toggled", G_CALLBACK(viewShowSidebar), this); |
|
|
|
GtkWidget* menuViewToolbarsVisible = get("menuViewToolbarsVisible"); |
|
g_signal_connect(menuViewToolbarsVisible, "toggled", G_CALLBACK(viewShowToolbar), this); |
|
|
|
updateScrollbarSidebarPosition(); |
|
|
|
gtk_window_set_default_size(GTK_WINDOW(this->window), control->getSettings()->getMainWndWidth(), |
|
control->getSettings()->getMainWndHeight()); |
|
|
|
if (control->getSettings()->isMainWndMaximized()) { |
|
gtk_window_maximize(GTK_WINDOW(this->window)); |
|
} else { |
|
gtk_window_unmaximize(GTK_WINDOW(this->window)); |
|
} |
|
|
|
getSpinPageNo()->addListener(this->control->getScrollHandler()); |
|
|
|
|
|
Util::execInUiThread([=]() { |
|
// Execute after the window is visible, else the check won't work |
|
initHideMenu(); |
|
}); |
|
|
|
// Drag and Drop |
|
g_signal_connect(this->window, "drag-data-received", G_CALLBACK(dragDataRecived), this); |
|
|
|
gtk_drag_dest_set(this->window, GTK_DEST_DEFAULT_ALL, nullptr, 0, GDK_ACTION_COPY); |
|
gtk_drag_dest_add_uri_targets(this->window); |
|
gtk_drag_dest_add_image_targets(this->window); |
|
gtk_drag_dest_add_text_targets(this->window); |
|
|
|
LayerCtrlListener::registerListener(control->getLayerController()); |
|
|
|
#ifdef MAC_INTEGRATION |
|
GtkosxApplication* osxApp = gtkosx_application_get(); |
|
|
|
GtkWidget* menubar = get("mainMenubar"); |
|
gtk_widget_hide(menubar); |
|
gtkosx_application_set_menu_bar(osxApp, GTK_MENU_SHELL(menubar)); |
|
|
|
g_signal_connect(osxApp, "NSApplicationWillTerminate", |
|
G_CALLBACK(+[](GtkosxApplication* osxApp, MainWindow* self) { self->control->quit(false); }), |
|
this); |
|
|
|
g_signal_connect(osxApp, "NSApplicationOpenFile", |
|
G_CALLBACK(+[](GtkosxApplication* osxApp, char* path, MainWindow* self) { |
|
return self->control->openFile(path); |
|
}), |
|
this); |
|
|
|
gtkosx_application_ready(osxApp); |
|
#endif |
|
} |
|
|
|
gboolean MainWindow::isKeyForClosure(GtkAccelKey* key, GClosure* closure, gpointer data) { return closure == data; } |
|
|
|
gboolean MainWindow::invokeMenu(GtkWidget* widget) { |
|
// g_warning("invoke_menu %s", gtk_widget_get_name(widget)); |
|
gtk_widget_activate(widget); |
|
return TRUE; |
|
} |
|
|
|
void MainWindow::rebindAcceleratorsMenuItem(GtkWidget* widget, gpointer user_data) { |
|
if (GTK_IS_MENU_ITEM(widget)) { |
|
GtkAccelGroup* newAccelGroup = reinterpret_cast<GtkAccelGroup*>(user_data); |
|
GList* menuAccelClosures = gtk_widget_list_accel_closures(widget); |
|
for (GList* l = menuAccelClosures; l != NULL; l = l->next) { |
|
GClosure* closure = reinterpret_cast<GClosure*>(l->data); |
|
GtkAccelGroup* accelGroup = gtk_accel_group_from_accel_closure(closure); |
|
GtkAccelKey* key = gtk_accel_group_find(accelGroup, isKeyForClosure, closure); |
|
|
|
// g_warning("Rebind %s : %s", gtk_accelerator_get_label(key->accel_key, key->accel_mods), |
|
// gtk_widget_get_name(widget)); |
|
|
|
gtk_accel_group_connect(newAccelGroup, key->accel_key, key->accel_mods, GtkAccelFlags(0), |
|
g_cclosure_new_swap(G_CALLBACK(MainWindow::invokeMenu), widget, NULL)); |
|
} |
|
|
|
MainWindow::rebindAcceleratorsSubMenu(widget, newAccelGroup); |
|
} |
|
} |
|
|
|
void MainWindow::rebindAcceleratorsSubMenu(GtkWidget* widget, gpointer user_data) { |
|
if (GTK_IS_MENU_ITEM(widget)) { |
|
GtkMenuItem* menuItem = reinterpret_cast<GtkMenuItem*>(widget); |
|
GtkWidget* subMenu = gtk_menu_item_get_submenu(menuItem); |
|
if (GTK_IS_CONTAINER(subMenu)) { |
|
gtk_container_foreach(reinterpret_cast<GtkContainer*>(subMenu), rebindAcceleratorsMenuItem, user_data); |
|
} |
|
} |
|
} |
|
|
|
// When the Menubar is hidden, accelerators no longer work so rebind them to the MainWindow |
|
// It should be called after all plugins have been initialised so that their injected menu items are captured |
|
void MainWindow::rebindMenubarAccelerators() { |
|
this->globalAccelGroup = gtk_accel_group_new(); |
|
gtk_window_add_accel_group(GTK_WINDOW(this->getWindow()), this->globalAccelGroup); |
|
|
|
GtkMenuBar* menuBar = (GtkMenuBar*)this->get("mainMenubar"); |
|
gtk_container_foreach(reinterpret_cast<GtkContainer*>(menuBar), rebindAcceleratorsSubMenu, this->globalAccelGroup); |
|
} |
|
|
|
MainWindow::~MainWindow() { |
|
for (int i = 0; i < TOOLBAR_DEFINITIONS_LEN; i++) { |
|
g_object_unref(this->toolbarWidgets[i]); |
|
} |
|
|
|
delete[] this->toolbarWidgets; |
|
this->toolbarWidgets = nullptr; |
|
|
|
delete this->toolbarSelectMenu; |
|
this->toolbarSelectMenu = nullptr; |
|
|
|
delete this->floatingToolbox; |
|
this->floatingToolbox = nullptr; |
|
|
|
delete this->xournal; |
|
this->xournal = nullptr; |
|
|
|
delete this->toolbar; |
|
this->toolbar = nullptr; |
|
|
|
delete scrollHandling; |
|
scrollHandling = nullptr; |
|
} |
|
|
|
/** |
|
* Topmost widgets, to check if there is a menu above |
|
*/ |
|
const char* TOP_WIDGETS[] = {"tbTop1", "tbTop2", "mainContainerBox", nullptr}; |
|
|
|
|
|
void MainWindow::toggleMenuBar(MainWindow* win) { |
|
GtkWidget* menu = win->get("mainMenubar"); |
|
if (gtk_widget_is_visible(menu)) { |
|
gtk_widget_hide(menu); |
|
} else { |
|
gtk_widget_show(menu); |
|
} |
|
} |
|
|
|
void MainWindow::initXournalWidget() { |
|
GtkWidget* boxContents = get("boxContents"); |
|
|
|
if (control->getSettings()->isTouchWorkaround()) { |
|
GtkWidget* box1 = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); |
|
gtk_container_add(GTK_CONTAINER(boxContents), box1); |
|
|
|
GtkWidget* box2 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); |
|
gtk_container_add(GTK_CONTAINER(box1), box2); |
|
|
|
scrollHandling = new ScrollHandlingXournalpp(); |
|
|
|
this->xournal = new XournalView(box2, control, scrollHandling); |
|
|
|
gtk_container_add(GTK_CONTAINER(box2), |
|
gtk_scrollbar_new(GTK_ORIENTATION_VERTICAL, scrollHandling->getVertical())); |
|
gtk_container_add(GTK_CONTAINER(box1), |
|
gtk_scrollbar_new(GTK_ORIENTATION_HORIZONTAL, scrollHandling->getHorizontal())); |
|
|
|
control->getZoomControl()->initZoomHandler(box2, xournal, control); |
|
gtk_widget_show_all(box1); |
|
} else { |
|
winXournal = gtk_scrolled_window_new(nullptr, nullptr); |
|
|
|
setTouchscreenScrollingForDeviceMapping(); |
|
|
|
gtk_container_add(GTK_CONTAINER(boxContents), winXournal); |
|
|
|
GtkWidget* vpXournal = gtk_viewport_new(nullptr, nullptr); |
|
|
|
gtk_container_add(GTK_CONTAINER(winXournal), vpXournal); |
|
|
|
scrollHandling = new ScrollHandlingGtk(GTK_SCROLLABLE(vpXournal)); |
|
|
|
this->xournal = new XournalView(vpXournal, control, scrollHandling); |
|
|
|
control->getZoomControl()->initZoomHandler(winXournal, xournal, control); |
|
gtk_widget_show_all(winXournal); |
|
} |
|
// Todo configure-event |
|
|
|
Layout* layout = gtk_xournal_get_layout(this->xournal->getWidget()); |
|
scrollHandling->init(this->xournal->getWidget(), layout); |
|
} |
|
|
|
void MainWindow::setTouchscreenScrollingForDeviceMapping() { |
|
for (InputDevice const& inputDevice: DeviceListHelper::getDeviceList(this->getControl()->getSettings())) { |
|
InputDeviceClass deviceClass = InputEvents::translateDeviceType(inputDevice.getName(), inputDevice.getSource(), |
|
this->getControl()->getSettings()); |
|
if (inputDevice.getSource() == GDK_SOURCE_TOUCHSCREEN && deviceClass != INPUT_DEVICE_TOUCHSCREEN) { |
|
gtk_scrolled_window_set_kinetic_scrolling(GTK_SCROLLED_WINDOW(winXournal), false); |
|
break; |
|
} |
|
} |
|
} |
|
|
|
/** |
|
* Allow to hide menubar, but only if global menu is not enabled |
|
*/ |
|
void MainWindow::initHideMenu() { |
|
int top = -1; |
|
for (int i = 0; TOP_WIDGETS[i]; i++) { |
|
GtkWidget* w = get(TOP_WIDGETS[i]); |
|
GtkAllocation allocation; |
|
gtk_widget_get_allocation(w, &allocation); |
|
if (allocation.y != -1) { |
|
top = allocation.y; |
|
break; |
|
} |
|
} |
|
|
|
GtkWidget* menuItem = get("menuHideMenu"); |
|
if (top < 5) { |
|
// There is no menu to hide, the menu is in the globalmenu! |
|
gtk_widget_hide(menuItem); |
|
} else { |
|
// Menu found, allow to hide it |
|
g_signal_connect(menuItem, "activate", |
|
G_CALLBACK(+[](GtkMenuItem* menuitem, MainWindow* self) { toggleMenuBar(self); }), this); |
|
} |
|
|
|
// Hide menubar at startup if specified in settings |
|
Settings* settings = control->getSettings(); |
|
if (settings && !settings->isMenubarVisible()) { |
|
toggleMenuBar(this); |
|
} |
|
} |
|
|
|
auto MainWindow::getLayout() -> Layout* { return gtk_xournal_get_layout(GTK_WIDGET(this->xournal->getWidget())); } |
|
|
|
auto cancellable_cancel(GCancellable* cancel) -> bool { |
|
g_cancellable_cancel(cancel); |
|
|
|
g_warning("Timeout... Cancel loading URL"); |
|
|
|
return false; |
|
} |
|
|
|
void MainWindow::dragDataRecived(GtkWidget* widget, GdkDragContext* dragContext, gint x, gint y, GtkSelectionData* data, |
|
guint info, guint time, MainWindow* win) { |
|
GtkWidget* source = gtk_drag_get_source_widget(dragContext); |
|
if (source && widget == gtk_widget_get_toplevel(source)) { |
|
gtk_drag_finish(dragContext, false, false, time); |
|
return; |
|
} |
|
|
|
guchar* text = gtk_selection_data_get_text(data); |
|
if (text) { |
|
win->control->clipboardPasteText(reinterpret_cast<const char*>(text)); |
|
|
|
g_free(text); |
|
gtk_drag_finish(dragContext, true, false, time); |
|
return; |
|
} |
|
|
|
GdkPixbuf* image = gtk_selection_data_get_pixbuf(data); |
|
if (image) { |
|
win->control->clipboardPasteImage(image); |
|
|
|
g_object_unref(image); |
|
gtk_drag_finish(dragContext, true, false, time); |
|
return; |
|
} |
|
|
|
gchar** uris = gtk_selection_data_get_uris(data); |
|
if (uris) { |
|
for (int i = 0; uris[i] != nullptr && i < 3; i++) { |
|
const char* uri = uris[i]; |
|
|
|
GCancellable* cancel = g_cancellable_new(); |
|
int cancelTimeout = g_timeout_add(3000, reinterpret_cast<GSourceFunc>(cancellable_cancel), cancel); |
|
|
|
GFile* file = g_file_new_for_uri(uri); |
|
GError* err = nullptr; |
|
GFileInputStream* in = g_file_read(file, cancel, &err); |
|
if (g_cancellable_is_cancelled(cancel)) { |
|
continue; |
|
} |
|
|
|
g_object_unref(file); |
|
if (err == nullptr) { |
|
GdkPixbuf* pixbuf = gdk_pixbuf_new_from_stream(G_INPUT_STREAM(in), cancel, nullptr); |
|
if (g_cancellable_is_cancelled(cancel)) { |
|
continue; |
|
} |
|
g_input_stream_close(G_INPUT_STREAM(in), cancel, nullptr); |
|
if (g_cancellable_is_cancelled(cancel)) { |
|
continue; |
|
} |
|
|
|
if (pixbuf) { |
|
win->control->clipboardPasteImage(pixbuf); |
|
|
|
g_object_unref(pixbuf); |
|
} |
|
} else { |
|
g_error_free(err); |
|
} |
|
|
|
if (!g_cancellable_is_cancelled(cancel)) { |
|
g_source_remove(cancelTimeout); |
|
} |
|
g_object_unref(cancel); |
|
} |
|
|
|
gtk_drag_finish(dragContext, true, false, time); |
|
|
|
g_strfreev(uris); |
|
} |
|
|
|
gtk_drag_finish(dragContext, false, false, time); |
|
} |
|
|
|
void MainWindow::viewShowSidebar(GtkCheckMenuItem* checkmenuitem, MainWindow* win) { |
|
bool a = gtk_check_menu_item_get_active(checkmenuitem); |
|
if (win->control->getSettings()->isSidebarVisible() == a) { |
|
return; |
|
} |
|
win->setSidebarVisible(a); |
|
} |
|
|
|
void MainWindow::viewShowToolbar(GtkCheckMenuItem* checkmenuitem, MainWindow* win) { |
|
bool showToolbar = gtk_check_menu_item_get_active(checkmenuitem); |
|
if (win->control->getSettings()->isToolbarVisible() == showToolbar) { |
|
return; |
|
} |
|
win->setToolbarVisible(showToolbar); |
|
} |
|
|
|
auto MainWindow::getControl() -> Control* { return control; } |
|
|
|
void MainWindow::updateScrollbarSidebarPosition() { |
|
GtkWidget* panelMainContents = get("panelMainContents"); |
|
|
|
if (winXournal != nullptr) { |
|
GtkScrolledWindow* scrolledWindow = GTK_SCROLLED_WINDOW(winXournal); |
|
|
|
ScrollbarHideType type = this->getControl()->getSettings()->getScrollbarHideType(); |
|
|
|
bool scrollbarOnLeft = control->getSettings()->isScrollbarOnLeft(); |
|
if (scrollbarOnLeft) { |
|
gtk_scrolled_window_set_placement(scrolledWindow, GTK_CORNER_TOP_RIGHT); |
|
} else { |
|
gtk_scrolled_window_set_placement(scrolledWindow, GTK_CORNER_TOP_LEFT); |
|
} |
|
|
|
gtk_widget_set_visible(gtk_scrolled_window_get_hscrollbar(scrolledWindow), !(type & SCROLLBAR_HIDE_HORIZONTAL)); |
|
gtk_widget_set_visible(gtk_scrolled_window_get_vscrollbar(scrolledWindow), !(type & SCROLLBAR_HIDE_VERTICAL)); |
|
|
|
gtk_scrolled_window_set_overlay_scrolling(scrolledWindow, |
|
!control->getSettings()->isScrollbarFadeoutDisabled()); |
|
} |
|
|
|
GtkWidget* sidebar = get("sidebar"); |
|
GtkWidget* boxContents = get("boxContents"); |
|
|
|
int divider = gtk_paned_get_position(GTK_PANED(panelMainContents)); |
|
bool sidebarRight = control->getSettings()->isSidebarOnRight(); |
|
if (sidebarRight == (gtk_paned_get_child2(GTK_PANED(panelMainContents)) == sidebar)) { |
|
// Already correct |
|
return; |
|
} |
|
|
|
|
|
GtkAllocation allocation; |
|
gtk_widget_get_allocation(panelMainContents, &allocation); |
|
divider = allocation.width - divider; |
|
|
|
|
|
g_object_ref(sidebar); |
|
g_object_ref(boxContents); |
|
|
|
gtk_container_remove(GTK_CONTAINER(panelMainContents), sidebar); |
|
gtk_container_remove(GTK_CONTAINER(panelMainContents), boxContents); |
|
|
|
if (sidebarRight) { |
|
gtk_paned_pack1(GTK_PANED(panelMainContents), boxContents, true, false); |
|
gtk_paned_pack2(GTK_PANED(panelMainContents), sidebar, false, false); |
|
} else { |
|
gtk_paned_pack1(GTK_PANED(panelMainContents), sidebar, false, false); |
|
gtk_paned_pack2(GTK_PANED(panelMainContents), boxContents, true, false); |
|
} |
|
|
|
gtk_paned_set_position(GTK_PANED(panelMainContents), divider); |
|
g_object_unref(sidebar); |
|
g_object_unref(boxContents); |
|
} |
|
|
|
void MainWindow::buttonCloseSidebarClicked(GtkButton* button, MainWindow* win) { win->setSidebarVisible(false); } |
|
|
|
auto MainWindow::onKeyPressCallback(GtkWidget* widget, GdkEventKey* event, MainWindow* win) -> bool { |
|
|
|
if (win->getXournal()->getSelection()) { |
|
// something is selected - give that control |
|
return false; |
|
} |
|
if (win->getXournal()->getTextEditor()) { |
|
// editing text - give that control |
|
return false; |
|
} |
|
if (event->keyval == GDK_KEY_Escape) { |
|
win->getControl()->getSearchBar()->showSearchBar(false); |
|
return true; |
|
} |
|
|
|
|
|
return false; |
|
} |
|
|
|
auto MainWindow::deleteEventCallback(GtkWidget* widget, GdkEvent* event, Control* control) -> bool { |
|
control->quit(); |
|
|
|
return true; |
|
} |
|
|
|
void MainWindow::setSidebarVisible(bool visible) { |
|
Settings* settings = control->getSettings(); |
|
GtkWidget* sidebar = get("sidebar"); |
|
GtkWidget* panel = get("panelMainContents"); |
|
|
|
gtk_widget_set_visible(sidebar, visible); |
|
settings->setSidebarVisible(visible); |
|
|
|
if (!visible && (control->getSidebar() != nullptr)) { |
|
saveSidebarSize(); |
|
} |
|
|
|
if (visible) { |
|
gtk_paned_set_position(GTK_PANED(panel), settings->getSidebarWidth()); |
|
} |
|
|
|
GtkWidget* w = get("menuViewSidebarVisible"); |
|
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(w), visible); |
|
} |
|
|
|
void MainWindow::setToolbarVisible(bool visible) { |
|
Settings* settings = control->getSettings(); |
|
|
|
settings->setToolbarVisible(visible); |
|
for (int i = 0; i < TOOLBAR_DEFINITIONS_LEN; i++) { |
|
gtk_widget_set_visible(this->toolbarWidgets[i], visible); |
|
} |
|
|
|
GtkWidget* w = get("menuViewToolbarsVisible"); |
|
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(w), visible); |
|
} |
|
|
|
void MainWindow::saveSidebarSize() { |
|
GtkWidget* panel = get("panelMainContents"); |
|
|
|
this->control->getSettings()->setSidebarWidth(gtk_paned_get_position(GTK_PANED(panel))); |
|
} |
|
|
|
void MainWindow::setMaximized(bool maximized) { this->maximized = maximized; } |
|
|
|
auto MainWindow::isMaximized() const -> bool { return this->maximized; } |
|
|
|
auto MainWindow::getXournal() -> XournalView* { return xournal; } |
|
|
|
auto MainWindow::windowStateEventCallback(GtkWidget* window, GdkEventWindowState* event, MainWindow* win) -> bool { |
|
win->setMaximized(gtk_window_is_maximized(GTK_WINDOW(window))); |
|
|
|
return false; |
|
} |
|
|
|
void MainWindow::reloadToolbars() { |
|
bool inDragAndDrop = this->control->isInDragAndDropToolbar(); |
|
|
|
ToolbarData* d = getSelectedToolbar(); |
|
|
|
if (inDragAndDrop) { |
|
this->control->endDragDropToolbar(); |
|
} |
|
|
|
this->clearToolbar(); |
|
this->toolbarSelected(d); |
|
|
|
if (inDragAndDrop) { |
|
this->control->startDragDropToolbar(); |
|
} |
|
} |
|
|
|
void MainWindow::toolbarSelected(ToolbarData* d) { |
|
if (!this->toolbarIntialized || this->selectedToolbar == d) { |
|
return; |
|
} |
|
|
|
Settings* settings = control->getSettings(); |
|
settings->setSelectedToolbar(d->getId()); |
|
|
|
this->clearToolbar(); |
|
this->loadToolbar(d); |
|
} |
|
|
|
auto MainWindow::clearToolbar() -> ToolbarData* { |
|
if (this->selectedToolbar != nullptr) { |
|
for (int i = 0; i < TOOLBAR_DEFINITIONS_LEN; i++) { |
|
ToolMenuHandler::unloadToolbar(this->toolbarWidgets[i]); |
|
} |
|
|
|
this->toolbar->freeDynamicToolbarItems(); |
|
} |
|
|
|
ToolbarData* oldData = this->selectedToolbar; |
|
|
|
this->selectedToolbar = nullptr; |
|
|
|
return oldData; |
|
} |
|
|
|
void MainWindow::loadToolbar(ToolbarData* d) { |
|
this->selectedToolbar = d; |
|
|
|
for (int i = 0; i < TOOLBAR_DEFINITIONS_LEN; i++) { |
|
this->toolbar->load(d, this->toolbarWidgets[i], TOOLBAR_DEFINITIONS[i].propName, |
|
TOOLBAR_DEFINITIONS[i].horizontal); |
|
} |
|
|
|
this->floatingToolbox->flagRecalculateSizeRequired(); |
|
} |
|
|
|
auto MainWindow::getSelectedToolbar() -> ToolbarData* { return this->selectedToolbar; } |
|
|
|
auto MainWindow::getToolbarWidgets(int& length) -> GtkWidget** { |
|
length = TOOLBAR_DEFINITIONS_LEN; |
|
return this->toolbarWidgets; |
|
} |
|
|
|
auto MainWindow::getToolbarName(GtkToolbar* toolbar) -> const char* { |
|
for (int i = 0; i < TOOLBAR_DEFINITIONS_LEN; i++) { |
|
if (static_cast<void*>(this->toolbarWidgets[i]) == static_cast<void*>(toolbar)) { |
|
return TOOLBAR_DEFINITIONS[i].propName; |
|
} |
|
} |
|
|
|
return ""; |
|
} |
|
|
|
void MainWindow::setControlTmpDisabled(bool disabled) { |
|
toolbar->setTmpDisabled(disabled); |
|
toolbarSelectMenu->setTmpDisabled(disabled); |
|
|
|
GtkWidget* menuFileRecent = get("menuFileRecent"); |
|
gtk_widget_set_sensitive(menuFileRecent, !disabled); |
|
} |
|
|
|
void MainWindow::updateToolbarMenu() { createToolbarAndMenu(); } |
|
|
|
void MainWindow::createToolbarAndMenu() { |
|
GtkMenuShell* menubar = GTK_MENU_SHELL(get("menuViewToolbar")); |
|
g_return_if_fail(menubar != nullptr); |
|
|
|
toolbarSelectMenu->updateToolbarMenu(menubar, control->getSettings(), toolbar); |
|
|
|
ToolbarData* td = toolbarSelectMenu->getSelectedToolbar(); |
|
if (td) { |
|
this->toolbarIntialized = true; |
|
toolbarSelected(td); |
|
} |
|
|
|
if (!this->control->getAudioController()->isPlaying()) { |
|
this->getToolMenuHandler()->disableAudioPlaybackButtons(); |
|
} |
|
|
|
this->control->getScheduler()->unblockRerenderZoom(); |
|
} |
|
|
|
void MainWindow::setFontButtonFont(XojFont& font) { toolbar->setFontButtonFont(font); } |
|
|
|
auto MainWindow::getFontButtonFont() -> XojFont { return toolbar->getFontButtonFont(); } |
|
|
|
void MainWindow::updatePageNumbers(size_t page, size_t pagecount, size_t pdfpage) { |
|
SpinPageAdapter* spinPageNo = getSpinPageNo(); |
|
|
|
size_t min = 0; |
|
size_t max = pagecount; |
|
|
|
if (pagecount == 0) { |
|
min = 0; |
|
page = 0; |
|
} else { |
|
min = 1; |
|
page++; |
|
} |
|
|
|
spinPageNo->setMinMaxPage(min, max); |
|
spinPageNo->setPage(page); |
|
|
|
string pdfText; |
|
if (pdfpage != npos) { |
|
pdfText = string(", ") + FS(_F("PDF Page {1}") % (pdfpage + 1)); |
|
} |
|
toolbar->setPageText(FS(C_F("Page {pagenumber} \"of {pagecount}\"", " of {1}{2}") % pagecount % pdfText)); |
|
} |
|
|
|
void MainWindow::rebuildLayerMenu() { layerVisibilityChanged(); } |
|
|
|
void MainWindow::layerVisibilityChanged() { |
|
LayerController* lc = control->getLayerController(); |
|
|
|
int layer = lc->getCurrentLayerId(); |
|
int maxLayer = lc->getLayerCount(); |
|
|
|
control->fireEnableAction(ACTION_DELETE_LAYER, layer > 0); |
|
control->fireEnableAction(ACTION_GOTO_NEXT_LAYER, layer < maxLayer); |
|
control->fireEnableAction(ACTION_GOTO_PREVIOUS_LAYER, layer > 0); |
|
control->fireEnableAction(ACTION_GOTO_TOP_LAYER, layer < maxLayer); |
|
} |
|
|
|
void MainWindow::setRecentMenu(GtkWidget* submenu) { |
|
GtkWidget* menuitem = get("menuFileRecent"); |
|
g_return_if_fail(menuitem != nullptr); |
|
gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), submenu); |
|
} |
|
|
|
void MainWindow::show(GtkWindow* parent) { gtk_widget_show(this->window); } |
|
|
|
void MainWindow::setUndoDescription(const string& description) { toolbar->setUndoDescription(description); } |
|
|
|
void MainWindow::setRedoDescription(const string& description) { toolbar->setRedoDescription(description); } |
|
|
|
auto MainWindow::getSpinPageNo() -> SpinPageAdapter* { return toolbar->getPageSpinner(); } |
|
|
|
auto MainWindow::getToolbarModel() -> ToolbarModel* { return this->toolbar->getModel(); } |
|
|
|
auto MainWindow::getToolMenuHandler() -> ToolMenuHandler* { return this->toolbar; } |
|
|
|
void MainWindow::disableAudioPlaybackButtons() { |
|
setAudioPlaybackPaused(false); |
|
|
|
this->getToolMenuHandler()->disableAudioPlaybackButtons(); |
|
} |
|
|
|
void MainWindow::enableAudioPlaybackButtons() { this->getToolMenuHandler()->enableAudioPlaybackButtons(); } |
|
|
|
void MainWindow::setAudioPlaybackPaused(bool paused) { this->getToolMenuHandler()->setAudioPlaybackPaused(paused); } |
|
|
|
void MainWindow::loadMainCSS(GladeSearchpath* gladeSearchPath, const gchar* cssFilename) { |
|
auto filepath = gladeSearchPath->findFile("", cssFilename); |
|
GtkCssProvider* provider = gtk_css_provider_new(); |
|
gtk_css_provider_load_from_path(provider, filepath.u8string().c_str(), nullptr); |
|
gtk_style_context_add_provider_for_screen(gdk_screen_get_default(), GTK_STYLE_PROVIDER(provider), |
|
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); |
|
g_object_unref(provider); |
|
}
|
|
|