#include "LayerController.h" #include #include "control/Control.h" #include "gui/XournalView.h" #include "undo/InsertLayerUndoAction.h" #include "undo/MoveLayerUndoAction.h" #include "undo/RemoveLayerUndoAction.h" #include "LayerCtrlListener.h" #include "Util.h" #include "i18n.h" LayerController::LayerController(Control* control): control(control), selectedPage(npos) {} void LayerController::documentChanged(DocumentChangeType type) { if (type == DOCUMENT_CHANGE_CLEARED || type == DOCUMENT_CHANGE_COMPLETE) { fireRebuildLayerMenu(); } } void LayerController::pageSelected(size_t page) { if (selectedPage == page) { return; } selectedPage = page; fireRebuildLayerMenu(); } void LayerController::insertLayer(PageRef page, Layer* layer, int layerPos) { page->insertLayer(layer, layerPos); fireRebuildLayerMenu(); } void LayerController::removeLayer(PageRef page, Layer* layer) { page->removeLayer(layer); fireRebuildLayerMenu(); } void LayerController::addLayer(PageRef page, Layer* layer) { page->addLayer(layer); fireRebuildLayerMenu(); } void LayerController::addListener(LayerCtrlListener* listener) { this->listener.push_back(listener); } void LayerController::removeListener(LayerCtrlListener* listener) { this->listener.remove(listener); } void LayerController::fireRebuildLayerMenu() { for (LayerCtrlListener* l: this->listener) { l->rebuildLayerMenu(); } } void LayerController::fireLayerVisibilityChanged() { for (LayerCtrlListener* l: this->listener) { l->layerVisibilityChanged(); } } auto LayerController::actionPerformed(ActionType type) -> bool { switch (type) { case ACTION_NEW_LAYER: addNewLayer(); return true; case ACTION_DELETE_LAYER: deleteCurrentLayer(); return true; case ACTION_FOOTER_LAYER: // This event is not fired anymore // This controller is called directly return true; case ACTION_GOTO_NEXT_LAYER: { PageRef p = getCurrentPage(); int layer = p->getSelectedLayerId(); if (layer < static_cast(p->getLayerCount())) { switchToLay(layer + 1, true); } } return true; case ACTION_GOTO_PREVIOUS_LAYER: { PageRef p = getCurrentPage(); int layer = p->getSelectedLayerId(); if (layer > 0) { switchToLay(layer - 1, true); } } return true; case ACTION_GOTO_TOP_LAYER: { PageRef p = getCurrentPage(); switchToLay(p->getLayerCount(), true); } return true; case ACTION_RENAME_LAYER: { RenameLayerDialog dialog(control->getGladeSearchPath(), control->getUndoRedoHandler(), this, getCurrentPage()->getSelectedLayer()); dialog.show(control->getGtkWindow()); } return true; default: return false; } } /** * Show all layer on the current page */ void LayerController::showAllLayer() { hideOrHideAllLayer(true); } /** * Hide all layer on the current page */ void LayerController::hideAllLayer() { hideOrHideAllLayer(false); } /** * Show / Hide all layer on the current page */ void LayerController::hideOrHideAllLayer(bool show) { PageRef page = getCurrentPage(); for (size_t i = 1; i <= page->getLayerCount(); i++) { page->setLayerVisible(i, show); } fireLayerVisibilityChanged(); control->getWindow()->getXournal()->layerChanged(selectedPage); } void LayerController::addNewLayer() { control->clearSelectionEndText(); PageRef p = getCurrentPage(); if (!p) { return; } auto* l = new Layer(); int layerPos = p->getSelectedLayerId(); p->insertLayer(l, layerPos); control->getUndoRedoHandler()->addUndoAction(std::make_unique(this, p, l, layerPos)); fireRebuildLayerMenu(); // Repaint is not needed here - the new layer is empty } void LayerController::deleteCurrentLayer() { control->clearSelectionEndText(); PageRef p = getCurrentPage(); int pId = selectedPage; if (!p) { return; } int lId = p->getSelectedLayerId(); if (lId < 1) { return; } Layer* l = p->getSelectedLayer(); p->removeLayer(l); MainWindow* win = control->getWindow(); if (win) { win->getXournal()->layerChanged(pId); } control->getUndoRedoHandler()->addUndoAction(std::make_unique(this, p, l, lId - 1)); control->resetShapeRecognizer(); fireRebuildLayerMenu(); } void LayerController::moveCurrentLayer(bool up) { control->clearSelectionEndText(); PageRef p = getCurrentPage(); int pId = selectedPage; if (!p) { return; } int lId = p->getSelectedLayerId(); Layer* currentLayer = p->getSelectedLayer(); if (lId < 1) { // Background cannot be moved return; } if (lId < 2 && !up) { // bottom layer cannot be moved down return; } if (lId == static_cast(p->getLayerCount()) && up) { // top layer cannot be moved up return; } p->removeLayer(currentLayer); // Layer IDs are a bit strange, because background is 0 // so the first layer is 1, technical the first layer is still // index 0 in the vector... confusing... int newIndex = up ? lId : lId - 2; p->insertLayer(currentLayer, newIndex); MainWindow* win = control->getWindow(); if (win) { win->getXournal()->layerChanged(pId); } control->getUndoRedoHandler()->addUndoAction( std::make_unique(this, p, currentLayer, lId - 1, newIndex)); fireRebuildLayerMenu(); } void LayerController::copyCurrentLayer() { control->clearSelectionEndText(); PageRef p = getCurrentPage(); int pId = selectedPage; if (!p) { return; } int lId = p->getSelectedLayerId(); if (lId < 1) { return; } Layer* l = p->getSelectedLayer(); Layer* cloned = l->clone(); p->insertLayer(cloned, lId); MainWindow* win = control->getWindow(); if (win) { win->getXournal()->layerChanged(pId); } control->getUndoRedoHandler()->addUndoAction(std::make_unique(this, p, cloned, lId)); control->resetShapeRecognizer(); fireRebuildLayerMenu(); } auto LayerController::getCurrentPage() -> PageRef { return control->getDocument()->getPage(selectedPage); } auto LayerController::getCurrentPageId() const -> size_t { return selectedPage; } void LayerController::setLayerVisible(int layerId, bool visible) { getCurrentPage()->setLayerVisible(layerId, visible); fireLayerVisibilityChanged(); control->getWindow()->getXournal()->layerChanged(selectedPage); } /** * Switch to a layer * * @param hideShow Auto hide / show other layers, * as it was before the advance layer menu */ void LayerController::switchToLay(int layer, bool hideShow) { control->clearSelectionEndText(); PageRef p = getCurrentPage(); if (!p) { return; } p->setSelectedLayerId(layer); if (hideShow) { for (size_t i = 1; i <= p->getLayerCount(); i++) { p->setLayerVisible(i, static_cast(i) <= layer); } } // Repaint page control->getWindow()->getXournal()->layerChanged(selectedPage); fireLayerVisibilityChanged(); } /** * @return Layer count of the current page */ auto LayerController::getLayerCount() -> size_t { PageRef page = getCurrentPage(); if (!page) { return 0; } return page->getLayerCount(); } /** * @return Current layer ID */ auto LayerController::getCurrentLayerId() -> size_t { PageRef page = getCurrentPage(); if (!page) { return 0; } return page->getSelectedLayerId(); } auto LayerController::getCurrentLayerName() -> std::string { PageRef page = getCurrentPage(); if (page == nullptr) { return "Unknown layer name"; } auto currentID = getCurrentLayerId(); if (currentID == 0) { // If is background return page->getBackgroundName(); } else if (auto layer = page->getSelectedLayer(); layer->hasName()) { return layer->getName(); } else { return FS(_F("Layer {1}") % currentID); } } void LayerController::setCurrentLayerName(const std::string& newName) { PageRef page = getCurrentPage(); if (page == nullptr) { return; } if (getCurrentLayerId() == 0) { // Background page->setBackgroundName(newName); } else { // Any other layer page->getSelectedLayer()->setName(newName); } fireRebuildLayerMenu(); } std::string LayerController::getLayerNameById(int id) { PageRef page = getCurrentPage(); if (page == nullptr) { return "Unknown layer name"; } if (id == 0) { return page->getBackgroundName(); } int previousId = page->getSelectedLayerId(); if (previousId == id) { return getCurrentLayerName(); } page->setSelectedLayerId(id); std::string name = getCurrentLayerName(); page->setSelectedLayerId(previousId); return name; } /** * Make sure there is at least one layer on the page */ void LayerController::ensureLayerExists(PageRef page) { if (page->getSelectedLayerId() > 0) { return; } // This creates a layer if none exists page->getSelectedLayer(); page->setSelectedLayerId(1); fireRebuildLayerMenu(); }