canvas.cpp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. /* canvas.cpp - main canvas widget
  2. * Copyright (C) 2017-2018 caryoscelus
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation, either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. */
  17. #include <cmath>
  18. #include <fmt/format.h>
  19. #include <QGraphicsScene>
  20. #include <QGraphicsRectItem>
  21. #include <QWheelEvent>
  22. #include <QSlider>
  23. #include <QToolButton>
  24. #include <geom_helpers/knots.h>
  25. #include <core/node/abstract_value.h>
  26. #include <core/node/abstract_node.h>
  27. #include <core/document.h>
  28. #include <generic/canvas_editor.h>
  29. #include <generic/node_editor.h>
  30. #include <util/pen.h>
  31. #include "canvas.h"
  32. using namespace fmt::literals;
  33. namespace rainynite::studio {
  34. static const int SLIDER_FACTOR = 8;
  35. static const int MIN_ZOOM = 6; // x64
  36. static const int MAX_ZOOM = 8; // x256
  37. Canvas::Canvas(QWidget* parent) :
  38. AbstractCanvas(parent)
  39. {
  40. setDragMode(QGraphicsView::RubberBandDrag);
  41. image_border.reset(scene()->addRect(0, 0, 0, 0));
  42. image_border->setPen(pens::cosmetic_dash());
  43. setResizeAnchor(QGraphicsView::NoAnchor);
  44. setTransformationAnchor(QGraphicsView::NoAnchor);
  45. setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
  46. setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
  47. zoom_slider.reset(new QSlider(Qt::Horizontal, this));
  48. zoom_slider->setRange(-SLIDER_FACTOR*MIN_ZOOM, SLIDER_FACTOR*MAX_ZOOM);
  49. zoom_reset.reset(new QToolButton(this));
  50. zoom_reset->setIcon(QIcon::fromTheme("zoom-reset"));
  51. zoom_reset->setToolTip("Reset zoom to 100%");
  52. connect(
  53. zoom_slider.get(),
  54. &QSlider::valueChanged,
  55. [this] (int value) {
  56. set_zoom(std::pow(2, value*1.0/SLIDER_FACTOR));
  57. }
  58. );
  59. connect(
  60. zoom_reset.get(),
  61. &QAbstractButton::clicked,
  62. [this]() {
  63. set_zoom(1.0);
  64. }
  65. );
  66. connect(
  67. this,
  68. &AbstractCanvas::zoomed,
  69. [this]() {
  70. auto old_lock = zoom_slider->blockSignals(true);
  71. zoom_slider->setValue(std::log2(zoom_level())*SLIDER_FACTOR);
  72. zoom_slider->blockSignals(old_lock);
  73. }
  74. );
  75. }
  76. Canvas::~Canvas() {
  77. }
  78. void Canvas::set_context(shared_ptr<EditorContext> context) {
  79. ContextListener::set_context(context);
  80. // TODO: listen to document change
  81. // TODO: possible *nullptr
  82. get_core_context()->get_document_node()->get_property("size")->subscribe(
  83. [this]() {
  84. update_border();
  85. }
  86. );
  87. list_cast(get_core_context()->get_document())->subscribe_to_link_change(
  88. [this]() {
  89. update_border();
  90. }
  91. );
  92. update_border();
  93. }
  94. void Canvas::active_node_index_changed(core::NodeTreeIndex index) {
  95. if (active_node_index != index) {
  96. // TODO: handle selection
  97. active_node_index = index;
  98. clear_editors();
  99. add_canvas_node_editor(*this, index);
  100. }
  101. }
  102. void Canvas::resizeEvent(QResizeEvent* event) {
  103. auto pos = event->size();
  104. zoom_slider->setGeometry({
  105. pos.width()-128,
  106. pos.height()-16,
  107. 128,
  108. 16
  109. });
  110. zoom_reset->setGeometry({
  111. pos.width()-144,
  112. pos.height()-16,
  113. 16,
  114. 16
  115. });
  116. }
  117. void Canvas::update_border() {
  118. auto size = get_core_context()->get_document_node()->get_property_value<Geom::Point>("size", get_core_context()).value_or(Geom::Point{});
  119. auto w = size.x();
  120. auto h = size.y();
  121. image_border->setRect(0, 0, w, h);
  122. setSceneRect(-w*2, -h*2, w*5, h*5);
  123. }
  124. } // namespace rainynite::studio