diff --git a/stuff/config/qss/Blue/Blue.qss b/stuff/config/qss/Blue/Blue.qss index f733955..ad09a59 100644 --- a/stuff/config/qss/Blue/Blue.qss +++ b/stuff/config/qss/Blue/Blue.qss @@ -1193,30 +1193,49 @@ QGroupBox:disabled { /* ----------------------------------------------------------------------------- Slider ----------------------------------------------------------------------------- */ -.Slider::groove:horizontal, -QSlider::groove:horizontal { +.Slider::groove, +QSlider::groove { background-color: transparent; background-image: url('../Default/imgs/white/slider-groove.svg'); background-position: center center; - background-repeat: repeat-x; margin: 0; +} +.Slider::groove:horizontal, +QSlider::groove:horizontal { + background-repeat: repeat-x; height: 20; min-height: 20; } -.Slider::groove:horizontal:disabled, -QSlider::groove:horizontal:disabled { +.Slider::groove:vertical, +QSlider::groove:vertical { + background-repeat: repeat-y; + width: 20; + min-width: 20; +} +.Slider::groove:disabled, +QSlider::groove:disabled { background-image: url('../Default/imgs/white/slider-groove_disabled.svg'); } .Slider::handle:horizontal, QSlider::handle:horizontal { - width: 10; margin: -2 -1; + width: 10; image: url('../Default/imgs/white/slider-handle.svg'); } .Slider::handle:horizontal:disabled, QSlider::handle:horizontal:disabled { image: url('../Default/imgs/white/slider-handle_disabled.svg'); } +.Slider::handle:vertical, +QSlider::handle:vertical { + margin: -1 -2; + height: 10; + image: url('../Default/imgs/white/slider-v-handle.svg'); +} +.Slider::handle:vertical:disabled, +QSlider::handle:vertical:disabled { + image: url('../Default/imgs/white/slider-v-handle_disabled.svg'); +} /* ----------------------------------------------------------------------------- Double Slider ----------------------------------------------------------------------------- */ diff --git a/stuff/config/qss/Dark/Dark.qss b/stuff/config/qss/Dark/Dark.qss index d2564a4..80dc897 100644 --- a/stuff/config/qss/Dark/Dark.qss +++ b/stuff/config/qss/Dark/Dark.qss @@ -1193,30 +1193,49 @@ QGroupBox:disabled { /* ----------------------------------------------------------------------------- Slider ----------------------------------------------------------------------------- */ -.Slider::groove:horizontal, -QSlider::groove:horizontal { +.Slider::groove, +QSlider::groove { background-color: transparent; background-image: url('../Default/imgs/white/slider-groove_dark.svg'); background-position: center center; - background-repeat: repeat-x; margin: 0; +} +.Slider::groove:horizontal, +QSlider::groove:horizontal { + background-repeat: repeat-x; height: 20; min-height: 20; } -.Slider::groove:horizontal:disabled, -QSlider::groove:horizontal:disabled { +.Slider::groove:vertical, +QSlider::groove:vertical { + background-repeat: repeat-y; + width: 20; + min-width: 20; +} +.Slider::groove:disabled, +QSlider::groove:disabled { background-image: url('../Default/imgs/white/slider-groove_disabled_dark.svg'); } .Slider::handle:horizontal, QSlider::handle:horizontal { - width: 10; margin: -2 -1; + width: 10; image: url('../Default/imgs/white/slider-handle.svg'); } .Slider::handle:horizontal:disabled, QSlider::handle:horizontal:disabled { image: url('../Default/imgs/white/slider-handle_disabled.svg'); } +.Slider::handle:vertical, +QSlider::handle:vertical { + margin: -1 -2; + height: 10; + image: url('../Default/imgs/white/slider-v-handle.svg'); +} +.Slider::handle:vertical:disabled, +QSlider::handle:vertical:disabled { + image: url('../Default/imgs/white/slider-v-handle_disabled.svg'); +} /* ----------------------------------------------------------------------------- Double Slider ----------------------------------------------------------------------------- */ diff --git a/stuff/config/qss/Default/Default.qss b/stuff/config/qss/Default/Default.qss index 41ec273..a36989a 100644 --- a/stuff/config/qss/Default/Default.qss +++ b/stuff/config/qss/Default/Default.qss @@ -1193,30 +1193,49 @@ QGroupBox:disabled { /* ----------------------------------------------------------------------------- Slider ----------------------------------------------------------------------------- */ -.Slider::groove:horizontal, -QSlider::groove:horizontal { +.Slider::groove, +QSlider::groove { background-color: transparent; background-image: url('imgs/white/slider-groove.svg'); background-position: center center; - background-repeat: repeat-x; margin: 0; +} +.Slider::groove:horizontal, +QSlider::groove:horizontal { + background-repeat: repeat-x; height: 20; min-height: 20; } -.Slider::groove:horizontal:disabled, -QSlider::groove:horizontal:disabled { +.Slider::groove:vertical, +QSlider::groove:vertical { + background-repeat: repeat-y; + width: 20; + min-width: 20; +} +.Slider::groove:disabled, +QSlider::groove:disabled { background-image: url('imgs/white/slider-groove_disabled.svg'); } .Slider::handle:horizontal, QSlider::handle:horizontal { - width: 10; margin: -2 -1; + width: 10; image: url('imgs/white/slider-handle.svg'); } .Slider::handle:horizontal:disabled, QSlider::handle:horizontal:disabled { image: url('imgs/white/slider-handle_disabled.svg'); } +.Slider::handle:vertical, +QSlider::handle:vertical { + margin: -1 -2; + height: 10; + image: url('imgs/white/slider-v-handle.svg'); +} +.Slider::handle:vertical:disabled, +QSlider::handle:vertical:disabled { + image: url('imgs/white/slider-v-handle_disabled.svg'); +} /* ----------------------------------------------------------------------------- Double Slider ----------------------------------------------------------------------------- */ diff --git a/stuff/config/qss/Default/imgs/black/slider-v-handle.svg b/stuff/config/qss/Default/imgs/black/slider-v-handle.svg new file mode 100644 index 0000000..742e54a --- /dev/null +++ b/stuff/config/qss/Default/imgs/black/slider-v-handle.svg @@ -0,0 +1,55 @@ + +image/svg+xml + + + \ No newline at end of file diff --git a/stuff/config/qss/Default/imgs/black/slider-v-handle_disabled.svg b/stuff/config/qss/Default/imgs/black/slider-v-handle_disabled.svg new file mode 100644 index 0000000..28a9e3b --- /dev/null +++ b/stuff/config/qss/Default/imgs/black/slider-v-handle_disabled.svg @@ -0,0 +1,55 @@ + +image/svg+xml + + + \ No newline at end of file diff --git a/stuff/config/qss/Default/imgs/black/slider-v-handle_disabled_light.svg b/stuff/config/qss/Default/imgs/black/slider-v-handle_disabled_light.svg new file mode 100644 index 0000000..70f13b4 --- /dev/null +++ b/stuff/config/qss/Default/imgs/black/slider-v-handle_disabled_light.svg @@ -0,0 +1,55 @@ + +image/svg+xml + + + \ No newline at end of file diff --git a/stuff/config/qss/Default/imgs/black/slider-v-handle_light.svg b/stuff/config/qss/Default/imgs/black/slider-v-handle_light.svg new file mode 100644 index 0000000..0ab7dc1 --- /dev/null +++ b/stuff/config/qss/Default/imgs/black/slider-v-handle_light.svg @@ -0,0 +1,55 @@ + +image/svg+xml + + + \ No newline at end of file diff --git a/stuff/config/qss/Default/imgs/white/slider-v-handle.svg b/stuff/config/qss/Default/imgs/white/slider-v-handle.svg new file mode 100644 index 0000000..6f6e280 --- /dev/null +++ b/stuff/config/qss/Default/imgs/white/slider-v-handle.svg @@ -0,0 +1,62 @@ + + + +image/svg+xml + + + + + \ No newline at end of file diff --git a/stuff/config/qss/Default/imgs/white/slider-v-handle_disabled.svg b/stuff/config/qss/Default/imgs/white/slider-v-handle_disabled.svg new file mode 100644 index 0000000..cbfd8fc --- /dev/null +++ b/stuff/config/qss/Default/imgs/white/slider-v-handle_disabled.svg @@ -0,0 +1,62 @@ + + + +image/svg+xml + + + + + \ No newline at end of file diff --git a/stuff/config/qss/Default/less/Default.less b/stuff/config/qss/Default/less/Default.less index 49a65d2..ff01577 100644 --- a/stuff/config/qss/Default/less/Default.less +++ b/stuff/config/qss/Default/less/Default.less @@ -279,6 +279,8 @@ @slider-handle-width: 10; @slider-handle-img: 'slider-handle.svg'; @slider-handle-img-disabled: 'slider-handle_disabled.svg'; +@slider-v-handle-img: 'slider-v-handle.svg'; +@slider-v-handle-img-disabled: 'slider-v-handle_disabled.svg'; // This one is used only for #ViewerFpsSlider @slider-handle-margin: -2 -1; diff --git a/stuff/config/qss/Default/less/layouts/controls.less b/stuff/config/qss/Default/less/layouts/controls.less index fc8a32d..cd5d469 100644 --- a/stuff/config/qss/Default/less/layouts/controls.less +++ b/stuff/config/qss/Default/less/layouts/controls.less @@ -310,24 +310,41 @@ QGroupBox { ----------------------------------------------------------------------------- */ .Slider { - &::groove:horizontal { + &::groove{ background-color: transparent; background-image: url('@{img-url}/@{slider-groove-img}'); background-position: center center; - background-repeat: repeat-x; margin: 0; + &:horizontal { + background-repeat: repeat-x; height: 20; min-height: 20; + } + &:vertical { + background-repeat: repeat-y; + width: 20; + min-width: 20; + } &:disabled { background-image: url('@{img-url}/@{slider-groove-img-disabled}'); } } - &::handle:horizontal { + &::handle{ + &:horizontal { + margin: @slider-handle-margin; width: @slider-handle-width; - margin: @slider-handle-margin; image: url('@{img-url}/@{slider-handle-img}'); &:disabled { image: url('@{img-url}/@{slider-handle-img-disabled}'); + } + } + &:vertical { + margin: -1 -2; + height: @slider-handle-width; + image: url('@{img-url}/@{slider-v-handle-img}'); + &:disabled { + image: url('@{img-url}/@{slider-v-handle-img-disabled}'); + } } } } diff --git a/stuff/config/qss/Default/less/themes/Light.less b/stuff/config/qss/Default/less/themes/Light.less index 0abf22b..ba4c0f6 100644 --- a/stuff/config/qss/Default/less/themes/Light.less +++ b/stuff/config/qss/Default/less/themes/Light.less @@ -157,6 +157,8 @@ @slider-groove-img-disabled: 'slider-groove_disabled_light.svg'; @slider-handle-img: 'slider-handle_light.svg'; @slider-handle-img-disabled: 'slider-handle_disabled_light.svg'; +@slider-v-handle-img: 'slider-v-handle_light.svg'; +@slider-v-handle-img-disabled: 'slider-v-handle_disabled_light.svg'; // This one is used only for #ViewerFpsSlider @slider-handle-bg-color: lighten(@bg, -10); diff --git a/stuff/config/qss/Light/Light.qss b/stuff/config/qss/Light/Light.qss index 9d37d55..071172d 100644 --- a/stuff/config/qss/Light/Light.qss +++ b/stuff/config/qss/Light/Light.qss @@ -1193,30 +1193,49 @@ QGroupBox:disabled { /* ----------------------------------------------------------------------------- Slider ----------------------------------------------------------------------------- */ -.Slider::groove:horizontal, -QSlider::groove:horizontal { +.Slider::groove, +QSlider::groove { background-color: transparent; background-image: url('../Default/imgs/black/slider-groove_light.svg'); background-position: center center; - background-repeat: repeat-x; margin: 0; +} +.Slider::groove:horizontal, +QSlider::groove:horizontal { + background-repeat: repeat-x; height: 20; min-height: 20; } -.Slider::groove:horizontal:disabled, -QSlider::groove:horizontal:disabled { +.Slider::groove:vertical, +QSlider::groove:vertical { + background-repeat: repeat-y; + width: 20; + min-width: 20; +} +.Slider::groove:disabled, +QSlider::groove:disabled { background-image: url('../Default/imgs/black/slider-groove_disabled_light.svg'); } .Slider::handle:horizontal, QSlider::handle:horizontal { - width: 10; margin: -2 0; + width: 10; image: url('../Default/imgs/black/slider-handle_light.svg'); } .Slider::handle:horizontal:disabled, QSlider::handle:horizontal:disabled { image: url('../Default/imgs/black/slider-handle_disabled_light.svg'); } +.Slider::handle:vertical, +QSlider::handle:vertical { + margin: -1 -2; + height: 10; + image: url('../Default/imgs/black/slider-v-handle_light.svg'); +} +.Slider::handle:vertical:disabled, +QSlider::handle:vertical:disabled { + image: url('../Default/imgs/black/slider-v-handle_disabled_light.svg'); +} /* ----------------------------------------------------------------------------- Double Slider ----------------------------------------------------------------------------- */ diff --git a/stuff/config/qss/Neutral/Neutral.qss b/stuff/config/qss/Neutral/Neutral.qss index 9887d45..69f9e7c 100644 --- a/stuff/config/qss/Neutral/Neutral.qss +++ b/stuff/config/qss/Neutral/Neutral.qss @@ -1193,30 +1193,49 @@ QGroupBox:disabled { /* ----------------------------------------------------------------------------- Slider ----------------------------------------------------------------------------- */ -.Slider::groove:horizontal, -QSlider::groove:horizontal { +.Slider::groove, +QSlider::groove { background-color: transparent; background-image: url('../Default/imgs/black/slider-groove.svg'); background-position: center center; - background-repeat: repeat-x; margin: 0; +} +.Slider::groove:horizontal, +QSlider::groove:horizontal { + background-repeat: repeat-x; height: 20; min-height: 20; } -.Slider::groove:horizontal:disabled, -QSlider::groove:horizontal:disabled { +.Slider::groove:vertical, +QSlider::groove:vertical { + background-repeat: repeat-y; + width: 20; + min-width: 20; +} +.Slider::groove:disabled, +QSlider::groove:disabled { background-image: url('../Default/imgs/black/slider-groove_disabled.svg'); } .Slider::handle:horizontal, QSlider::handle:horizontal { - width: 10; margin: -2 0; + width: 10; image: url('../Default/imgs/black/slider-handle.svg'); } .Slider::handle:horizontal:disabled, QSlider::handle:horizontal:disabled { image: url('../Default/imgs/black/slider-handle_disabled.svg'); } +.Slider::handle:vertical, +QSlider::handle:vertical { + margin: -1 -2; + height: 10; + image: url('../Default/imgs/black/slider-v-handle.svg'); +} +.Slider::handle:vertical:disabled, +QSlider::handle:vertical:disabled { + image: url('../Default/imgs/black/slider-v-handle_disabled.svg'); +} /* ----------------------------------------------------------------------------- Double Slider ----------------------------------------------------------------------------- */ diff --git a/toonz/sources/include/orientation.h b/toonz/sources/include/orientation.h index 5f1130f..e95c2d2 100644 --- a/toonz/sources/include/orientation.h +++ b/toonz/sources/include/orientation.h @@ -116,10 +116,11 @@ enum class PredefinedRect { FILTER_COLOR, //! where to show layer's filter color CONFIG_AREA, //! clickable area larger than the config icon, containing it CONFIG, //! the config icon itself - CAMERA_CONFIG_AREA, //! config area for the camera column - CAMERA_CONFIG, //! the config icon for camera column - FRAME_MARKER_AREA, //! Cell's frame indicator - FRAME_INDICATOR, //! Row # indicator + CAMERA_CONFIG_AREA, //! config area for the camera column + CAMERA_CONFIG, //! the config icon for camera column + FRAME_MARKER_AREA, //! Cell's frame indicator + CAMERA_FRAME_MARKER_AREA, //! Cell's frame indicator for camera column + FRAME_INDICATOR, //! Row # indicator ZOOM_SLIDER_AREA, ZOOM_SLIDER, ZOOM_IN_AREA, @@ -151,7 +152,8 @@ enum class PredefinedDimension { ONION_TURN, //! onion handle turn in degrees QBOXLAYOUT_DIRECTION, //! direction of QBoxLayout CENTER_ALIGN, //! horizontal / vertical align - CAMERA_LAYER //! width of a camera column / height of camera row + CAMERA_LAYER, //! width of a camera column / height of camera row + SCALE_THRESHOLD //! scale threshold to simplify the view }; enum class PredefinedPath { DRAG_HANDLE_CORNER, //! triangle corner at drag sidebar @@ -213,11 +215,11 @@ protected: public: virtual CellPosition xyToPosition(const QPoint &xy, - const ColumnFan *fan) const = 0; + const ColumnFan *fan) const = 0; virtual QPoint positionToXY(const CellPosition &position, - const ColumnFan *fan) const = 0; - virtual CellPositionRatio xyToPositionRatio(const QPoint &xy) const = 0; - virtual QPoint positionRatioToXY(const CellPositionRatio &ratio) const = 0; + const ColumnFan *fan) const = 0; + virtual CellPositionRatio xyToPositionRatio(const QPointF &xy) const = 0; + virtual QPointF positionRatioToXY(const CellPositionRatio &ratio) const = 0; virtual int colToLayerAxis(int layer, const ColumnFan *fan) const = 0; virtual int rowToFrameAxis(int frame) const = 0; diff --git a/toonz/sources/include/toonz/cellpositionratio.h b/toonz/sources/include/toonz/cellpositionratio.h index a46d708..e37fcb4 100644 --- a/toonz/sources/include/toonz/cellpositionratio.h +++ b/toonz/sources/include/toonz/cellpositionratio.h @@ -15,34 +15,15 @@ #include "tcommon.h" -class DVAPI Ratio { - int m_num, m_denom; - - void normalize(); - Ratio normalized() const; - -public: - Ratio(int num, int denom); - - friend Ratio operator+(const Ratio &a, const Ratio &b); - friend Ratio operator-(const Ratio &a, const Ratio &b); - friend Ratio operator*(const Ratio &a, const Ratio &b); - friend Ratio operator/(const Ratio &a, const Ratio &b); - - friend int operator*(const Ratio &a, int b); - - bool operator!() const { return m_num == 0; } -}; - class DVAPI CellPositionRatio { - Ratio m_frame, m_layer; + double m_frameRatio, m_layerRatio; public: - CellPositionRatio(const Ratio &frame, const Ratio &layer) - : m_frame(frame), m_layer(layer) {} + CellPositionRatio(const double frameRatio, const double layerRatio) + : m_frameRatio(frameRatio), m_layerRatio(layerRatio) {} - Ratio frame() const { return m_frame; } - Ratio layer() const { return m_layer; } + double frame() const { return m_frameRatio; } + double layer() const { return m_layerRatio; } }; #endif diff --git a/toonz/sources/include/toonz/txsheethandle.h b/toonz/sources/include/toonz/txsheethandle.h index d851017..3c995c2 100644 --- a/toonz/sources/include/toonz/txsheethandle.h +++ b/toonz/sources/include/toonz/txsheethandle.h @@ -28,6 +28,7 @@ class DVAPI TXsheetHandle final : public QObject { Q_OBJECT TXsheet *m_xsheet; + int m_zoomFactor; public: TXsheetHandle(); @@ -39,12 +40,18 @@ public: void notifyXsheetSwitched() { emit xsheetSwitched(); } void notifyXsheetSoundChanged() { emit xsheetSoundChanged(); } void changeXsheetCamera(int index) { emit xsheetCameraChange(index); } + void notifyZoomScaleChanged(int factor) { + m_zoomFactor = factor; + emit zoomScaleChanged(); + } + int getZoomFactor() { return m_zoomFactor; } signals: void xsheetSwitched(); void xsheetChanged(); void xsheetSoundChanged(); void xsheetCameraChange(int); + void zoomScaleChanged(); }; #endif // TXSHEETHANDLE_H diff --git a/toonz/sources/include/toonzqt/functionsheet.h b/toonz/sources/include/toonzqt/functionsheet.h index acb2333..76f8259 100644 --- a/toonz/sources/include/toonzqt/functionsheet.h +++ b/toonz/sources/include/toonzqt/functionsheet.h @@ -27,6 +27,17 @@ class TDoubleParam; class TFrameHandle; class FunctionSelection; +class FunctionSheetButtonArea final : public QWidget { + Q_OBJECT + QPushButton *m_syncSizeBtn; + +public: + FunctionSheetButtonArea(QWidget *parent); + void setSyncSizeBtnState(bool); +signals: + void syncSizeBtnToggled(bool); +}; + class FunctionSheetRowViewer final : public Spreadsheet::RowPanel { FunctionSheet *m_sheet; @@ -98,7 +109,20 @@ private slots: class FunctionSheet final : public SpreadsheetViewer { Q_OBJECT + + FunctionSheetRowViewer *m_rowViewer; + FunctionSheetColumnHeadViewer *m_columnHeadViewer; + FunctionSheetCellViewer *m_cellViewer; + FunctionSelection *m_selection; + FunctionTreeModel *m_functionTreeModel; + FunctionViewer *m_functionViewer; + FunctionSheetButtonArea *m_buttonArea; + TXsheetHandle *m_xshHandle; + + QRect m_selectedCells; + bool m_isFloating; bool m_showIbtwnValue = true; + bool m_syncSize = true; public: FunctionSheet(QWidget *parent = 0, bool isFloating = false); @@ -138,21 +162,16 @@ public: update(); } + bool isSyncSize() { return m_syncSize; } + void setSyncSize(bool on); + void setXsheetHandle(TXsheetHandle *xshHandle) { m_xshHandle = xshHandle; } + + int getFrameZoomFactor() const override; + protected: void showEvent(QShowEvent *e) override; void hideEvent(QHideEvent *e) override; -private: - FunctionSheetRowViewer *m_rowViewer; - FunctionSheetColumnHeadViewer *m_columnHeadViewer; - FunctionSheetCellViewer *m_cellViewer; - FunctionSelection *m_selection; - FunctionTreeModel *m_functionTreeModel; - FunctionViewer *m_functionViewer; - - QRect m_selectedCells; - bool m_isFloating; - public slots: void updateAll(); @@ -160,6 +179,9 @@ public slots: /*--- * カレントChannelが切り替わったら、NumericalColumnsがそのChannelを表示できるようにスクロールする。---*/ void onCurrentChannelChanged(FunctionTreeModel::Channel *); + + void onSyncSizeBtnToggled(bool); + void onZoomScaleChanged(); }; #endif diff --git a/toonz/sources/include/toonzqt/spreadsheetviewer.h b/toonz/sources/include/toonzqt/spreadsheetviewer.h index 1ae6ed0..1d7fbab 100644 --- a/toonz/sources/include/toonzqt/spreadsheetviewer.h +++ b/toonz/sources/include/toonzqt/spreadsheetviewer.h @@ -61,7 +61,7 @@ public: void registerFrameScroller(); void unregisterFrameScroller(); - void prepareToScrollOthers(const QPoint &offset); + void prepareToScrollOthers(const QPointF &offset); void setSyncing(bool s) { m_syncing = s; } bool isSyncing() { return m_syncing; } @@ -79,8 +79,8 @@ private slots: void onVScroll(int value); void onHScroll(int value); signals: - void prepareToScrollOffset(const QPoint &offset); - void zoomScrollAdjust(QPoint &offset, bool toZoom); + void prepareToScrollOffset(const QPointF &offset); + void zoomScrollAdjust(QPointF &offset, bool toZoom); }; //------------------------------------------------------------------- @@ -303,6 +303,7 @@ class DVAPI SpreadsheetViewer : public QDialog { int m_columnWidth; int m_rowHeight; + int m_scaleFactor; // QPoint m_delta; int m_timerId; @@ -328,9 +329,12 @@ public: int getRowHeight() const { return m_rowHeight; } void setRowHeight(int height) { m_rowHeight = height; } + void setScaleFactor(int factor) { m_scaleFactor = factor; } + void setRowsPanel(Spreadsheet::RowPanel *rows); void setColumnsPanel(Spreadsheet::ColumnPanel *columns); void setCellsPanel(Spreadsheet::CellPanel *cells); + void setButtonAreaWidget(QWidget *widget); int getRowCount() const { return m_rowCount; } @@ -466,6 +470,8 @@ public: void ensureVisibleCol(int col); + virtual int getFrameZoomFactor() const { return 100; } + protected: void showEvent(QShowEvent *) override; void hideEvent(QHideEvent *) override; @@ -484,7 +490,9 @@ public slots: void onVSliderChanged(int); void onHSliderChanged(int); - void onPrepareToScrollOffset(const QPoint &offset); + void onPrepareToScrollOffset(const QPointF &offset); + void onZoomScrollAdjust(QPointF &offset, bool toZoom); + /* void updateAllAree(); void updateCellColumnAree(); diff --git a/toonz/sources/toonz/icons/dark/actions/17/syncscale.svg b/toonz/sources/toonz/icons/dark/actions/17/syncscale.svg new file mode 100644 index 0000000..4609a0f --- /dev/null +++ b/toonz/sources/toonz/icons/dark/actions/17/syncscale.svg @@ -0,0 +1,61 @@ + +image/svg+xml + + + + + + + + + \ No newline at end of file diff --git a/toonz/sources/toonz/layerfooterpanel.cpp b/toonz/sources/toonz/layerfooterpanel.cpp index 3c607ee..7ebeca7 100644 --- a/toonz/sources/toonz/layerfooterpanel.cpp +++ b/toonz/sources/toonz/layerfooterpanel.cpp @@ -26,20 +26,26 @@ LayerFooterPanel::LayerFooterPanel(XsheetViewer *viewer, QWidget *parent, Qt::WFlags flags) #endif : QWidget(parent, flags), m_viewer(viewer) { - const Orientation *o = Orientations::leftToRight(); - QRect rect = o->rect(PredefinedRect::LAYER_FOOTER_PANEL); + const Orientation *o = viewer->orientation(); setObjectName("layerFooterPanel"); - setFixedSize(rect.size()); - setMouseTracking(true); - m_frameZoomSlider = new QSlider(Qt::Horizontal, this); + Qt::Orientation ori = + (o->isVerticalTimeline()) ? Qt::Vertical : Qt::Horizontal; + bool invDirection = o->isVerticalTimeline(); + QString tooltipStr = (o->isVerticalTimeline()) + ? tr("Zoom in/out of xsheet") + : tr("Zoom in/out of timeline"); + + m_frameZoomSlider = new QSlider(ori, this); m_frameZoomSlider->setMinimum(20); m_frameZoomSlider->setMaximum(100); m_frameZoomSlider->setValue(m_viewer->getFrameZoomFactor()); - m_frameZoomSlider->setToolTip(tr("Zoom in/out of timeline")); + m_frameZoomSlider->setToolTip(tooltipStr); + m_frameZoomSlider->setInvertedAppearance(invDirection); + m_frameZoomSlider->setInvertedControls(invDirection); connect(m_frameZoomSlider, SIGNAL(valueChanged(int)), this, SLOT(onFrameZoomSliderValueChanged(int))); @@ -66,13 +72,13 @@ QRect shorter(const QRect original) { return original.adjusted(0, 2, 0, -2); } QLine leftSide(const QRect &r) { return QLine(r.topLeft(), r.bottomLeft()); } QLine rightSide(const QRect &r) { return QLine(r.topRight(), r.bottomRight()); } -} +} // namespace void LayerFooterPanel::paintEvent(QPaintEvent *event) { QPainter p(this); p.setRenderHint(QPainter::SmoothPixmapTransform, true); - const Orientation *o = Orientations::leftToRight(); + const Orientation *o = m_viewer->orientation(); QRect zoomSliderRect = o->rect(PredefinedRect::ZOOM_SLIDER_AREA); p.fillRect(zoomSliderRect, Qt::NoBrush); @@ -103,18 +109,29 @@ void LayerFooterPanel::paintEvent(QPaintEvent *event) { else p.drawPixmap(zoomOutImgRect, zoomOut); - p.setPen(m_viewer->getVerticalLineColor()); - - QLine line = {leftSide(shorter(zoomOutImgRect)).translated(-2, 0)}; - p.drawLine(line); + if (!o->isVerticalTimeline()) { + p.setPen(m_viewer->getVerticalLineColor()); + QLine line = {leftSide(shorter(zoomOutImgRect)).translated(-2, 0)}; + p.drawLine(line); + } } void LayerFooterPanel::showOrHide(const Orientation *o) { QRect rect = o->rect(PredefinedRect::LAYER_FOOTER_PANEL); - if (rect.isEmpty()) - hide(); - else - show(); + setFixedSize(rect.size()); + Qt::Orientation ori = + (o->isVerticalTimeline()) ? Qt::Vertical : Qt::Horizontal; + bool invDirection = o->isVerticalTimeline(); + QString tooltipStr = (o->isVerticalTimeline()) + ? tr("Zoom in/out of xsheet") + : tr("Zoom in/out of timeline"); + + m_frameZoomSlider->setOrientation(ori); + m_frameZoomSlider->setToolTip(tooltipStr); + m_frameZoomSlider->setInvertedAppearance(invDirection); + m_frameZoomSlider->setInvertedControls(invDirection); + + show(); } //----------------------------------------------------------------------------- @@ -133,7 +150,7 @@ void LayerFooterPanel::leaveEvent(QEvent *) { } void LayerFooterPanel::mousePressEvent(QMouseEvent *event) { - const Orientation *o = Orientations::leftToRight(); + const Orientation *o = m_viewer->orientation(); if (event->button() == Qt::LeftButton) { // get mouse position @@ -153,7 +170,7 @@ void LayerFooterPanel::mousePressEvent(QMouseEvent *event) { } void LayerFooterPanel::mouseMoveEvent(QMouseEvent *event) { - const Orientation *o = Orientations::leftToRight(); + const Orientation *o = m_viewer->orientation(); QPoint pos = event->pos(); @@ -188,6 +205,28 @@ bool LayerFooterPanel::event(QEvent *event) { //----------------------------------------------------------------------------- +void LayerFooterPanel::contextMenuEvent(QContextMenuEvent *event) { + if (!m_viewer->orientation()->isVerticalTimeline()) { + event->ignore(); + return; + } + + QList frames = m_viewer->availableFramesPerPage(); + if (frames.isEmpty()) { + return; + } + + QMenu *menu = new QMenu(this); + for (auto frame : frames) { + QAction *action = menu->addAction(tr("%1 frames per page").arg(frame)); + action->setData(frame); + connect(action, SIGNAL(triggered()), this, SLOT(onFramesPerPageSelected())); + } + menu->exec(event->globalPos()); +} + +//----------------------------------------------------------------------------- + void LayerFooterPanel::setZoomSliderValue(int val) { if (val > m_frameZoomSlider->maximum()) val = m_frameZoomSlider->maximum(); @@ -207,6 +246,14 @@ void LayerFooterPanel::onFrameZoomSliderValueChanged(int val) { //----------------------------------------------------------------------------- +void LayerFooterPanel::onFramesPerPageSelected() { + QAction *action = (QAction *)QObject::sender(); + int frame = action->data().toInt(); + m_viewer->zoomToFramesPerPage(frame); +} + +//----------------------------------------------------------------------------- + void LayerFooterPanel::onControlPressed(bool pressed) { isCtrlPressed = pressed; update(); diff --git a/toonz/sources/toonz/layerfooterpanel.h b/toonz/sources/toonz/layerfooterpanel.h index 2eb2e31..804ccc2 100644 --- a/toonz/sources/toonz/layerfooterpanel.h +++ b/toonz/sources/toonz/layerfooterpanel.h @@ -16,51 +16,53 @@ class XsheetViewer; // Panel showing column footers for layers in timeline mode class LayerFooterPanel final : public QWidget { - Q_OBJECT + Q_OBJECT - QString m_tooltip; - QPoint m_pos; + QString m_tooltip; + QPoint m_pos; - QSlider *m_frameZoomSlider; + QSlider *m_frameZoomSlider; - bool isCtrlPressed = false; - bool m_zoomInHighlighted = false; - bool m_zoomOutHighlighted = false; + bool isCtrlPressed = false; + bool m_zoomInHighlighted = false; + bool m_zoomOutHighlighted = false; private: - XsheetViewer *m_viewer; + XsheetViewer *m_viewer; public: #if QT_VERSION >= 0x050500 - LayerFooterPanel(XsheetViewer *viewer, QWidget *parent = 0, - Qt::WindowFlags flags = 0); + LayerFooterPanel(XsheetViewer *viewer, QWidget *parent = 0, + Qt::WindowFlags flags = 0); #else - LayerFooterPanel(XsheetViewer *viewer, QWidget *parent = 0, - Qt::WFlags flags = 0); + LayerFooterPanel(XsheetViewer *viewer, QWidget *parent = 0, + Qt::WFlags flags = 0); #endif - ~LayerFooterPanel(); + ~LayerFooterPanel(); - void showOrHide(const Orientation *o); + void showOrHide(const Orientation *o); - void setZoomSliderValue(int val); + void setZoomSliderValue(int val); - void onControlPressed(bool pressed); - const bool isControlPressed(); + void onControlPressed(bool pressed); + const bool isControlPressed(); protected: - void paintEvent(QPaintEvent *event) override; + void paintEvent(QPaintEvent *event) override; - void enterEvent(QEvent *) override; - void leaveEvent(QEvent *) override; - void mousePressEvent(QMouseEvent *event) override; - void mouseMoveEvent(QMouseEvent *event) override; - bool event(QEvent *event) override; + void enterEvent(QEvent *) override; + void leaveEvent(QEvent *) override; + void mousePressEvent(QMouseEvent *event) override; + void mouseMoveEvent(QMouseEvent *event) override; + bool event(QEvent *event) override; + void contextMenuEvent(QContextMenuEvent *) override; - void keyPressEvent(QKeyEvent *event) override { event->ignore(); } - void wheelEvent(QWheelEvent *event) override { event->ignore(); } + void keyPressEvent(QKeyEvent *event) override { event->ignore(); } + void wheelEvent(QWheelEvent *event) override { event->ignore(); } public slots: - void onFrameZoomSliderValueChanged(int val); + void onFrameZoomSliderValueChanged(int val); + void onFramesPerPageSelected(); }; #endif #pragma once diff --git a/toonz/sources/toonz/toonz.qrc b/toonz/sources/toonz/toonz.qrc index 2985300..492add9 100644 --- a/toonz/sources/toonz/toonz.qrc +++ b/toonz/sources/toonz/toonz.qrc @@ -530,6 +530,7 @@ icons/dark/actions/16/tool_options.svg icons/dark/actions/16/view_file.svg icons/dark/actions/16/level_strip.svg + icons/dark/actions/17/syncscale.svg icons/dark/actions/20/key_off.svg diff --git a/toonz/sources/toonz/xshcellviewer.cpp b/toonz/sources/toonz/xshcellviewer.cpp index e56e4d2..0375e9c 100644 --- a/toonz/sources/toonz/xshcellviewer.cpp +++ b/toonz/sources/toonz/xshcellviewer.cpp @@ -1391,10 +1391,10 @@ void CellArea::drawSoundCell(QPainter &p, int row, int col, bool isReference) { nextCell = soundColumn->getSoundCell(row + 1); // cell in next frame bool isNextEmpty = nextCell.getFrameId().getNumber() < 0; - int frameAdj = m_viewer->getFrameZoomAdjustment(); - int frameZoomF = m_viewer->getFrameZoomFactor(); - QRect cellRect = o->rect(PredefinedRect::CELL).translated(QPoint(x, y)); - cellRect.adjust(0, 0, -frameAdj, 0); + QPoint frameAdj = m_viewer->getFrameZoomAdjustment(); + int frameZoomF = m_viewer->getFrameZoomFactor(); + QRect cellRect = o->rect(PredefinedRect::CELL).translated(QPoint(x, y)); + cellRect.adjust(0, 0, -frameAdj.x(), -frameAdj.y()); QRect rect = cellRect.adjusted( 1, 1, (!m_viewer->orientation()->isVerticalTimeline() && !isNextEmpty ? 2 : 0), @@ -1458,10 +1458,10 @@ void CellArea::drawSoundCell(QPainter &p, int row, int col, bool isReference) { drawLockedDottedLine(p, soundColumn->isLocked(), xy, cellColor); QRect trackRect = o->rect(PredefinedRect::SOUND_TRACK) - .adjusted(0, 0, -frameAdj, 0) + .adjusted(0, 0, -frameAdj.x(), -frameAdj.y()) .translated(xy); QRect previewRect = o->rect(PredefinedRect::PREVIEW_TRACK) - .adjusted(0, 0, -frameAdj, 0) + .adjusted(0, 0, -frameAdj.x(), -frameAdj.y()) .translated(xy); NumberRange trackBounds = o->layerSide(trackRect); NumberRange previewBounds = o->layerSide(previewRect); @@ -1536,7 +1536,7 @@ void CellArea::drawSoundCell(QPainter &p, int row, int col, bool isReference) { if (isLastRow) { QRect modifierRect = m_viewer->orientation() ->rect(PredefinedRect::END_SOUND_EDIT) - .adjusted(-frameAdj, 0, -frameAdj, 0) + .translated(-frameAdj) .translated(xy); if (r1 != r1WithoutOff) p.fillRect(modifierRect, SoundColumnExtenderColor); m_soundLevelModifyRects.append(modifierRect); @@ -1561,10 +1561,10 @@ void CellArea::drawSoundCell(QPainter &p, int row, int col, bool isReference) { // paint side bar void CellArea::drawDragHandle(QPainter &p, const QPoint &xy, const QColor &sideColor) const { - int frameAdj = m_viewer->getFrameZoomAdjustment(); + QPoint frameAdj = m_viewer->getFrameZoomAdjustment(); QRect dragHandleRect = m_viewer->orientation() ->rect(PredefinedRect::DRAG_HANDLE_CORNER) - .adjusted(0, 0, -frameAdj, 0) + .adjusted(0, 0, -frameAdj.x(), -frameAdj.y()) .translated(xy); p.fillRect(dragHandleRect, QBrush(sideColor)); } @@ -1573,10 +1573,10 @@ void CellArea::drawDragHandle(QPainter &p, const QPoint &xy, void CellArea::drawEndOfDragHandle(QPainter &p, bool isEnd, const QPoint &xy, const QColor &cellColor) const { if (!isEnd) return; - int frameAdj = m_viewer->getFrameZoomAdjustment(); + QPoint frameAdj = m_viewer->getFrameZoomAdjustment(); QPainterPath corner = m_viewer->orientation() ->path(PredefinedPath::DRAG_HANDLE_CORNER) - .translated(xy - QPoint(frameAdj, 0)); + .translated(xy - frameAdj); p.fillPath(corner, QBrush(cellColor)); } @@ -1586,19 +1586,20 @@ void CellArea::drawLockedDottedLine(QPainter &p, bool isLocked, const QColor &cellColor) const { if (!isLocked) return; p.setPen(QPen(cellColor, 2, Qt::DotLine)); - int frameAdj = m_viewer->getFrameZoomAdjustment(); + QPoint frameAdj = m_viewer->getFrameZoomAdjustment(); QLine dottedLine = m_viewer->orientation()->line(PredefinedLine::LOCKED).translated(xy); - dottedLine.setP2(QPoint(dottedLine.x2() - frameAdj, dottedLine.y2())); + dottedLine.setP2(QPoint(dottedLine.x2(), dottedLine.y2()) - frameAdj); p.drawLine(dottedLine); } void CellArea::drawCurrentTimeIndicator(QPainter &p, const QPoint &xy, bool isFolded) { - int frameAdj = m_viewer->getFrameZoomAdjustment(); - QRect cell = - m_viewer->orientation()->rect(PredefinedRect::CELL).translated(xy); - cell.adjust(-frameAdj / 2, 0, -frameAdj / 2, 0); + QPoint frameAdj = m_viewer->getFrameZoomAdjustment(); + QRect cell = m_viewer->orientation() + ->rect(PredefinedRect::CELL) + .translated(xy) + .translated(-frameAdj / 2); int cellMid = cell.left() + (cell.width() / 2) - 1; int cellTop = cell.top(); @@ -1615,19 +1616,34 @@ void CellArea::drawCurrentTimeIndicator(QPainter &p, const QPoint &xy, } void CellArea::drawFrameMarker(QPainter &p, const QPoint &xy, QColor color, - bool isKeyFrame) { + bool isKeyFrame, bool isCamera) { QColor outlineColor = Qt::black; - int frameAdj = m_viewer->getFrameZoomAdjustment(); - QRect dotRect = m_viewer->orientation() - ->rect(PredefinedRect::FRAME_MARKER_AREA) - .translated(xy); - dotRect.adjust(-frameAdj / 2, 0, -frameAdj / 2, 0); + QPoint frameAdj = m_viewer->getFrameZoomAdjustment(); + QRect dotRect = (isCamera) + ? m_viewer->orientation() + ->rect(PredefinedRect::CAMERA_FRAME_MARKER_AREA) + .translated(xy) + .translated(-frameAdj / 2) + : m_viewer->orientation() + ->rect(PredefinedRect::FRAME_MARKER_AREA) + .translated(xy) + .translated(-frameAdj / 2); if (isKeyFrame) m_viewer->drawPredefinedPath(p, PredefinedPath::FRAME_MARKER_DIAMOND, dotRect.adjusted(1, 1, 1, 1).center(), color, outlineColor); else { + // move to column center + if (m_viewer->orientation()->isVerticalTimeline()) { + PredefinedLine which = + Preferences::instance()->isLevelNameOnEachMarkerEnabled() + ? PredefinedLine::CONTINUE_LEVEL_WITH_NAME + : PredefinedLine::CONTINUE_LEVEL; + + QLine continueLine = m_viewer->orientation()->line(which).translated(xy); + dotRect.moveCenter(QPoint(continueLine.x1() - 1, dotRect.center().y())); + } p.setPen(outlineColor); p.setBrush(color); p.drawEllipse(dotRect); @@ -1666,11 +1682,11 @@ void CellArea::drawLevelCell(QPainter &p, int row, int col, bool isReference) { TXshCell nextCell; nextCell = xsh->getCell(row + 1, col); // cell in next frame - int frameAdj = m_viewer->getFrameZoomAdjustment(); + QPoint frameAdj = m_viewer->getFrameZoomAdjustment(); QRect cellRect = o->rect((col < 0) ? PredefinedRect::CAMERA_CELL : PredefinedRect::CELL) .translated(QPoint(x, y)); - cellRect.adjust(0, 0, -frameAdj, 0); + cellRect.adjust(0, 0, -frameAdj.x(), -frameAdj.y()); QRect rect = cellRect.adjusted( 1, 1, (!m_viewer->orientation()->isVerticalTimeline() && !nextCell.isEmpty() @@ -1796,6 +1812,8 @@ void CellArea::drawLevelCell(QPainter &p, int row, int col, bool isReference) { // if (distance == 0) distance = 6; bool isAfterMarkers = distance > 0 && ((row - offset) % distance) == 0 && row != 0; + bool isSimpleView = m_viewer->getFrameZoomFactor() <= + o->dimension(PredefinedDimension::SCALE_THRESHOLD); // draw marker interval if (o->isVerticalTimeline() && isAfterMarkers) { @@ -1813,7 +1831,7 @@ void CellArea::drawLevelCell(QPainter &p, int row, int col, bool isReference) { .translated(QPoint(x, y)); } - nameRect.adjust(0, 0, -frameAdj, 0); + nameRect.adjust(0, 0, -frameAdj.x(), -frameAdj.y()); // draw text in red if the file does not exist bool isRed = false; @@ -1854,15 +1872,17 @@ void CellArea::drawLevelCell(QPainter &p, int row, int col, bool isReference) { : PredefinedLine::CONTINUE_LEVEL; QLine continueLine = o->line(which).translated(xy); - continueLine.setP2(QPoint(continueLine.x2() - frameAdj, continueLine.y2())); + continueLine.setP2(QPoint(continueLine.x2(), continueLine.y2()) - frameAdj); p.drawLine(continueLine); } // draw frame number else { - if (m_viewer->getFrameZoomFactor() <= 50) { - // Lets not draw normal marker if there is a keyframe here - TStageObject *pegbar = xsh->getStageObject(m_viewer->getObjectId(col)); - if (pegbar->isKeyframe(row)) return; + if (isSimpleView) { + if (!o->isVerticalTimeline()) { + // Lets not draw normal marker if there is a keyframe here + TStageObject *pegbar = xsh->getStageObject(m_viewer->getObjectId(col)); + if (pegbar->isKeyframe(row)) return; + } drawFrameMarker(p, QPoint(x, y), (isRed ? Qt::red : Qt::black)); return; @@ -1888,7 +1908,7 @@ void CellArea::drawLevelCell(QPainter &p, int row, int col, bool isReference) { // draw level name if (!sameLevel || - (isAfterMarkers && + (isAfterMarkers && !isSimpleView && Preferences::instance()->isLevelNameOnEachMarkerEnabled())) { std::wstring levelName = cell.m_level->getName(); QString text = QString::fromStdWString(levelName); @@ -1952,9 +1972,9 @@ void CellArea::drawSoundTextCell(QPainter &p, int row, int col) { TXshCell nextCell; nextCell = xsh->getCell(row + 1, col); - int frameAdj = m_viewer->getFrameZoomAdjustment(); - QRect cellRect = o->rect(PredefinedRect::CELL).translated(QPoint(x, y)); - cellRect.adjust(0, 0, -frameAdj, 0); + QPoint frameAdj = m_viewer->getFrameZoomAdjustment(); + QRect cellRect = o->rect(PredefinedRect::CELL).translated(QPoint(x, y)); + cellRect.adjust(0, 0, -frameAdj.x(), -frameAdj.y()); QRect rect = cellRect.adjusted( 1, 1, (!m_viewer->orientation()->isVerticalTimeline() && !nextCell.isEmpty() @@ -2023,7 +2043,7 @@ void CellArea::drawSoundTextCell(QPainter &p, int row, int col) { p.setPen(Qt::black); QRect nameRect = o->rect(PredefinedRect::CELL_NAME).translated(QPoint(x, y)); - nameRect.adjust(0, 0, -frameAdj, 0); + nameRect.adjust(0, 0, -frameAdj.x(), -frameAdj.y()); // il nome va scritto se e' diverso dalla cella precedente oppure se // siamo su una marker line @@ -2049,7 +2069,7 @@ void CellArea::drawSoundTextCell(QPainter &p, int row, int col) { ? PredefinedLine::CONTINUE_LEVEL_WITH_NAME : PredefinedLine::CONTINUE_LEVEL; QLine continueLine = o->line(which).translated(xy); - continueLine.setP2(QPoint(continueLine.x2() - frameAdj, continueLine.y2())); + continueLine.setP2(QPoint(continueLine.x2(), continueLine.y2()) - frameAdj); p.drawLine(continueLine); } @@ -2125,9 +2145,9 @@ void CellArea::drawPaletteCell(QPainter &p, int row, int col, prevCell.m_frameId == cell.m_frameId); drawFrameSeparator(p, row, col, false, heldFrame); - int frameAdj = m_viewer->getFrameZoomAdjustment(); - QRect cellRect = o->rect(PredefinedRect::CELL).translated(QPoint(x, y)); - cellRect.adjust(0, 0, -frameAdj, 0); + QPoint frameAdj = m_viewer->getFrameZoomAdjustment(); + QRect cellRect = o->rect(PredefinedRect::CELL).translated(QPoint(x, y)); + cellRect.adjust(0, 0, -frameAdj.x(), -frameAdj.y()); QRect rect = cellRect.adjusted( 1, 1, (!m_viewer->orientation()->isVerticalTimeline() && !nextCell.isEmpty() @@ -2194,14 +2214,17 @@ void CellArea::drawPaletteCell(QPainter &p, int row, int col, QPen oldPen = p.pen(); p.setPen(QPen(m_viewer->getTextColor(), 1)); QLine continueLine = o->line(PredefinedLine::CONTINUE_LEVEL).translated(xy); - continueLine.setP2(QPoint(continueLine.x2() - frameAdj, continueLine.y2())); + continueLine.setP2(QPoint(continueLine.x2(), continueLine.y2()) - frameAdj); p.drawLine(continueLine); p.setPen(oldPen); } else { - if (m_viewer->getFrameZoomFactor() <= 50) { - // Lets not draw normal marker if there is a keyframe here - TStageObject *pegbar = xsh->getStageObject(m_viewer->getObjectId(col)); - if (pegbar->isKeyframe(row)) return; + if (m_viewer->getFrameZoomFactor() <= + o->dimension(PredefinedDimension::SCALE_THRESHOLD)) { + if (!o->isVerticalTimeline()) { + // Lets not draw normal marker if there is a keyframe here + TStageObject *pegbar = xsh->getStageObject(m_viewer->getObjectId(col)); + if (pegbar->isKeyframe(row)) return; + } drawFrameMarker(p, QPoint(x, y), (isRed ? Qt::red : Qt::black)); return; } @@ -2224,7 +2247,7 @@ void CellArea::drawPaletteCell(QPainter &p, int row, int col, .translated(QPoint(x, y)); } - nameRect.adjust(0, 0, -frameAdj, 0); + nameRect.adjust(0, 0, -frameAdj.x(), -frameAdj.y()); QColor penColor = isRed ? QColor(m_viewer->getErrorTextColor()) : m_viewer->getTextColor(); p.setPen(penColor); @@ -2291,9 +2314,9 @@ void CellArea::drawKeyframe(QPainter &p, const QRect toBeUpdated) { static QPixmap selectedKey = svgToPixmap(":Resources/selected_key.svg"); static QPixmap key = svgToPixmap(":Resources/key.svg"); - int frameAdj = m_viewer->getFrameZoomAdjustment(); - const QRect &keyRect = o->rect(PredefinedRect::KEY_ICON) - .adjusted(-frameAdj / 2, 0, -frameAdj / 2, 0); + QPoint frameAdj = m_viewer->getFrameZoomAdjustment(); + const QRect &keyRect = + o->rect(PredefinedRect::KEY_ICON).translated(-frameAdj / 2); TXsheet *xsh = m_viewer->getXsheet(); ColumnFan *columnFan = xsh->getColumnFan(o); @@ -2314,10 +2337,9 @@ void CellArea::drawKeyframe(QPainter &p, const QRect toBeUpdated) { row0 = std::max(row0, r0); row1 = std::min(row1, r1); - QRect tmpKeyRect = (col >= 0) - ? keyRect - : o->rect(PredefinedRect::CAMERA_KEY_ICON) - .adjusted(-frameAdj / 2, 0, -frameAdj / 2, 0); + QRect tmpKeyRect = (col >= 0) ? keyRect + : o->rect(PredefinedRect::CAMERA_KEY_ICON) + .translated(-frameAdj / 2); /*- first, draw key segments -*/ p.setPen(m_viewer->getTextColor()); @@ -2363,7 +2385,8 @@ void CellArea::drawKeyframe(QPainter &p, const QRect toBeUpdated) { if (pegbar->isKeyframe(row)) { QPoint xy = m_viewer->positionToXY(CellPosition(row, col)); QPoint target = tmpKeyRect.translated(xy).topLeft(); - if (!o->isVerticalTimeline() && m_viewer->getFrameZoomFactor() <= 50) { + if (m_viewer->getFrameZoomFactor() <= + o->dimension(PredefinedDimension::SCALE_THRESHOLD)) { QColor color = Qt::white; int x = xy.x(); int y = xy.y(); @@ -2378,7 +2401,7 @@ void CellArea::drawKeyframe(QPainter &p, const QRect toBeUpdated) { m_viewer->getKeyframeSelection()->isSelected(row, col)) color = QColor(85, 157, 255); - drawFrameMarker(p, QPoint(x, y), color, true); + drawFrameMarker(p, QPoint(x, y), color, true, col < 0); } else if (m_viewer->getKeyframeSelection() && m_viewer->getKeyframeSelection()->isSelected(row, col)) { @@ -2434,11 +2457,11 @@ void CellArea::drawKeyframe(QPainter &p, const QRect toBeUpdated) { void CellArea::drawKeyframeLine(QPainter &p, int col, const NumberRange &rows) const { - int frameAdj = m_viewer->getFrameZoomAdjustment(); + QPoint frameAdj = m_viewer->getFrameZoomAdjustment(); const QRect &keyRect = m_viewer->orientation() ->rect((col < 0) ? PredefinedRect::CAMERA_KEY_ICON : PredefinedRect::KEY_ICON) - .adjusted(-frameAdj / 2, 0, -frameAdj / 2, 0); + .translated(-frameAdj / 2); QPoint begin = keyRect.center() + m_viewer->positionToXY(CellPosition(rows.from(), col)); QPoint end = @@ -2543,15 +2566,15 @@ void CellArea::paintEvent(QPaintEvent *event) { drawNotes(p, toBeUpdated); // focus cell border - int frameAdj = m_viewer->getFrameZoomAdjustment(); - int row = m_viewer->getCurrentRow(); - int col = m_viewer->getCurrentColumn(); - QPoint xy = m_viewer->positionToXY(CellPosition(row, col)); + QPoint frameAdj = m_viewer->getFrameZoomAdjustment(); + int row = m_viewer->getCurrentRow(); + int col = m_viewer->getCurrentColumn(); + QPoint xy = m_viewer->positionToXY(CellPosition(row, col)); QRect rect = m_viewer->orientation() ->rect((col < 0) ? PredefinedRect::CAMERA_CELL : PredefinedRect::CELL) .translated(xy) - .adjusted(0, 0, -1 - frameAdj, 0); + .adjusted(0, 0, -1 - frameAdj.x(), -frameAdj.y()); p.setPen(m_viewer->getCellFocusColor()); p.setBrush(Qt::NoBrush); for (int i = 0; i < 2; i++) // thick border within cell @@ -2603,7 +2626,7 @@ bool CellArea::isKeyFrameArea(int col, int row, QPoint mouseInCell) { if (!isKeyframeFrame) return false; const Orientation *o = m_viewer->orientation(); - int frameAdj = m_viewer->getFrameZoomAdjustment(); + QPoint frameAdj = m_viewer->getFrameZoomAdjustment(); if (o->isVerticalTimeline()) return o->rect((col < 0) ? PredefinedRect::CAMERA_CELL @@ -2611,14 +2634,14 @@ bool CellArea::isKeyFrameArea(int col, int row, QPoint mouseInCell) { .contains(mouseInCell) && row < k1 + 1; - QRect activeArea = (m_viewer->getFrameZoomFactor() > 50 + QRect activeArea = (m_viewer->getFrameZoomFactor() > + o->dimension(PredefinedDimension::SCALE_THRESHOLD) ? o->rect(PredefinedRect::KEYFRAME_AREA) : o->rect(PredefinedRect::FRAME_MARKER_AREA)); // If directly over keyframe icon, return true if (pegbar->isKeyframe(row) && - activeArea.adjusted(-frameAdj / 2, 0, -frameAdj / 2, 0) - .contains(mouseInCell) && + activeArea.translated(-frameAdj / 2).contains(mouseInCell) && row < k1 + 1) return true; @@ -2633,8 +2656,7 @@ bool CellArea::isKeyFrameArea(int col, int row, QPoint mouseInCell) { if (row < k1) activeArea.adjust(0, 0, (o->cellWidth() - activeArea.right()), 0); - return activeArea.adjusted(-frameAdj / 2, 0, -frameAdj / 2, 0) - .contains(mouseInCell) && + return activeArea.translated(-frameAdj / 2).contains(mouseInCell) && row < k1 + 1; } @@ -2644,7 +2666,7 @@ void CellArea::mousePressEvent(QMouseEvent *event) { m_viewer->setQtModifiers(event->modifiers()); assert(!m_isPanning); m_isMousePressed = true; - int frameAdj = m_viewer->getFrameZoomAdjustment(); + QPoint frameAdj = m_viewer->getFrameZoomAdjustment(); if (event->button() == Qt::LeftButton) { assert(getDragTool() == 0); @@ -2768,7 +2790,7 @@ void CellArea::mousePressEvent(QMouseEvent *event) { XsheetGUI::DragTool::makeLevelExtenderTool(m_viewer, false, true)); } else if ((!xsh->getCell(row, col).isEmpty()) && o->rect(PredefinedRect::DRAG_AREA) - .adjusted(0, 0, -frameAdj, 0) + .adjusted(0, 0, -frameAdj.x(), -frameAdj.y()) .contains(mouseInCell)) { TXshColumn *column = xsh->getColumn(col); if (column && !m_viewer->getCellSelection()->isCellSelected(row, col)) { @@ -2795,7 +2817,7 @@ void CellArea::mousePressEvent(QMouseEvent *event) { } else { m_viewer->getKeyframeSelection()->selectNone(); if (isSoundColumn && o->rect(PredefinedRect::PREVIEW_TRACK) - .adjusted(0, 0, -frameAdj, 0) + .adjusted(0, 0, -frameAdj.x(), -frameAdj.y()) .contains(mouseInCell)) setDragTool(XsheetGUI::DragTool::makeSoundScrubTool( m_viewer, column->getSoundColumn())); @@ -2818,7 +2840,7 @@ void CellArea::mousePressEvent(QMouseEvent *event) { void CellArea::mouseMoveEvent(QMouseEvent *event) { const Orientation *o = m_viewer->orientation(); - int frameAdj = m_viewer->getFrameZoomAdjustment(); + QPoint frameAdj = m_viewer->getFrameZoomAdjustment(); m_viewer->setQtModifiers(event->modifiers()); setCursor(Qt::ArrowCursor); @@ -2896,7 +2918,7 @@ void CellArea::mouseMoveEvent(QMouseEvent *event) { m_tooltip = tr("Set the cycle of previous keyframes"); else if ((!xsh->getCell(row, col).isEmpty()) && o->rect(PredefinedRect::DRAG_AREA) - .adjusted(0, 0, -frameAdj, 0) + .adjusted(0, 0, -frameAdj.x(), -frameAdj.y()) .contains(mouseInCell)) m_tooltip = tr("Click and drag to move the selection"); else if (isZeraryColumn) @@ -2905,7 +2927,7 @@ void CellArea::mouseMoveEvent(QMouseEvent *event) { ->getZeraryFx() ->getName()); else if ((!isSoundColumn && !xsh->getCell(row, col).isEmpty()) && // x > 6 && - x < (o->cellWidth() - frameAdj)) { + x < (o->cellWidth() - frameAdj.x())) { TXshCell cell = xsh->getCell(row, col); TFrameId fid = cell.getFrameId(); std::wstring levelName = cell.m_level->getName(); @@ -2932,7 +2954,7 @@ void CellArea::mouseMoveEvent(QMouseEvent *event) { QString::fromStdString(frameNumber)); } } else if (isSoundColumn && o->rect(PredefinedRect::PREVIEW_TRACK) - .adjusted(0, 0, -frameAdj, 0) + .adjusted(0, 0, -frameAdj.x(), -frameAdj.y()) .contains(mouseInCell)) m_tooltip = tr("Click and drag to play"); else if (m_levelExtenderRect.contains(pos)) @@ -2961,7 +2983,6 @@ void CellArea::mouseReleaseEvent(QMouseEvent *event) { void CellArea::mouseDoubleClickEvent(QMouseEvent *event) { const Orientation *o = m_viewer->orientation(); - int frameAdj = m_viewer->getFrameZoomAdjustment(); TPoint pos(event->pos().x(), event->pos().y()); CellPosition cellPosition = m_viewer->xyToPosition(event->pos()); int row = cellPosition.frame(); @@ -3009,7 +3030,6 @@ void CellArea::mouseDoubleClickEvent(QMouseEvent *event) { void CellArea::contextMenuEvent(QContextMenuEvent *event) { const Orientation *o = m_viewer->orientation(); - int frameAdj = m_viewer->getFrameZoomAdjustment(); TPoint pos(event->pos().x(), event->pos().y()); CellPosition cellPosition = m_viewer->xyToPosition(event->pos()); int row = cellPosition.frame(); diff --git a/toonz/sources/toonz/xshcellviewer.h b/toonz/sources/toonz/xshcellviewer.h index 43a219a..fe047d1 100644 --- a/toonz/sources/toonz/xshcellviewer.h +++ b/toonz/sources/toonz/xshcellviewer.h @@ -104,7 +104,7 @@ class CellArea final : public QWidget { bool isFolded = false); void drawFrameMarker(QPainter &p, const QPoint &xy, QColor color, - bool isKeyFrame = false); + bool isKeyFrame = false, bool isCamera = false); // Restistusce true bool getEaseHandles(int r0, int r1, double e0, double e1, int &rh0, int &rh1); diff --git a/toonz/sources/toonz/xsheetviewer.cpp b/toonz/sources/toonz/xsheetviewer.cpp index 4913be5..2d56bc0 100644 --- a/toonz/sources/toonz/xsheetviewer.cpp +++ b/toonz/sources/toonz/xsheetviewer.cpp @@ -14,6 +14,7 @@ #include "toonz/txshpalettelevel.h" #include "toonz/preferences.h" #include "toonz/sceneproperties.h" +#include "toutputproperties.h" #include "toonzqt/tselectionhandle.h" #include "toonzqt/icongenerator.h" #include "cellselection.h" @@ -40,6 +41,7 @@ #include #include #include +#include TEnv::IntVar FrameDisplayStyleInXsheetRowArea( "FrameDisplayStyleInXsheetRowArea", 0); @@ -360,6 +362,10 @@ const Orientation *XsheetViewer::orientation() const { void XsheetViewer::flipOrientation() { m_orientation = orientation()->next(); + + int factor = (m_orientation->isVerticalTimeline()) ? m_frameZoomFactor : 100; + TApp::instance()->getCurrentXsheet()->notifyZoomScaleChanged(factor); + emit orientationChanged(orientation()); } @@ -413,9 +419,15 @@ void XsheetViewer::positionSections() { m_rowScrollArea->setGeometry(o->frameLayerRect( bodyFrame.adjusted(0, -XsheetGUI::SCROLLBAR_WIDTH), headerLayer)); - m_layerFooterPanel->setGeometry(0, - m_columnScrollArea->geometry().bottom() + 1, - m_columnScrollArea->width(), 14); + if (o->isVerticalTimeline()) { + m_layerFooterPanel->setGeometry(m_columnScrollArea->geometry().right() + 1, + m_columnScrollArea->geometry().top(), 14, + m_columnScrollArea->height()); + } else { + m_layerFooterPanel->setGeometry(0, + m_columnScrollArea->geometry().bottom() + 1, + m_columnScrollArea->width(), 14); + } m_layerFooterPanel->showOrHide(o); } @@ -581,24 +593,36 @@ void XsheetViewer::scroll(QPoint delta) { //----------------------------------------------------------------------------- -void XsheetViewer::onPrepareToScrollOffset(const QPoint &offset) { - refreshContentSize(offset.x(), offset.y()); +void XsheetViewer::onPrepareToScrollOffset(const QPointF &offset) { + refreshContentSize((int)offset.x(), (int)offset.y()); } //----------------------------------------------------------------------------- -void XsheetViewer::onZoomScrollAdjust(QPoint &offset, bool toZoom) { - int frameZoomFactor = getFrameZoomFactor(); +void XsheetViewer::onZoomScrollAdjust(QPointF &offset, bool toZoom) { + double frameZoomFactor = (double)getFrameZoomFactor(); - // toZoom = true: Adjust standardized offset down to zoom factor - // toZoom = false: Adjust zoomed offset up to standardized offset - int newX; - if (toZoom) - newX = (offset.x() * frameZoomFactor) / 100; - else - newX = (offset.x() * 100) / frameZoomFactor; + if (orientation()->isVerticalTimeline()) { + // toZoom = true: Adjust standardized offset down to zoom factor + // toZoom = false: Adjust zoomed offset up to standardized offset + double newY; + if (toZoom) + newY = (offset.y() * frameZoomFactor) / 100.0; + else + newY = (offset.y() * 100.0) / frameZoomFactor; - offset.setX(newX); + offset.setY(newY); + } else { + // toZoom = true: Adjust standardized offset down to zoom factor + // toZoom = false: Adjust zoomed offset up to standardized offset + double newX; + if (toZoom) + newX = (offset.x() * frameZoomFactor) / 100.0; + else + newX = (offset.x() * 100.0) / frameZoomFactor; + + offset.setX(newX); + } } //----------------------------------------------------------------------------- @@ -777,7 +801,9 @@ CellPosition XsheetViewer::xyToPosition(const QPoint &point) const { ColumnFan *fan = xsh->getColumnFan(o); - if (!o->isVerticalTimeline()) + if (o->isVerticalTimeline()) + usePoint.setY((usePoint.y() * 100) / getFrameZoomFactor()); + else usePoint.setX((usePoint.x() * 100) / getFrameZoomFactor()); if (o->isVerticalTimeline()) return o->xyToPosition(usePoint, fan); @@ -813,7 +839,9 @@ QPoint XsheetViewer::positionToXY(const CellPosition &pos) const { ColumnFan *fan = xsh->getColumnFan(o); QPoint usePoint = o->positionToXY(pos, fan); - if (!o->isVerticalTimeline()) + if (o->isVerticalTimeline()) + usePoint.setY((usePoint.y() * getFrameZoomFactor()) / 100); + else usePoint.setX((usePoint.x() * getFrameZoomFactor()) / 100); if (o->isVerticalTimeline()) return usePoint; @@ -847,8 +875,8 @@ int XsheetViewer::columnToLayerAxis(int layer) const { } int XsheetViewer::rowToFrameAxis(int frame) const { int result = orientation()->rowToFrameAxis(frame); - if (!orientation()->isVerticalTimeline()) - result = (result * getFrameZoomFactor()) / 100; + // if (!orientation()->isVerticalTimeline()) + result = (result * getFrameZoomFactor()) / 100; return result; } @@ -1043,6 +1071,8 @@ void XsheetViewer::showEvent(QShowEvent *) { assert(ret); refreshContentSize(0, 0); changeWindowTitle(); + + xsheetHandle->notifyZoomScaleChanged(m_frameZoomFactor); } //----------------------------------------------------------------------------- @@ -1088,6 +1118,8 @@ void XsheetViewer::hideEvent(QHideEvent *) { disconnect(IconGenerator::instance(), SIGNAL(iconGenerated()), this, SLOT(updateColumnArea())); + + xsheetHandle->notifyZoomScaleChanged(100); } //----------------------------------------------------------------------------- @@ -1271,10 +1303,12 @@ void XsheetViewer::keyPressEvent(QKeyEvent *event) { break; case Qt::Key_End: - if (orientation()->isVerticalTimeline()) - locals.scrollVertTo((frameCount + 1) * orientation()->cellHeight(), - visibleRect); - else { + if (orientation()->isVerticalTimeline()) { + int y = (((frameCount + 1) * orientation()->cellHeight()) * + getFrameZoomFactor()) / + 100; + locals.scrollVertTo(y, visibleRect); + } else { int x = (((frameCount + 1) * orientation()->cellWidth()) * getFrameZoomFactor()) / 100; @@ -1736,6 +1770,7 @@ void XsheetViewer::save(QSettings &settings) const { settings.setValue("orientation", orientation()->name()); settings.setValue("frameZoomFactor", m_frameZoomFactor); } + void XsheetViewer::load(QSettings &settings) { QVariant zoomFactor = settings.value("frameZoomFactor"); QVariant name = settings.value("orientation"); @@ -1763,20 +1798,92 @@ TPanel *createXsheetViewer(QWidget *parent) */ //---------------------------------------------------------------- + +QList XsheetViewer::availableFramesPerPage() { + int frameRate = TApp::instance() + ->getCurrentScene() + ->getScene() + ->getProperties() + ->getOutputProperties() + ->getFrameRate(); + // 1sec, 1.5sec, 2sec, 3sec, 4sec, 6sec + QList ret; + ret << frameRate; + if (frameRate % 2 == 0) ret << frameRate * 3 / 2; + ret << frameRate * 2; + ret << frameRate * 3; + ret << frameRate * 4; + ret << frameRate * 6; + + // visible area size + int size = (orientation()->isVerticalTimeline()) + ? m_cellScrollArea->viewport()->height() + : m_cellScrollArea->viewport()->width(); + int scaleMin = (orientation()->isVerticalTimeline()) ? 50 : 20; + int scaleMax = 100; + + int frameMin = (int)std::ceil( + (double)size / + ((double)orientation()->dimension(PredefinedDimension::FRAME) * + (double)scaleMax / 100.0)); + int frameMax = (int)std::floor( + (double)size / + ((double)orientation()->dimension(PredefinedDimension::FRAME) * + (double)scaleMin / 100.0)); + + for (auto itr = ret.begin(); itr != ret.end();) { + // erase unavailable items + if (*itr < frameMin || *itr > frameMax) { + itr = ret.erase(itr); + continue; + } + itr++; + } + return ret; +} + +//---------------------------------------------------------------- + +void XsheetViewer::zoomToFramesPerPage(int frames) { + int size = (orientation()->isVerticalTimeline()) + ? m_cellScrollArea->viewport()->height() + : m_cellScrollArea->viewport()->width(); + int frameDim = orientation()->dimension(PredefinedDimension::FRAME); + + double scale = (double)size / ((double)frameDim * (double)frames); + + // convert to factor value + int factor; + if (orientation()->isVerticalTimeline()) + factor = (int)std::round((0.2 + (scale - 0.5) * 8.0 / 5.0) * 100); + else + factor = (int)std::round(scale * 100); + + zoomOnFrame(getCurrentRow(), factor); +} + +//---------------------------------------------------------------- int XsheetViewer::getFrameZoomFactor() const { - if (orientation()->isVerticalTimeline()) return 100; + if (orientation()->isVerticalTimeline()) + return 50 + (m_frameZoomFactor - 20) * 5 / 8; return m_frameZoomFactor; } -int XsheetViewer::getFrameZoomAdjustment() { - if (orientation()->isVerticalTimeline()) return 0; +QPoint XsheetViewer::getFrameZoomAdjustment() { + // if (orientation()->isVerticalTimeline()) return 0; QRect frameRect = orientation()->rect(PredefinedRect::FRAME_HEADER); - int adj = frameRect.width() - - ((frameRect.width() * getFrameZoomFactor()) / 100) - 1; - - return std::max(0, adj); + int adj; + if (orientation()->isVerticalTimeline()) { + adj = frameRect.height() - + ((frameRect.height() * getFrameZoomFactor()) / 100) - 1; + return QPoint(0, std::max(0, adj)); + } else { + adj = frameRect.width() - + ((frameRect.width() * getFrameZoomFactor()) / 100) - 1; + return QPoint(std::max(0, adj), 0); + } } void XsheetViewer::zoomOnFrame(int frame, int factor) { @@ -1787,11 +1894,11 @@ void XsheetViewer::zoomOnFrame(int frame, int factor) { QPoint xyNew = positionToXY(CellPosition(frame, -1)); - int viewShift = xyNew.x() - xyOrig.x(); - - scroll(QPoint(viewShift, 0)); + scroll(xyNew - xyOrig); TApp::instance()->getCurrentXsheet()->notifyXsheetChanged(); + if (orientation()->isVerticalTimeline()) + TApp::instance()->getCurrentXsheet()->notifyZoomScaleChanged(factor); m_rowArea->update(); } diff --git a/toonz/sources/toonz/xsheetviewer.h b/toonz/sources/toonz/xsheetviewer.h index 7cc073e..ddb51cc 100644 --- a/toonz/sources/toonz/xsheetviewer.h +++ b/toonz/sources/toonz/xsheetviewer.h @@ -1253,6 +1253,9 @@ public: virtual void load(QSettings &settings) override; QString getXsheetLayout() const { return m_xsheetLayout; } + // returns a list of frame amount per page displayable in the current size + QList availableFramesPerPage(); + void zoomToFramesPerPage(int frames); protected: void scrollToColumn(int col); @@ -1302,12 +1305,12 @@ public slots: void resetXsheetNotes(); void onOrientationChanged(const Orientation *newOrientation); - void onPrepareToScrollOffset(const QPoint &offset); - void onZoomScrollAdjust(QPoint &offset, bool toZoom); + void onPrepareToScrollOffset(const QPointF &offset); + void onZoomScrollAdjust(QPointF &offset, bool toZoom); void setFrameZoomFactor(int f) { m_frameZoomFactor = f; } int getFrameZoomFactor() const; - int getFrameZoomAdjustment(); + QPoint getFrameZoomAdjustment(); void zoomOnFrame(int frame, int factor); }; diff --git a/toonz/sources/toonz/xshrowviewer.cpp b/toonz/sources/toonz/xshrowviewer.cpp index 088741b..5c59ffb 100644 --- a/toonz/sources/toonz/xshrowviewer.cpp +++ b/toonz/sources/toonz/xshrowviewer.cpp @@ -121,7 +121,9 @@ void RowArea::drawRows(QPainter &p, int r0, int r1) { int y1 = visibleRect.bottom(); NumberRange layerSide = o->layerSide(visibleRect); - int frameAdj = m_viewer->getFrameZoomAdjustment(); + QPoint frameAdj = m_viewer->getFrameZoomAdjustment(); + bool simpleView = m_viewer->getFrameZoomFactor() <= + o->dimension(PredefinedDimension::SCALE_THRESHOLD); for (int r = r0; r <= r1; r++) { int frameAxis = m_viewer->rowToFrameAxis(r); @@ -161,7 +163,8 @@ void RowArea::drawRows(QPainter &p, int r0, int r1) { QRect labelRect = m_viewer->orientation() ->rect(PredefinedRect::FRAME_LABEL) .translated(basePoint); - labelRect.adjust(-frameAdj / 2, 0, -frameAdj / 2, 0); + labelRect.adjust(-frameAdj.x() / 2, -frameAdj.y() / 2, -frameAdj.x() / 2, + -frameAdj.y() / 2); int align = m_viewer->orientation()->dimension( PredefinedDimension::FRAME_LABEL_ALIGN); // display time and/or frame number @@ -185,7 +188,7 @@ void RowArea::drawRows(QPainter &p, int r0, int r1) { .arg(QString::number(koma).rightJustified(2, '0')); z = 0; } else { - if (!o->isVerticalTimeline() && m_viewer->getFrameZoomFactor() <= 50) { + if (simpleView) { if ((z + 1) % zz) break; if (r % frameRate == 1 || (r + 2) % frameRate == 1) break; } @@ -199,9 +202,7 @@ void RowArea::drawRows(QPainter &p, int r0, int r1) { } case XsheetViewer::Frame: { - if (!o->isVerticalTimeline() && m_viewer->getFrameZoomFactor() <= 50 && - r > 0 && (r + 1) % (distance > 0 ? distance : 5)) - break; + if (simpleView && r > 0 && (r + 1) % (distance > 0 ? distance : 5)) break; QString number = QString::number(r + 1); p.drawText(labelRect, align, number); break; @@ -226,7 +227,7 @@ void RowArea::drawRows(QPainter &p, int r0, int r1) { .arg(QString::number(koma).rightJustified(3, '0')); z = 0; } else { - if (!o->isVerticalTimeline() && m_viewer->getFrameZoomFactor() <= 50) { + if (simpleView) { if ((z + 1) % zz) break; if (r % frameRate == 1 || (r + 2) % frameRate == 1) break; } @@ -255,7 +256,7 @@ void RowArea::drawRows(QPainter &p, int r0, int r1) { .arg(QString::number(koma).rightJustified(2, '0')); z = 0; } else { - if (!o->isVerticalTimeline() && m_viewer->getFrameZoomFactor() <= 50) { + if (simpleView) { if ((z + 1) % zz) break; if (r % frameRate == 1 || (r + 2) % frameRate == 1) break; } @@ -275,7 +276,7 @@ void RowArea::drawPlayRangeBackground(QPainter &p, int r0, int r1) { const Orientation *o = m_viewer->orientation(); TXsheet *xsh = m_viewer->getXsheet(); - int frameAdj = m_viewer->getFrameZoomAdjustment(); + QPoint frameAdj = m_viewer->getFrameZoomAdjustment(); QRect playRangeRect = o->rect(PredefinedRect::PLAY_RANGE); int playR0, playR1, step; @@ -291,7 +292,7 @@ void RowArea::drawPlayRangeBackground(QPainter &p, int r0, int r1) { basePoint.setX(0); QRect previewBoxRect = o->rect(PredefinedRect::PREVIEW_FRAME_AREA) - .adjusted(0, 0, -frameAdj, 0) + .adjusted(0, 0, -frameAdj.x(), -frameAdj.y()) .translated(basePoint); p.fillRect(previewBoxRect, m_viewer->getPlayRangeColor()); @@ -313,7 +314,7 @@ void RowArea::drawPlayRangeBackground(QPainter &p, int r0, int r1) { void RowArea::drawPlayRange(QPainter &p, int r0, int r1) { bool playRangeEnabled = XsheetGUI::isPlayRangeEnabled(); - int frameAdj = m_viewer->getFrameZoomAdjustment(); + QPoint frameAdj = m_viewer->getFrameZoomAdjustment(); TXsheet *xsh = m_viewer->getXsheet(); // Update the play range internal fields @@ -344,7 +345,7 @@ void RowArea::drawPlayRange(QPainter &p, int r0, int r1) { if (m_r1 > r0 - 1 && r1 + 1 > m_r1) { QPoint topLeft = m_viewer->positionToXY(CellPosition(m_r1, -1)); - topLeft.setX(topLeft.x() - frameAdj); + topLeft -= frameAdj; if (!m_viewer->orientation()->isVerticalTimeline()) topLeft.setY(0); else @@ -368,8 +369,8 @@ void RowArea::drawCurrentRowGadget(QPainter &p, int r0, int r1) { QRect header = m_viewer->orientation() ->rect(PredefinedRect::FRAME_HEADER) .translated(topLeft); - int frameAdj = m_viewer->getFrameZoomAdjustment(); - header.adjust(1, 1, -frameAdj, 0); + QPoint frameAdj = m_viewer->getFrameZoomAdjustment(); + header.adjust(1, 1, -frameAdj.x(), -frameAdj.y()); p.fillRect(header, m_viewer->getCurrentRowBgColor()); } @@ -385,8 +386,8 @@ void RowArea::drawStopMotionCameraIndicator(QPainter &p) { QRect header = m_viewer->orientation() ->rect(PredefinedRect::FRAME_HEADER) .translated(topLeft); - int frameAdj = m_viewer->getFrameZoomAdjustment(); - header.adjust(1, 1, -frameAdj, 0); + QPoint frameAdj = m_viewer->getFrameZoomAdjustment(); + header.adjust(1, 1, -frameAdj.x(), -frameAdj.y()); p.fillRect(header, Qt::GlobalColor::darkGreen); } @@ -396,7 +397,7 @@ void RowArea::drawStopMotionCameraIndicator(QPainter &p) { void RowArea::drawOnionSkinBackground(QPainter &p, int r0, int r1) { const Orientation *o = m_viewer->orientation(); - int frameAdj = m_viewer->getFrameZoomAdjustment(); + QPoint frameAdj = m_viewer->getFrameZoomAdjustment(); for (int r = r0; r <= r1; r++) { QPoint basePoint = m_viewer->positionToXY(CellPosition(r, -1)); @@ -407,7 +408,7 @@ void RowArea::drawOnionSkinBackground(QPainter &p, int r0, int r1) { QRect oRect = m_viewer->orientation() ->rect(PredefinedRect::ONION_AREA) - .adjusted(0, 0, -frameAdj, 0) + .adjusted(0, 0, -frameAdj.x(), -frameAdj.y()) .translated(basePoint); p.fillRect(oRect, m_viewer->getOnionSkinAreaBgColor()); } @@ -423,7 +424,7 @@ void RowArea::drawOnionSkinSelection(QPainter &p) { assert(xsh); int currentRow = m_viewer->getCurrentRow(); - int frameAdj = m_viewer->getFrameZoomAdjustment(); + QPoint frameAdj = m_viewer->getFrameZoomAdjustment(); // get onion colors TPixel frontPixel, backPixel; @@ -482,13 +483,16 @@ void RowArea::drawOnionSkinSelection(QPainter &p) { if (maxMos < mos) maxMos = mos; } p.setBrush(Qt::NoBrush); + int frameAdj_i = (m_viewer->orientation()->isVerticalTimeline()) + ? frameAdj.y() + : frameAdj.x(); if (minMos < 0) // previous frames { int layerAxis = onionCenter_layer; int fromFrameAxis = m_viewer->rowToFrameAxis(currentRow + minMos) + - onionCenter_frame - (frameAdj / 2); + onionCenter_frame - (frameAdj_i / 2); int toFrameAxis = m_viewer->rowToFrameAxis(currentRow) + onionCenter_frame - - (frameAdj / 2); + (frameAdj_i / 2); QLine verticalLine = m_viewer->orientation()->verticalLine( layerAxis, NumberRange(fromFrameAxis, toFrameAxis)); p.setPen(backPen); @@ -503,9 +507,9 @@ void RowArea::drawOnionSkinSelection(QPainter &p) { { int layerAxis = onionCenter_layer; int fromFrameAxis = m_viewer->rowToFrameAxis(currentRow) + - onionCenter_frame - (frameAdj / 2); + onionCenter_frame - (frameAdj_i / 2); int toFrameAxis = m_viewer->rowToFrameAxis(currentRow + maxMos) + - onionCenter_frame - (frameAdj / 2); + onionCenter_frame - (frameAdj_i / 2); QLine verticalLine = m_viewer->orientation()->verticalLine( layerAxis, NumberRange(fromFrameAxis, toFrameAxis)); p.setPen(frontPen); @@ -522,8 +526,8 @@ void RowArea::drawOnionSkinSelection(QPainter &p) { handleTopLeft.setY(0); else handleTopLeft.setX(0); - QRect handleRect = onionRect.translated(handleTopLeft); - handleRect.adjust(-frameAdj / 2, 0, -frameAdj / 2, 0); + QRect handleRect = + onionRect.translated(handleTopLeft).translated(-frameAdj / 2); int angle180 = 16 * 180; int turn = m_viewer->orientation()->dimension(PredefinedDimension::ONION_TURN) * 16; @@ -553,8 +557,8 @@ void RowArea::drawOnionSkinSelection(QPainter &p) { topLeft.setX(0); QRect dotRect = m_viewer->orientation() ->rect(PredefinedRect::ONION_DOT) - .translated(topLeft); - dotRect.adjust(-frameAdj / 2, 0, -frameAdj / 2, 0); + .translated(topLeft) + .translated(-frameAdj / 2); p.drawEllipse(dotRect); } @@ -585,8 +589,8 @@ void RowArea::drawOnionSkinSelection(QPainter &p) { topLeft.setX(0); QRect dotRect = m_viewer->orientation() ->rect(PredefinedRect::ONION_DOT_FIXED) - .translated(topLeft); - dotRect.adjust(-frameAdj / 2, 0, -frameAdj / 2, 0); + .translated(topLeft) + .translated(-frameAdj / 2); p.drawEllipse(dotRect); } @@ -603,8 +607,8 @@ void RowArea::drawOnionSkinSelection(QPainter &p) { m_viewer->orientation() ->rect(m_showOnionToSet == Fos ? PredefinedRect::ONION_DOT_FIXED : PredefinedRect::ONION_DOT) - .translated(topLeft); - dotRect.adjust(-frameAdj / 2, 0, -frameAdj / 2, 0); + .translated(topLeft) + .translated(-frameAdj / 2); p.drawEllipse(dotRect); } } @@ -612,8 +616,8 @@ void RowArea::drawOnionSkinSelection(QPainter &p) { //----------------------------------------------------------------------------- void RowArea::drawCurrentTimeIndicator(QPainter &p) { - int frameAdj = m_viewer->getFrameZoomAdjustment(); - int currentRow = m_viewer->getCurrentRow(); + QPoint frameAdj = m_viewer->getFrameZoomAdjustment(); + int currentRow = m_viewer->getCurrentRow(); QPoint topLeft = m_viewer->positionToXY(CellPosition(currentRow, -1)); if (!m_viewer->orientation()->isVerticalTimeline()) @@ -622,8 +626,8 @@ void RowArea::drawCurrentTimeIndicator(QPainter &p) { topLeft.setX(0); QRect header = m_viewer->orientation() ->rect(PredefinedRect::FRAME_HEADER) - .adjusted(-frameAdj / 2, 0, -frameAdj / 2, 0) - .translated(topLeft); + .translated(topLeft) + .translated(-frameAdj / 2); int frameMid = header.left() + (header.width() / 2) - 1; int frameTop = header.top() + 22; @@ -639,8 +643,8 @@ void RowArea::drawCurrentTimeIndicator(QPainter &p) { } void RowArea::drawCurrentTimeLine(QPainter &p) { - int frameAdj = m_viewer->getFrameZoomAdjustment(); - int currentRow = m_viewer->getCurrentRow(); + QPoint frameAdj = m_viewer->getFrameZoomAdjustment(); + int currentRow = m_viewer->getCurrentRow(); QPoint topLeft = m_viewer->positionToXY(CellPosition(currentRow, -1)); if (!m_viewer->orientation()->isVerticalTimeline()) @@ -649,8 +653,8 @@ void RowArea::drawCurrentTimeLine(QPainter &p) { topLeft.setX(0); QRect header = m_viewer->orientation() ->rect(PredefinedRect::FRAME_HEADER) - .adjusted(-frameAdj / 2, 0, -frameAdj / 2, 0) - .translated(topLeft); + .translated(topLeft) + .translated(-frameAdj / 2); int frameMid = header.left() + (header.width() / 2) - 1; int frameTop = header.top(); @@ -670,7 +674,10 @@ void RowArea::drawShiftTraceMarker(QPainter &p) { assert(xsh); int currentRow = m_viewer->getCurrentRow(); - int frameAdj = m_viewer->getFrameZoomAdjustment(); + QPoint frameAdj = m_viewer->getFrameZoomAdjustment(); + int frameAdj_i = (m_viewer->orientation()->isVerticalTimeline()) + ? frameAdj.y() + : frameAdj.x(); // get onion colors TPixel frontPixel, backPixel; @@ -694,9 +701,9 @@ void RowArea::drawShiftTraceMarker(QPainter &p) { { int layerAxis = onionCenter_layer; int fromFrameAxis = m_viewer->rowToFrameAxis(currentRow + prevOffset) + - onionCenter_frame - (frameAdj / 2); + onionCenter_frame - (frameAdj_i / 2); int toFrameAxis = m_viewer->rowToFrameAxis(currentRow) + onionCenter_frame - - (frameAdj / 2); + (frameAdj_i / 2); QLine verticalLine = m_viewer->orientation()->verticalLine( layerAxis, NumberRange(fromFrameAxis, toFrameAxis)); p.setPen(backColor); @@ -707,9 +714,9 @@ void RowArea::drawShiftTraceMarker(QPainter &p) { { int layerAxis = onionCenter_layer; int fromFrameAxis = m_viewer->rowToFrameAxis(currentRow) + - onionCenter_frame - (frameAdj / 2); + onionCenter_frame - (frameAdj_i / 2); int toFrameAxis = m_viewer->rowToFrameAxis(currentRow + forwardOffset) + - onionCenter_frame - (frameAdj / 2); + onionCenter_frame - (frameAdj_i / 2); QLine verticalLine = m_viewer->orientation()->verticalLine( layerAxis, NumberRange(fromFrameAxis, toFrameAxis)); p.setPen(frontColor); @@ -739,8 +746,8 @@ void RowArea::drawShiftTraceMarker(QPainter &p) { topLeft.setX(0); QRect dotRect = m_viewer->orientation() ->rect(PredefinedRect::SHIFTTRACE_DOT) - .translated(topLeft); - dotRect.adjust(-frameAdj / 2, 0, -frameAdj / 2, 0); + .translated(topLeft) + .translated(-frameAdj / 2); p.drawRect(dotRect); // draw shortcut numbers p.setPen(Qt::black); @@ -759,8 +766,8 @@ void RowArea::drawShiftTraceMarker(QPainter &p) { topLeft.setX(0); QRect dotRect = m_viewer->orientation() ->rect(PredefinedRect::SHIFTTRACE_DOT) - .translated(topLeft); - dotRect.adjust(-frameAdj / 2, 0, -frameAdj / 2, 0); + .translated(topLeft) + .translated(-frameAdj / 2); p.drawRect(dotRect); } } @@ -805,11 +812,11 @@ void RowArea::drawPinnedCenterKeys(QPainter &p, int r0, int r1) { int columnCount = xsh->getColumnCount(); int prev_pinnedCol = -2; - int frameAdj = m_viewer->getFrameZoomAdjustment(); + QPoint frameAdj = m_viewer->getFrameZoomAdjustment(); QRect keyRect = m_viewer->orientation() ->rect(PredefinedRect::PINNED_CENTER_KEY) - .adjusted(-frameAdj / 2, 0, -frameAdj / 2, 0); + .translated(-frameAdj / 2); p.setPen(Qt::black); r1 = (r1 < xsh->getFrameCount() - 1) ? xsh->getFrameCount() - 1 : r1; @@ -933,11 +940,11 @@ void RowArea::mousePressEvent(QMouseEvent *event) { else topLeft.setX(0); QPoint mouseInCell = event->pos() - topLeft; - int frameAdj = m_viewer->getFrameZoomAdjustment(); + QPoint frameAdj = m_viewer->getFrameZoomAdjustment(); if (CommandManager::instance()->getAction(MI_ShiftTrace)->isChecked() && o->rect(PredefinedRect::SHIFTTRACE_DOT_AREA) - .adjusted(0, 0, -frameAdj, 0) + .adjusted(0, 0, -frameAdj.x(), -frameAdj.y()) .contains(mouseInCell)) { // Reset ghosts to neighbor frames if (row == currentFrame) @@ -968,19 +975,19 @@ void RowArea::mousePressEvent(QMouseEvent *event) { ->isChecked() && Preferences::instance()->isOnionSkinEnabled() && o->rect(PredefinedRect::ONION_AREA) - .adjusted(0, 0, -frameAdj, 0) + .adjusted(0, 0, -frameAdj.x(), -frameAdj.y()) .contains(mouseInCell)) { if (row == currentFrame) { setDragTool( XsheetGUI::DragTool::makeCurrentFrameModifierTool(m_viewer)); frameAreaIsClicked = true; } else if (o->rect(PredefinedRect::ONION_FIXED_DOT_AREA) - .adjusted(0, 0, -frameAdj, 0) + .adjusted(0, 0, -frameAdj.x(), -frameAdj.y()) .contains(mouseInCell)) setDragTool(XsheetGUI::DragTool::makeKeyOnionSkinMaskModifierTool( m_viewer, true)); else if (o->rect(PredefinedRect::ONION_DOT_AREA) - .adjusted(0, 0, -frameAdj, 0) + .adjusted(0, 0, -frameAdj.x(), -frameAdj.y()) .contains(mouseInCell)) setDragTool(XsheetGUI::DragTool::makeKeyOnionSkinMaskModifierTool( m_viewer, false)); @@ -1000,7 +1007,7 @@ void RowArea::mousePressEvent(QMouseEvent *event) { XsheetGUI::DragTool::makeCurrentFrameModifierTool(m_viewer)); frameAreaIsClicked = true; } else if (o->rect(PredefinedRect::PLAY_RANGE) - .adjusted(0, 0, -frameAdj, 0) + .adjusted(0, 0, -frameAdj.x(), -frameAdj.y()) .contains(mouseInCell) && (row == playR0 || row == playR1)) { if (!playRangeEnabled) XsheetGUI::setPlayRange(playR0, playR1, step); @@ -1076,10 +1083,10 @@ void RowArea::mouseMoveEvent(QMouseEvent *event) { if (getDragTool()) return; - int currentRow = TApp::instance()->getCurrentFrame()->getFrame(); - int row = m_viewer->xyToPosition(m_pos).frame(); - int frameAdj = m_viewer->getFrameZoomAdjustment(); - QPoint topLeft = m_viewer->positionToXY(CellPosition(row, -1)); + int currentRow = TApp::instance()->getCurrentFrame()->getFrame(); + int row = m_viewer->xyToPosition(m_pos).frame(); + QPoint frameAdj = m_viewer->getFrameZoomAdjustment(); + QPoint topLeft = m_viewer->positionToXY(CellPosition(row, -1)); if (!m_viewer->orientation()->isVerticalTimeline()) topLeft.setY(0); else @@ -1092,7 +1099,7 @@ void RowArea::mouseMoveEvent(QMouseEvent *event) { // whether to show ability to move the shift and trace ghost frame if (CommandManager::instance()->getAction(MI_ShiftTrace)->isChecked()) { if (o->rect(PredefinedRect::SHIFTTRACE_DOT_AREA) - .adjusted(0, 0, -frameAdj, 0) + .adjusted(0, 0, -frameAdj.x(), -frameAdj.y()) .contains(mouseInCell)) { m_showOnionToSet = ShiftTraceGhost; @@ -1119,11 +1126,11 @@ void RowArea::mouseMoveEvent(QMouseEvent *event) { // whether to show ability to set onion marks else if (Preferences::instance()->isOnionSkinEnabled() && row != currentRow) { if (o->rect(PredefinedRect::ONION_FIXED_DOT_AREA) - .adjusted(0, 0, -frameAdj, 0) + .adjusted(0, 0, -frameAdj.x(), -frameAdj.y()) .contains(mouseInCell)) m_showOnionToSet = Fos; else if (o->rect(PredefinedRect::ONION_DOT_AREA) - .adjusted(0, 0, -frameAdj, 0) + .adjusted(0, 0, -frameAdj.x(), -frameAdj.y()) .contains(mouseInCell)) m_showOnionToSet = Mos; } @@ -1134,7 +1141,7 @@ void RowArea::mouseMoveEvent(QMouseEvent *event) { int pinnedCenterColumnId = -1; if (TApp::instance()->getCurrentTool()->getTool()->getName() == T_Skeleton && o->rect(PredefinedRect::PINNED_CENTER_KEY) - .adjusted(-frameAdj / 2, 0, -frameAdj / 2, 0) + .translated(-frameAdj / 2) .contains(mouseInCell)) { int col = m_viewer->getCurrentColumn(); TXsheet *xsh = m_viewer->getXsheet(); @@ -1185,7 +1192,7 @@ void RowArea::mouseMoveEvent(QMouseEvent *event) { else if (row == currentRow) { if (Preferences::instance()->isOnionSkinEnabled() && o->rect(PredefinedRect::ONION) - .adjusted(-frameAdj / 2, 0, -frameAdj / 2, 0) + .translated(-frameAdj / 2) .contains(mouseInCell)) m_tooltip = tr("Double Click to Toggle Onion Skin"); else @@ -1295,7 +1302,7 @@ int RowArea::getNonEmptyCell(int row, int column, Direction direction) { void RowArea::mouseDoubleClickEvent(QMouseEvent *event) { int currentFrame = TApp::instance()->getCurrentFrame()->getFrame(); int row = m_viewer->xyToPosition(event->pos()).frame(); - int frameAdj = m_viewer->getFrameZoomAdjustment(); + QPoint frameAdj = m_viewer->getFrameZoomAdjustment(); QPoint topLeft = m_viewer->positionToXY(CellPosition(row, -1)); if (!m_viewer->orientation()->isVerticalTimeline()) topLeft.setY(0); @@ -1307,7 +1314,7 @@ void RowArea::mouseDoubleClickEvent(QMouseEvent *event) { Preferences::instance()->isOnionSkinEnabled() && row == currentFrame && m_viewer->orientation() ->rect(PredefinedRect::ONION) - .adjusted(-frameAdj / 2, 0, -frameAdj / 2, 0) + .translated(-frameAdj / 2) .contains(mouseInCell)) { TOnionSkinMaskHandle *osmh = TApp::instance()->getCurrentOnionSkin(); OnionSkinMask osm = osmh->getOnionSkinMask(); diff --git a/toonz/sources/toonzlib/CMakeLists.txt b/toonz/sources/toonzlib/CMakeLists.txt index e382fee..70b8871 100644 --- a/toonz/sources/toonzlib/CMakeLists.txt +++ b/toonz/sources/toonzlib/CMakeLists.txt @@ -169,7 +169,6 @@ set(SOURCES autoclose.cpp autopos.cpp captureparameters.cpp - cellpositionratio.cpp childstack.cpp cleanupcolorstyles.cpp cleanuppalette.cpp diff --git a/toonz/sources/toonzlib/cellpositionratio.cpp b/toonz/sources/toonzlib/cellpositionratio.cpp deleted file mode 100644 index f3286ec..0000000 --- a/toonz/sources/toonzlib/cellpositionratio.cpp +++ /dev/null @@ -1,68 +0,0 @@ -#include "toonz/cellpositionratio.h" - -#include -#include - -// Euclid's algorithm -static int greatestCommonDivisor(int a, int b) { - a = std::abs(a); - b = std::abs(b); - int c = std::max(a, b); - int d = std::min(a, b); - while (d) { - int q = c / d; - int r = c % d; - c = d; - d = r; - } - return c; -} - -#if 0 /* UNUSED */ -int leastCommonMultiple(int a, int b) { - return a * b / greatestCommonDivisor(a, b); -} -#endif - -void Ratio::normalize() { - int gcd = greatestCommonDivisor(m_num, m_denom); - if (m_denom < 0) gcd = -gcd; - m_num /= gcd; - m_denom /= gcd; -} - -Ratio Ratio::normalized() const { - Ratio copy(*this); - copy.normalize(); - return copy; -} - -Ratio::Ratio(int num, int denom) : m_num(num), m_denom(denom) { - if (!denom) throw std::runtime_error("ratio with denominator == 0"); - normalize(); -} - -Ratio operator*(const Ratio &a, const Ratio &b) { - return Ratio(a.m_num * b.m_num, a.m_denom * b.m_denom); -} -Ratio operator/(const Ratio &a, const Ratio &b) { - return Ratio(a.m_num * b.m_denom, a.m_denom * b.m_num); -} - -Ratio operator+(const Ratio &a, const Ratio &b) { - int gcd = greatestCommonDivisor(a.m_denom, b.m_denom); - int denom = a.m_denom * b.m_denom / gcd; - int aMult = b.m_denom * gcd; - int bMult = a.m_denom * gcd; - return Ratio(a.m_num * aMult + b.m_num * bMult, denom); -} - -Ratio operator-(const Ratio &a, const Ratio &b) { - int gcd = greatestCommonDivisor(a.m_denom, b.m_denom); - int denom = a.m_denom * b.m_denom / gcd; - int aMult = b.m_denom * gcd; - int bMult = a.m_denom * gcd; - return Ratio(a.m_num * aMult - b.m_num * bMult, denom); -} - -int operator*(const Ratio &a, int b) { return a.m_num * b / a.m_denom; } diff --git a/toonz/sources/toonzlib/orientation.cpp b/toonz/sources/toonzlib/orientation.cpp index 7f7e79e..e5dbfb6 100644 --- a/toonz/sources/toonzlib/orientation.cpp +++ b/toonz/sources/toonzlib/orientation.cpp @@ -42,11 +42,12 @@ class TopToBottomOrientation : public Orientation { const int FRAME_HEADER_WIDTH = CELL_WIDTH; const int PLAY_RANGE_X = FRAME_HEADER_WIDTH / 2 - PLAY_MARKER_SIZE; const int ONION_X = 0, ONION_Y = 0; - const int ICON_WIDTH = 18; - const int ICON_HEIGHT = 18; - const int TRACKLEN = 60; - const int SHIFTTRACE_DOT_OFFSET = 3; - const int CAMERA_CELL_WIDTH = 22; + const int ICON_WIDTH = 18; + const int ICON_HEIGHT = 18; + const int TRACKLEN = 60; + const int SHIFTTRACE_DOT_OFFSET = 3; + const int CAMERA_CELL_WIDTH = 22; + const int LAYER_FOOTER_PANEL_WIDTH = 16; public: TopToBottomOrientation(); @@ -55,8 +56,8 @@ public: const ColumnFan *fan) const override; virtual QPoint positionToXY(const CellPosition &position, const ColumnFan *fan) const override; - virtual CellPositionRatio xyToPositionRatio(const QPoint &xy) const override; - virtual QPoint positionRatioToXY( + virtual CellPositionRatio xyToPositionRatio(const QPointF &xy) const override; + virtual QPointF positionRatioToXY( const CellPositionRatio &ratio) const override; virtual int colToLayerAxis(int layer, const ColumnFan *fan) const override; @@ -120,8 +121,8 @@ public: const ColumnFan *fan) const override; virtual QPoint positionToXY(const CellPosition &position, const ColumnFan *fan) const override; - virtual CellPositionRatio xyToPositionRatio(const QPoint &xy) const override; - virtual QPoint positionRatioToXY( + virtual CellPositionRatio xyToPositionRatio(const QPointF &xy) const override; + virtual QPointF positionRatioToXY( const CellPositionRatio &ratio) const override; virtual int colToLayerAxis(int layer, const ColumnFan *fan) const override; @@ -327,7 +328,12 @@ TopToBottomOrientation::TopToBottomOrientation() { addRect(PredefinedRect::LOOP_ICON, QRect(keyRect.left(), 0, 10, 11)); addRect(PredefinedRect::CAMERA_LOOP_ICON, QRect(cameraKeyRect.left(), 0, 10, 11)); - addRect(PredefinedRect::FRAME_MARKER_AREA, QRect(0, 0, -1, -1)); // hide + QRect frameMarker(CELL_WIDTH - FRAME_MARKER_SIZE - 4, + (CELL_HEIGHT - FRAME_MARKER_SIZE) / 2, FRAME_MARKER_SIZE, + FRAME_MARKER_SIZE); + addRect(PredefinedRect::FRAME_MARKER_AREA, frameMarker); + addRect(PredefinedRect::CAMERA_FRAME_MARKER_AREA, + cameraKeyRect.translated(-1, 0)); // Note viewer addRect( @@ -345,7 +351,7 @@ TopToBottomOrientation::TopToBottomOrientation() { // Row viewer addRect(PredefinedRect::FRAME_LABEL, - QRect(CELL_WIDTH / 2, 1, CELL_WIDTH / 2, CELL_HEIGHT - 2)); + QRect(0, 0, CELL_WIDTH - 4, CELL_HEIGHT)); addRect(PredefinedRect::FRAME_HEADER, QRect(0, 0, FRAME_HEADER_WIDTH, CELL_HEIGHT)); addRect(PredefinedRect::PLAY_RANGE, @@ -743,11 +749,30 @@ TopToBottomOrientation::TopToBottomOrientation() { } // Layer footer panel + QRect layerFooterPanel( + QRect(0, 0, LAYER_FOOTER_PANEL_WIDTH + 2, use_header_height)); + addRect(PredefinedRect::LAYER_FOOTER_PANEL, layerFooterPanel); + + QRect zoomSlider, zoomIn, zoomOut; + + zoomSlider = QRect(0, 17, LAYER_FOOTER_PANEL_WIDTH, use_header_height - 34); + addRect(PredefinedRect::ZOOM_SLIDER_AREA, zoomSlider); + addRect(PredefinedRect::ZOOM_SLIDER, zoomSlider.adjusted(0, 1, 0, 0)); + + zoomIn = QRect(0, zoomSlider.bottom() + 1, LAYER_FOOTER_PANEL_WIDTH, 16); + addRect(PredefinedRect::ZOOM_IN_AREA, zoomIn); + addRect(PredefinedRect::ZOOM_IN, zoomIn.adjusted(1, 1, 0, 0)); + + zoomOut = QRect(0, zoomSlider.top() - 17, LAYER_FOOTER_PANEL_WIDTH, 16); + addRect(PredefinedRect::ZOOM_OUT_AREA, zoomOut); + addRect(PredefinedRect::ZOOM_OUT, zoomOut.adjusted(1, 1, 0, 0)); + /* + // Layer footer panel addRect(PredefinedRect::LAYER_FOOTER_PANEL, QRect(0, 0, -1, -1)); // hide addRect(PredefinedRect::ZOOM_SLIDER, QRect(0, 0, -1, -1)); addRect(PredefinedRect::ZOOM_IN, QRect(0, 0, -1, -1)); addRect(PredefinedRect::ZOOM_OUT, QRect(0, 0, -1, -1)); - + */ // // Lines // @@ -770,12 +795,14 @@ TopToBottomOrientation::TopToBottomOrientation() { addDimension(PredefinedDimension::INDEX, 0); addDimension(PredefinedDimension::SOUND_AMPLITUDE, int(sqrt(CELL_HEIGHT * soundRect.width()) / 2)); - addDimension(PredefinedDimension::FRAME_LABEL_ALIGN, Qt::AlignCenter); + addDimension(PredefinedDimension::FRAME_LABEL_ALIGN, + Qt::AlignVCenter | Qt::AlignRight); addDimension(PredefinedDimension::ONION_TURN, 0); addDimension(PredefinedDimension::QBOXLAYOUT_DIRECTION, QBoxLayout::Direction::TopToBottom); addDimension(PredefinedDimension::CENTER_ALIGN, Qt::AlignHCenter); addDimension(PredefinedDimension::CAMERA_LAYER, CAMERA_CELL_WIDTH); + addDimension(PredefinedDimension::SCALE_THRESHOLD, 57); // // Paths @@ -786,6 +813,13 @@ TopToBottomOrientation::TopToBottomOrientation() { corner.lineTo(QPointF(0, CELL_HEIGHT)); addPath(PredefinedPath::DRAG_HANDLE_CORNER, corner); + QPainterPath diamond(QPointF(0, -4)); + diamond.lineTo(4, 0); + diamond.lineTo(0, 4); + diamond.lineTo(-4, 0); + diamond.lineTo(0, -4); + addPath(PredefinedPath::FRAME_MARKER_DIAMOND, diamond); + QPainterPath fromTriangle(QPointF(0, EASE_TRIANGLE_SIZE / 2)); fromTriangle.lineTo(QPointF(EASE_TRIANGLE_SIZE, -EASE_TRIANGLE_SIZE / 2)); fromTriangle.lineTo(QPointF(-EASE_TRIANGLE_SIZE, -EASE_TRIANGLE_SIZE / 2)); @@ -880,16 +914,16 @@ QPoint TopToBottomOrientation::positionToXY(const CellPosition &position, return QPoint(x, y); } CellPositionRatio TopToBottomOrientation::xyToPositionRatio( - const QPoint &xy) const { - Ratio frame{xy.y(), CELL_HEIGHT}; - Ratio layer{xy.x(), CELL_WIDTH}; + const QPointF &xy) const { + double frame = xy.y() / (double)CELL_HEIGHT; + double layer = xy.x() / (double)CELL_WIDTH; return CellPositionRatio{frame, layer}; } -QPoint TopToBottomOrientation::positionRatioToXY( +QPointF TopToBottomOrientation::positionRatioToXY( const CellPositionRatio &ratio) const { - int x = ratio.layer() * CELL_WIDTH; - int y = ratio.frame() * CELL_HEIGHT; - return QPoint(x, y); + double x = ratio.layer() * (double)CELL_WIDTH; + double y = ratio.frame() * (double)CELL_HEIGHT; + return QPointF(x, y); } int TopToBottomOrientation::colToLayerAxis(int layer, @@ -975,6 +1009,8 @@ LeftToRightOrientation::LeftToRightOrientation() { CELL_HEIGHT - FRAME_MARKER_SIZE - 7, FRAME_MARKER_SIZE, FRAME_MARKER_SIZE); addRect(PredefinedRect::FRAME_MARKER_AREA, frameMarker); + addRect(PredefinedRect::CAMERA_FRAME_MARKER_AREA, + rect(PredefinedRect::FRAME_MARKER_AREA)); // Notes viewer addRect( @@ -1182,6 +1218,7 @@ LeftToRightOrientation::LeftToRightOrientation() { QBoxLayout::Direction::LeftToRight); addDimension(PredefinedDimension::CENTER_ALIGN, Qt::AlignVCenter); addDimension(PredefinedDimension::CAMERA_LAYER, CAMERA_CELL_HEIGHT); + addDimension(PredefinedDimension::SCALE_THRESHOLD, 50); // // Paths @@ -1279,16 +1316,16 @@ QPoint LeftToRightOrientation::positionToXY(const CellPosition &position, return QPoint(x, y); } CellPositionRatio LeftToRightOrientation::xyToPositionRatio( - const QPoint &xy) const { - Ratio frame{xy.x(), CELL_WIDTH}; - Ratio layer{xy.y(), CELL_HEIGHT}; + const QPointF &xy) const { + double frame = xy.x() / (double)CELL_WIDTH; + double layer = xy.y() / (double)CELL_HEIGHT; return CellPositionRatio{frame, layer}; } -QPoint LeftToRightOrientation::positionRatioToXY( +QPointF LeftToRightOrientation::positionRatioToXY( const CellPositionRatio &ratio) const { - int x = ratio.frame() * CELL_WIDTH; - int y = ratio.layer() * CELL_HEIGHT; - return QPoint(x, y); + double x = ratio.frame() * (double)CELL_WIDTH; + double y = ratio.layer() * (double)CELL_HEIGHT; + return QPointF(x, y); } int LeftToRightOrientation::colToLayerAxis(int layer, diff --git a/toonz/sources/toonzlib/txsheethandle.cpp b/toonz/sources/toonzlib/txsheethandle.cpp index 3b79750..ad1b142 100644 --- a/toonz/sources/toonzlib/txsheethandle.cpp +++ b/toonz/sources/toonzlib/txsheethandle.cpp @@ -9,7 +9,7 @@ // TXsheeHandle //----------------------------------------------------------------------------- -TXsheetHandle::TXsheetHandle() : m_xsheet(0) {} +TXsheetHandle::TXsheetHandle() : m_xsheet(0), m_zoomFactor(100) {} //----------------------------------------------------------------------------- diff --git a/toonz/sources/toonzqt/functionsheet.cpp b/toonz/sources/toonzqt/functionsheet.cpp index 714008f..593617a 100644 --- a/toonz/sources/toonzqt/functionsheet.cpp +++ b/toonz/sources/toonzqt/functionsheet.cpp @@ -27,6 +27,7 @@ #include #include //for drag&drop #include +#include //******************************************************************************** // Local namespace stuff @@ -187,6 +188,48 @@ public: }; //******************************************************************************** +// FunctionSheetButtonArea implementation +//******************************************************************************** + +FunctionSheetButtonArea::FunctionSheetButtonArea(QWidget *parent) + : QWidget(parent) { + m_syncSizeBtn = new QPushButton("", this); + m_syncSizeBtn->setCheckable(true); + m_syncSizeBtn->setFixedSize(20, 20); + static QPixmap syncScaleImg = + recolorPixmap(svgToPixmap(getIconThemePath("actions/17/syncscale.svg"))); + QPixmap offPm(17, 17); + offPm.fill(Qt::transparent); + { + QPainter p(&offPm); + p.setOpacity(0.7); + p.drawPixmap(0, 0, syncScaleImg); + } + QIcon icon; + icon.addPixmap(offPm); + icon.addPixmap(syncScaleImg, QIcon::Normal, QIcon::On); + m_syncSizeBtn->setIcon(icon); + + m_syncSizeBtn->setToolTip(tr("Toggle synchronizing zoom with xsheet")); + + QVBoxLayout *layout = new QVBoxLayout(); + layout->setMargin(2); + layout->setSpacing(0); + { + layout->addStretch(); + layout->addWidget(m_syncSizeBtn, 0, Qt::AlignCenter); + } + setLayout(layout); + + connect(m_syncSizeBtn, SIGNAL(clicked(bool)), this, + SIGNAL(syncSizeBtnToggled(bool))); +} + +void FunctionSheetButtonArea::setSyncSizeBtnState(bool on) { + m_syncSizeBtn->setChecked(on); +} + +//******************************************************************************** // FunctionSheetRowViewer implementation //******************************************************************************** @@ -655,6 +698,11 @@ void FunctionSheetCellViewer::drawCells(QPainter &painter, int r0, int c0, TXsheet *xsh = m_sheet->getViewer()->getXsheetHandle()->getXsheet(); + bool simpleView = getViewer()->getFrameZoomFactor() <= + Orientations::topToBottom()->dimension( + PredefinedDimension::SCALE_THRESHOLD); + bool showIbtwn = !simpleView && m_sheet->isIbtwnValueVisible(); + // top and bottom pos int y0 = getViewer()->rowToY(r0); int y1 = getViewer()->rowToY(r1 + 1) - 1; @@ -723,7 +771,7 @@ void FunctionSheetCellViewer::drawCells(QPainter &painter, int r0, int c0, // when the inbetween values are hidden, change the cell colors to // semi-transparent if the frame is in middle of the value step - if (!m_sheet->isIbtwnValueVisible()) { + if (!showIbtwn) { TDoubleKeyframe kf = curve->getKeyframe(curve->getPrevKeyframe(row)); int step = kf.m_step; @@ -751,9 +799,8 @@ void FunctionSheetCellViewer::drawCells(QPainter &painter, int r0, int c0, } } - drawValue = (curve->isKeyframe(row)) - ? Key - : (m_sheet->isIbtwnValueVisible()) ? Inbetween : None; + drawValue = + (curve->isKeyframe(row)) ? Key : (showIbtwn) ? Inbetween : None; } // empty cells @@ -1138,7 +1185,8 @@ FunctionSheet::FunctionSheet(QWidget *parent, bool isFloating) : SpreadsheetViewer(parent) , m_selectedCells() , m_selection(0) - , m_isFloating(isFloating) { + , m_isFloating(isFloating) + , m_buttonArea(nullptr) { setColumnsPanel(m_columnHeadViewer = new FunctionSheetColumnHeadViewer(this)); setRowsPanel(m_rowViewer = new FunctionSheetRowViewer(this)); setCellsPanel(m_cellViewer = new FunctionSheetCellViewer(this)); @@ -1156,6 +1204,10 @@ FunctionSheet::FunctionSheet(QWidget *parent, bool isFloating) setGeometry(settings.value("FunctionSpreadsheet", QRect(500, 500, 400, 300)) .toRect()); } + + setButtonAreaWidget(m_buttonArea = new FunctionSheetButtonArea(this)); + connect(m_buttonArea, SIGNAL(syncSizeBtnToggled(bool)), this, + SLOT(onSyncSizeBtnToggled(bool))); } //----------------------------------------------------------------------------- @@ -1189,6 +1241,12 @@ void FunctionSheet::setSelection(FunctionSelection *selection) { void FunctionSheet::showEvent(QShowEvent *e) { m_frameScroller.registerFrameScroller(); SpreadsheetViewer::showEvent(e); + + if (m_xshHandle && m_syncSize) { + connect(m_xshHandle, SIGNAL(zoomScaleChanged()), this, + SLOT(onZoomScaleChanged())); + onZoomScaleChanged(); + } } //----------------------------------------------------------------------------- @@ -1196,6 +1254,11 @@ void FunctionSheet::showEvent(QShowEvent *e) { void FunctionSheet::hideEvent(QHideEvent *e) { m_frameScroller.unregisterFrameScroller(); SpreadsheetViewer::hideEvent(e); + + if (m_xshHandle && m_syncSize) { + disconnect(m_xshHandle, SIGNAL(zoomScaleChanged()), this, + SLOT(onZoomScaleChanged())); + } } //----------------------------------------------------------------------------- @@ -1343,4 +1406,49 @@ TStageObject *FunctionSheet::getStageObject(int column) { if (!stageItem) return nullptr; return stageItem->getStageObject(); +} + +//----------------------------------------------------------------------------- + +void FunctionSheet::setSyncSize(bool on) { + m_syncSize = on; + m_buttonArea->setSyncSizeBtnState(on); + update(); +} + +//----------------------------------------------------------------------------- + +int FunctionSheet::getFrameZoomFactor() const { + if (m_syncSize && m_xshHandle) { + int zoomFactor = m_xshHandle->getZoomFactor(); + return 50 + (zoomFactor - 20) * 5 / 8; + } + return 100; +} + +//----------------------------------------------------------------------------- + +void FunctionSheet::onSyncSizeBtnToggled(bool on) { + // switch the flag + m_syncSize = on; + + if (m_xshHandle) { + if (on) + connect(m_xshHandle, SIGNAL(zoomScaleChanged()), this, + SLOT(onZoomScaleChanged())); + else + disconnect(m_xshHandle, SIGNAL(zoomScaleChanged()), this, + SLOT(onZoomScaleChanged())); + onZoomScaleChanged(); + } +} + +//----------------------------------------------------------------------------- + +void FunctionSheet::onZoomScaleChanged() { + QPoint xyOrig = positionToXY(CellPosition(getCurrentFrame(), -1)); + setScaleFactor(getFrameZoomFactor()); + QPoint xyNew = positionToXY(CellPosition(getCurrentFrame(), -1)); + scroll(xyNew - xyOrig); + update(); } \ No newline at end of file diff --git a/toonz/sources/toonzqt/functionviewer.cpp b/toonz/sources/toonzqt/functionviewer.cpp index a0d4a6a..a138303 100644 --- a/toonz/sources/toonzqt/functionviewer.cpp +++ b/toonz/sources/toonzqt/functionviewer.cpp @@ -387,6 +387,7 @@ void FunctionViewer::setXsheetHandle(TXsheetHandle *xshHandle) { m_xshHandle = xshHandle; m_segmentViewer->setXsheetHandle(xshHandle); m_treeView->setXsheetHandle(xshHandle); + m_numericalColumns->setXsheetHandle(xshHandle); if (m_xshHandle && isVisible()) { TXsheet *xsh = m_xshHandle->getXsheet(); @@ -729,6 +730,7 @@ void FunctionViewer::save(QSettings &settings) const { settings.setValue("toggleStatus", m_toggleStatus); settings.setValue("showIbtwnValuesInSheet", m_numericalColumns->isIbtwnValueVisible()); + settings.setValue("syncSize", m_numericalColumns->isSyncSize()); } //---------------------------------------------------------------------------- @@ -744,6 +746,10 @@ void FunctionViewer::load(QSettings &settings) { m_numericalColumns->isIbtwnValueVisible()) .toBool(); m_numericalColumns->setIbtwnValueVisible(ibtwnVisible); + + bool syncSize = + settings.value("syncSize", m_numericalColumns->isSyncSize()).toBool(); + m_numericalColumns->setSyncSize(syncSize); } //----------------------------------------------------------------------------- diff --git a/toonz/sources/toonzqt/spreadsheetviewer.cpp b/toonz/sources/toonzqt/spreadsheetviewer.cpp index 82e0698..c52ddb4 100644 --- a/toonz/sources/toonzqt/spreadsheetviewer.cpp +++ b/toonz/sources/toonzqt/spreadsheetviewer.cpp @@ -82,11 +82,12 @@ void FrameScroller::handleScroll(QPoint &offset) { offset.y())) // only synchronize changes by frames axis return; + QPointF offsetF(offset); // In case of a zoomed viewer is sending this out, adjust the // zoomed offset back to a standardized offset - emit zoomScrollAdjust(offset, false); + emit zoomScrollAdjust(offsetF, false); - CellPositionRatio ratio = orientation()->xyToPositionRatio(offset); + CellPositionRatio ratio = orientation()->xyToPositionRatio(offsetF); for (int i = 0; i < frameScrollers.size(); i++) if (frameScrollers[i] != this) { @@ -100,10 +101,11 @@ void FrameScroller::handleScroll(QPoint &offset) { void adjustScrollbar(QScrollBar *scrollBar, int add); void FrameScroller::onScroll(const CellPositionRatio &ratio) { - QPoint offset = orientation()->positionRatioToXY(ratio); + QPointF offset = orientation()->positionRatioToXY(ratio); // In case of a zoomed viewer is receiving this, adjust the // standardized offset to zoomed offset + emit zoomScrollAdjust(offset, true); // scroll area should be resized before moving down the scroll bar. @@ -111,11 +113,11 @@ void FrameScroller::onScroll(const CellPositionRatio &ratio) { // since the receiver is in the same thread. // when moving up the scroll bar, resizing will be done in // SpreadsheetViewer::onVSliderChanged(). - if (offset.x() > 0 || offset.y() > 0) emit prepareToScrollOffset(offset); - if (offset.x()) - adjustScrollbar(m_scrollArea->horizontalScrollBar(), offset.x()); - if (offset.y()) - adjustScrollbar(m_scrollArea->verticalScrollBar(), offset.y()); + if (offset.x() > 0.0 || offset.y() > 0.0) emit prepareToScrollOffset(offset); + if ((int)offset.x()) + adjustScrollbar(m_scrollArea->horizontalScrollBar(), (int)offset.x()); + if ((int)offset.y()) + adjustScrollbar(m_scrollArea->verticalScrollBar(), (int)offset.y()); } void adjustScrollbar(QScrollBar *scrollBar, int add) { @@ -130,14 +132,14 @@ void FrameScroller::unregisterFrameScroller() { if (frameScrollers.contains(this)) frameScrollers.removeAll(this); } -void FrameScroller::prepareToScrollOthers(const QPoint &offset) { +void FrameScroller::prepareToScrollOthers(const QPointF &offset) { CellPositionRatio ratio = orientation()->xyToPositionRatio(offset); for (int i = 0; i < frameScrollers.size(); i++) if (frameScrollers[i] != this) frameScrollers[i]->prepareToScrollRatio(ratio); } void FrameScroller::prepareToScrollRatio(const CellPositionRatio &ratio) { - QPoint offset = orientation()->positionRatioToXY(ratio); + QPointF offset = orientation()->positionRatioToXY(ratio); emit prepareToScrollOffset(offset); } @@ -321,9 +323,13 @@ void RowPanel::drawRows(QPainter &p, int r0, int r1) { int y0 = visibleRect.top(); int y1 = visibleRect.bottom(); + bool simpleView = getViewer()->getFrameZoomFactor() <= + Orientations::topToBottom()->dimension( + PredefinedDimension::SCALE_THRESHOLD); int r; + int y = getViewer()->rowToY(r0); for (r = r0; r <= r1; r++) { - int y = getViewer()->rowToY(r); + int next_y = getViewer()->rowToY(r + 1); // draw horizontal line QColor color = (getViewer()->isMarkRow(r)) ? getViewer()->getMarkerLineColor() @@ -331,12 +337,18 @@ void RowPanel::drawRows(QPainter &p, int r0, int r1) { p.setPen(color); p.drawLine(x0, y, x1, y); + if (simpleView && r > 0 && !getViewer()->isMarkRow(r + 1)) { + y = next_y; + continue; + } + // draw numbers p.setPen(getViewer()->getTextColor()); QString number = QString::number(r + 1); - p.drawText(QRect(x0, y + 1, width(), 18), - Qt::AlignHCenter | Qt::AlignBottom, number); + p.drawText(QRect(x0, y + 1, width() - 4, next_y - y - 1), + Qt::AlignVCenter | Qt::AlignRight, number); + y = next_y; } // erase the marker interval at upper-end if (r0 == 0) { @@ -349,9 +361,13 @@ void RowPanel::drawRows(QPainter &p, int r0, int r1) { void RowPanel::drawCurrentRowGadget(QPainter &p, int r0, int r1) { int currentRow = getViewer()->getCurrentRow(); - int y = getViewer()->rowToY(currentRow); + // int y = getViewer()->rowToY(currentRow); if (currentRow < r0 || r1 < currentRow) return; - p.fillRect(1, y + 1, width() - 1, 19, getViewer()->getCurrentRowBgColor()); + int top = getViewer()->rowToY(currentRow); + int bottom = getViewer()->rowToY(currentRow + 1) - 1; + QRect rect(1, top, width() - 1, bottom - top); + + p.fillRect(rect, getViewer()->getCurrentRowBgColor()); } //----------------------------------------------------------------------------- @@ -455,6 +471,7 @@ SpreadsheetViewer::SpreadsheetViewer(QWidget *parent) , m_frameHandle(0) , m_columnWidth(50) , m_rowHeight(20) + , m_scaleFactor(100) , m_timerId(0) , m_autoPanSpeed(0, 0) , m_lastAutoPanPos(0, 0) @@ -501,12 +518,14 @@ SpreadsheetViewer::SpreadsheetViewer(QWidget *parent) QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Ignored)); m_rowScrollArea->setFixedWidth(30); - m_columnScrollArea->setFixedHeight(m_rowHeight * 3 - 3); + m_columnScrollArea->setFixedHeight(m_rowHeight * 3 - 4); // m_columnScrollArea->setFixedHeight(m_rowHeight * 3 + 60 - 63); m_frameScroller.setFrameScrollArea(m_cellScrollArea); connect(&m_frameScroller, &Spreadsheet::FrameScroller::prepareToScrollOffset, this, &SpreadsheetViewer::onPrepareToScrollOffset); + connect(&m_frameScroller, &Spreadsheet::FrameScroller::zoomScrollAdjust, this, + &SpreadsheetViewer::onZoomScrollAdjust); //---- layout QGridLayout *layout = new QGridLayout(); @@ -520,7 +539,8 @@ SpreadsheetViewer::SpreadsheetViewer(QWidget *parent) int scrollBarWidth = 16; // upper-right QWidget *w = new QWidget(this); - w->setFixedSize(QSize(scrollBarWidth, m_rowHeight * 3 + 60 - 63)); + w->setFixedWidth(scrollBarWidth); + w->setFixedHeight(m_columnScrollArea->height()); layout->addWidget(w, 0, 2); // lower-left @@ -584,6 +604,11 @@ void SpreadsheetViewer::setCellsPanel(Spreadsheet::CellPanel *cells) { m_cellScrollArea->setWidget(cells); } +void SpreadsheetViewer::setButtonAreaWidget(QWidget *widget) { + QGridLayout *lay = dynamic_cast(layout()); + lay->addWidget(widget, 0, 0); +} + void SpreadsheetViewer::setRowCount(int rowCount) { if (m_rowCount != rowCount) { m_rowCount = rowCount; @@ -619,6 +644,10 @@ void SpreadsheetViewer::scroll(QPoint delta) { else if (!notUpdateSizeH && notUpdateSizeV) refreshContentSize(x, 0); + // Recheck in case refreshContentSize changed the max + if (!notUpdateSizeH) maxValueH = hSc->maximum(); + if (!notUpdateSizeV) maxValueV = vSc->maximum(); + if (valueH > maxValueH && x > 0) valueH = hSc->maximum(); if (valueV > maxValueV && y > 0) valueV = vSc->maximum(); @@ -627,8 +656,22 @@ void SpreadsheetViewer::scroll(QPoint delta) { vSc->setValue(valueV); } -void SpreadsheetViewer::onPrepareToScrollOffset(const QPoint &offset) { - refreshContentSize(offset.x(), offset.y()); +void SpreadsheetViewer::onPrepareToScrollOffset(const QPointF &offset) { + refreshContentSize((int)offset.x(), (int)offset.y()); +} + +void SpreadsheetViewer::onZoomScrollAdjust(QPointF &offset, bool toZoom) { + double frameZoomFactor = (double)getFrameZoomFactor(); + + // toZoom = true: Adjust standardized offset down to zoom factor + // toZoom = false: Adjust zoomed offset up to standardized offset + double newY; + if (toZoom) + newY = (offset.y() * frameZoomFactor) / 100.0; + else + newY = (offset.y() * 100.0) / frameZoomFactor; + + offset.setY(newY); } void SpreadsheetViewer::setAutoPanSpeed(const QPoint &speed) { @@ -686,7 +729,7 @@ int SpreadsheetViewer::rowToY(int row) const { /*!Shift is a consequence of style sheet border.*/ CellPosition SpreadsheetViewer::xyToPosition(const QPoint &point) const { - int row = (point.y() + 1) / m_rowHeight; + int row = (point.y() * 100 / m_scaleFactor) / m_rowHeight; int col = (point.x()) / m_columnWidth; return CellPosition(row, col); } @@ -694,7 +737,8 @@ CellPosition SpreadsheetViewer::xyToPosition(const QPoint &point) const { /*!Shift is a consequence of style sheet border.*/ QPoint SpreadsheetViewer::positionToXY(const CellPosition &pos) const { int x = (pos.layer() * m_columnWidth); - int y = (pos.frame() * m_rowHeight) - 1; + int y = pos.frame() * m_rowHeight * m_scaleFactor / 100; + // int y = (pos.frame() * m_rowHeight * m_scaleFactor / 100) - 1; return QPoint(x, y); } @@ -728,6 +772,7 @@ bool SpreadsheetViewer::refreshContentSize(int scrollDx, int scrollDy) { m_columnScrollArea->widget()->setFixedSize( actualSize.width(), m_columnScrollArea->viewport()->height()); m_isComputingSize = false; + return true; } } @@ -738,7 +783,8 @@ void SpreadsheetViewer::showEvent(QShowEvent *) { QScrollBar *vSc = m_cellScrollArea->verticalScrollBar(); int actualContentHeight = std::max(contentHeight, vSc->value() + viewportHeight); - m_rowScrollArea->widget()->setFixedHeight(actualContentHeight); + m_rowScrollArea->widget()->setFixedSize(m_rowScrollArea->viewport()->width(), + actualContentHeight); m_cellScrollArea->widget()->setFixedHeight(actualContentHeight); if (m_frameHandle) connect(m_frameHandle, SIGNAL(frameSwitched()), this,