Timeline zoom control update (#1947)

close #1689
This commit is contained in:
manongjohn 2018-05-16 04:23:35 -04:00 committed by shun-iwasawa
parent 9ce0c271a7
commit e71b98140e
10 changed files with 372 additions and 74 deletions

View file

@ -107,10 +107,17 @@ enum class PredefinedRect {
PEGBAR_NAME, //! where to display pegbar name
PARENT_HANDLE_NAME, //! where to display parent handle number
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
FRAME_DOT, //! Cell's frame indicator
FRAME_INDICATOR //! Row # indicator
CONFIG_AREA, //! clickable area larger than the config icon, containing it
CONFIG, //! the config icon itself
FRAME_DOT, //! Cell's frame indicator
FRAME_INDICATOR, //! Row # indicator
ZOOM_SLIDER_AREA,
ZOOM_SLIDER,
ZOOM_IN_AREA,
ZOOM_IN,
ZOOM_OUT_AREA,
ZOOM_OUT,
LAYER_FOOTER_PANEL
};
enum class PredefinedLine {
LOCKED, //! dotted vertical line when cell is locked

View file

@ -64,7 +64,8 @@ set(MOC_HEADERS
keyframedata.h
keyframeselection.h
keyframemover.h
layerheaderpanel.h
layerfooterpanel.h
layerheaderpanel.h
levelcreatepopup.h
levelsettingspopup.h
linesfadepopup.h
@ -230,7 +231,8 @@ set(SOURCES
fxparameditorpopup.cpp
histogrampopup.cpp
insertfxpopup.cpp
layerheaderpanel.cpp
layerfooterpanel.cpp
layerheaderpanel.cpp
levelcreatepopup.cpp
levelsettingspopup.cpp
linetestcapturepane.cpp

View file

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.0" id="Ebene_2" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 235.9 228.5" style="enable-background:new 0 0 235.9 228.5;" xml:space="preserve">
<style type="text/css">
.st0{fill:#E1E1E1;}
</style>
<rect x="-0.44491577" id="rect824" y="0.55508518" class="st0" width="236" height="228" style="fill:#e6e6e6;fill-opacity:0.29019608" />
<polygon class="st0" points="5.8,155.9 71.4,90.1 95.5,113.8 54,155.8 "/>
<polygon class="st0" points="66.6,156.1 149.1,73.3 232,156.2 "/>
</svg>

After

Width:  |  Height:  |  Size: 691 B

View file

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.0" id="Ebene_3" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 235.9 228.5" style="enable-background:new 0 0 235.9 228.5;" xml:space="preserve">
<style type="text/css">
.st0{fill:#E1E1E1;}
</style>
<rect x="0.12288401" id="rect824" y="0.25000307" class="st0" width="236" height="228" style="fill:#e6e6e6;fill-opacity:0.29019608" />
<polygon class="st0" points="55.6,156 93.5,118 111.1,135.3 138.4,108.3 186,156.2 "/>
</svg>

After

Width:  |  Height:  |  Size: 637 B

View file

@ -0,0 +1,217 @@
#include "layerfooterpanel.h"
#include <QPainter>
#include <QToolTip>
#include <QScrollBar>
#include "xsheetviewer.h"
#include "xshcolumnviewer.h"
#include "tapp.h"
#include "toonz/tscenehandle.h"
#include "toonz/txsheethandle.h"
#include "toonz/tobjecthandle.h"
#include "toonz/preferences.h"
#include "toonzqt/gutil.h"
using XsheetGUI::ColumnArea;
#if QT_VERSION >= 0x050500
LayerFooterPanel::LayerFooterPanel(XsheetViewer *viewer, QWidget *parent,
Qt::WindowFlags flags)
#else
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);
setObjectName("layerFooterPanel");
setFixedSize(rect.size());
setMouseTracking(true);
m_frameZoomSlider = new QSlider(Qt::Horizontal, this);
m_frameZoomSlider->setMinimum(20);
m_frameZoomSlider->setMaximum(100);
m_frameZoomSlider->setValue(m_viewer->getFrameZoomFactor());
m_frameZoomSlider->setToolTip(tr("Zoom in/out of timeline"));
connect(m_frameZoomSlider, SIGNAL(valueChanged(int)), this,
SLOT(onFrameZoomSliderValueChanged(int)));
}
LayerFooterPanel::~LayerFooterPanel() {}
namespace {
QColor mix(const QColor &a, const QColor &b, double w) {
return QColor(a.red() * w + b.red() * (1 - w),
a.green() * w + b.green() * (1 - w),
a.blue() * w + b.blue() * (1 - w));
}
QColor withAlpha(const QColor &color, double alpha) {
QColor result(color);
result.setAlpha(alpha * 255);
return result;
}
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()); }
}
void LayerFooterPanel::paintEvent(QPaintEvent *event) {
QPainter p(this);
p.setRenderHint(QPainter::SmoothPixmapTransform, true);
const Orientation *o = Orientations::leftToRight();
QRect zoomSliderRect = o->rect(PredefinedRect::ZOOM_SLIDER_AREA);
p.fillRect(zoomSliderRect, Qt::NoBrush);
QRect sliderObjRect = o->rect(PredefinedRect::ZOOM_SLIDER);
m_frameZoomSlider->setGeometry(sliderObjRect);
static QPixmap zoomIn = svgToPixmap(":Resources/zoom_in.svg");
static QPixmap zoomInRollover = svgToPixmap(":Resources/zoom_in_rollover.svg");
const QRect zoomInImgRect = o->rect(PredefinedRect::ZOOM_IN);
static QPixmap zoomOut = svgToPixmap(":Resources/zoom_out.svg");
static QPixmap zoomOutRollover = svgToPixmap(":Resources/zoom_out_rollover.svg");
const QRect zoomOutImgRect = o->rect(PredefinedRect::ZOOM_OUT);
p.setRenderHint(QPainter::SmoothPixmapTransform, true);
if (m_zoomInHighlighted)
p.drawPixmap(zoomInImgRect, zoomInRollover);
else
p.drawPixmap(zoomInImgRect, zoomIn);
if (m_zoomOutHighlighted)
p.drawPixmap(zoomOutImgRect, zoomOutRollover);
else
p.drawPixmap(zoomOutImgRect, zoomOut);
p.setPen(withAlpha(m_viewer->getTextColor(), 0.5));
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();
}
//-----------------------------------------------------------------------------
void LayerFooterPanel::enterEvent(QEvent *) {
m_zoomInHighlighted = false;
m_zoomOutHighlighted = false;
update();
}
void LayerFooterPanel::leaveEvent(QEvent *) {
m_zoomInHighlighted = false;
m_zoomOutHighlighted = false;
update();
}
void LayerFooterPanel::mousePressEvent(QMouseEvent *event) {
const Orientation *o = Orientations::leftToRight();
if (event->button() == Qt::LeftButton) {
// get mouse position
QPoint pos = event->pos();
if (o->rect(PredefinedRect::ZOOM_IN_AREA).contains(pos)) {
int newFactor = isCtrlPressed ? m_frameZoomSlider->maximum()
: m_frameZoomSlider->value() + 10;
m_frameZoomSlider->setValue(newFactor);
}
else if (o->rect(PredefinedRect::ZOOM_OUT_AREA).contains(pos)) {
int newFactor = isCtrlPressed ? m_frameZoomSlider->minimum()
: m_frameZoomSlider->value() - 10;
m_frameZoomSlider->setValue(newFactor);
}
}
update();
}
void LayerFooterPanel::mouseMoveEvent(QMouseEvent *event) {
const Orientation *o = Orientations::leftToRight();
QPoint pos = event->pos();
m_zoomInHighlighted = false;
m_zoomOutHighlighted = false;
if (o->rect(PredefinedRect::ZOOM_IN_AREA).contains(pos)) {
m_zoomInHighlighted = true;
m_tooltip = tr("Zoom in (Ctrl-click to zoom in all the way)");
}
else if (o->rect(PredefinedRect::ZOOM_OUT_AREA)
.contains(pos)) {
m_zoomOutHighlighted = true;
m_tooltip = tr("Zoom out (Ctrl-click to zoom out all the way)");
}
else {
m_tooltip = tr("");
}
m_pos = pos;
update();
}
//-----------------------------------------------------------------------------
bool LayerFooterPanel::event(QEvent *event) {
if (event->type() == QEvent::ToolTip) {
if (!m_tooltip.isEmpty())
QToolTip::showText(mapToGlobal(m_pos), m_tooltip);
else
QToolTip::hideText();
}
return QWidget::event(event);
}
//-----------------------------------------------------------------------------
void LayerFooterPanel::setZoomSliderValue(int val) {
if (val > m_frameZoomSlider->maximum())
val = m_frameZoomSlider->maximum();
else if (val < m_frameZoomSlider->minimum())
val = m_frameZoomSlider->minimum();
m_frameZoomSlider->blockSignals(true);
m_frameZoomSlider->setValue(val);
m_frameZoomSlider->blockSignals(false);
}
//-----------------------------------------------------------------------------
void LayerFooterPanel::onFrameZoomSliderValueChanged(int val) {
m_viewer->zoomOnFrame(m_viewer->getCurrentRow(), val);
}
//-----------------------------------------------------------------------------
void LayerFooterPanel::onControlPressed(bool pressed) {
isCtrlPressed = pressed;
update();
}
//-----------------------------------------------------------------------------
const bool LayerFooterPanel::isControlPressed() { return isCtrlPressed; }

View file

@ -0,0 +1,66 @@
#pragma once
#ifndef LAYER_FOOTER_PANEL_INCLUDED
#define LAYER_FOOTER_PANEL_INCLUDED
#include <QWidget>
#include <QSlider>
#include <QKeyEvent>
#include <boost/optional.hpp>
#include "orientation.h"
using boost::optional;
class XsheetViewer;
// Panel showing column footers for layers in timeline mode
class LayerFooterPanel final : public QWidget {
Q_OBJECT
QString m_tooltip;
QPoint m_pos;
QSlider *m_frameZoomSlider;
bool isCtrlPressed = false;
bool m_zoomInHighlighted = false;
bool m_zoomOutHighlighted = false;
private:
XsheetViewer *m_viewer;
public:
#if QT_VERSION >= 0x050500
LayerFooterPanel(XsheetViewer *viewer, QWidget *parent = 0,
Qt::WindowFlags flags = 0);
#else
LayerFooterPanel(XsheetViewer *viewer, QWidget *parent = 0,
Qt::WFlags flags = 0);
#endif
~LayerFooterPanel();
void showOrHide(const Orientation *o);
void setZoomSliderValue(int val);
void onControlPressed(bool pressed);
const bool isControlPressed();
protected:
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 keyPressEvent(QKeyEvent *event) override { event->ignore(); }
void wheelEvent(QWheelEvent *event) override { event->ignore(); }
public slots:
void onFrameZoomSliderValueChanged(int val);
};
#endif
#pragma once

View file

@ -457,5 +457,7 @@
<file>Resources/refresh_over.svg</file>
<file>Resources/zoom_in.svg</file>
<file>Resources/zoom_out.svg</file>
<file>Resources/zoom_in_rollover.svg</file>
<file>Resources/zoom_out_rollover.svg</file>
</qresource>
</RCC>

View file

@ -48,11 +48,12 @@ TEnv::IntVar FrameDisplayStyleInXsheetRowArea(
namespace XsheetGUI {
//-----------------------------------------------------------------------------
const int ColumnWidth = 74;
const int RowHeight = 20;
const int SCROLLBAR_WIDTH = 16;
const int TOOLBAR_HEIGHT = 30;
const int ZOOM_SLIDER_WIDTH = 80;
const int ColumnWidth = 74;
const int RowHeight = 20;
const int SCROLLBAR_WIDTH = 16;
const int TOOLBAR_HEIGHT = 30;
const int ZOOM_FACTOR_MAX = 100;
const int ZOOM_FACTOR_MIN = 20;
} // namespace XsheetGUI
//=============================================================================
@ -267,18 +268,14 @@ XsheetViewer::XsheetViewer(QWidget *parent, Qt::WFlags flags)
m_rowScrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
m_rowScrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
m_layerFooterPanel = new LayerFooterPanel(this, this);
m_frameScroller.setFrameScrollArea(m_cellScrollArea);
connect(&m_frameScroller, &Spreadsheet::FrameScroller::prepareToScrollOffset,
this, &XsheetViewer::onPrepareToScrollOffset);
connect(&m_frameScroller, &Spreadsheet::FrameScroller::zoomScrollAdjust, this,
&XsheetViewer::onZoomScrollAdjust);
m_frameZoomSlider = new QSlider(Qt::Horizontal, this);
m_frameZoomSlider->setMinimum(20);
m_frameZoomSlider->setMaximum(100);
m_frameZoomSlider->setValue(m_frameZoomFactor);
m_frameZoomSlider->setToolTip(tr("Zoom in/out of timeline"));
connectScrollBars();
connect(this, &XsheetViewer::orientationChanged, this,
@ -286,11 +283,6 @@ XsheetViewer::XsheetViewer(QWidget *parent, Qt::WFlags flags)
connect(m_toolbar, SIGNAL(updateVisibility()), this,
SLOT(positionSections()));
connect(m_frameZoomSlider, SIGNAL(sliderReleased()), this,
SLOT(onFrameZoomSliderReleased()));
connect(m_frameZoomSlider, SIGNAL(valueChanged(int)), this,
SLOT(onFrameZoomSliderValueChanged(int)));
emit orientationChanged(orientation());
}
@ -412,18 +404,12 @@ void XsheetViewer::positionSections() {
bodyLayer.adjusted(0, -XsheetGUI::SCROLLBAR_WIDTH)));
m_rowScrollArea->setGeometry(o->frameLayerRect(
bodyFrame.adjusted(0, -XsheetGUI::SCROLLBAR_WIDTH), headerLayer));
if (o->isVerticalTimeline())
m_frameZoomSlider->hide();
else {
if (m_frameZoomSlider->isHidden()) m_frameZoomSlider->show();
QRect sliderRect =
QRect(0, 0, XsheetGUI::ZOOM_SLIDER_WIDTH,
XsheetGUI::SCROLLBAR_WIDTH - 2)
.translated(m_columnScrollArea->rect().right() -
XsheetGUI::ZOOM_SLIDER_WIDTH - 17,
height() - XsheetGUI::SCROLLBAR_WIDTH + 1);
m_frameZoomSlider->setGeometry(sliderRect);
}
m_layerFooterPanel->setGeometry(0,
m_columnScrollArea->geometry().bottom() + 1,
m_columnScrollArea->width(), 14);
m_layerFooterPanel->showOrHide(o);
}
void XsheetViewer::disconnectScrollBars() {
@ -1079,23 +1065,6 @@ void XsheetViewer::hideEvent(QHideEvent *) {
//-----------------------------------------------------------------------------
void XsheetViewer::paintEvent(QPaintEvent *) {
QPainter p(this);
static QPixmap zoomIn = svgToPixmap(":Resources/zoom_in.svg");
const QRect zoomInRect = QRect(m_frameZoomSlider->geometry().right() + 2,
m_frameZoomSlider->geometry().top(), 14, 14);
static QPixmap zoomOut = svgToPixmap(":Resources/zoom_out.svg");
const QRect zoomOutRect = QRect(m_frameZoomSlider->geometry().left() - 16,
m_frameZoomSlider->geometry().top(), 14, 14);
p.setRenderHint(QPainter::SmoothPixmapTransform, true);
p.drawPixmap(zoomInRect, zoomIn);
p.drawPixmap(zoomOutRect, zoomOut);
}
//-----------------------------------------------------------------------------
void XsheetViewer::resizeEvent(QResizeEvent *event) {
positionSections();
@ -1120,12 +1089,12 @@ void XsheetViewer::wheelEvent(QWheelEvent *event) {
int newFactor =
getFrameZoomFactor() + ((event->angleDelta().y() > 0 ? 1 : -1) * 10);
if (newFactor > m_frameZoomSlider->maximum())
newFactor = m_frameZoomSlider->maximum();
else if (newFactor < m_frameZoomSlider->minimum())
newFactor = m_frameZoomSlider->minimum();
if (newFactor > XsheetGUI::ZOOM_FACTOR_MAX)
newFactor = XsheetGUI::ZOOM_FACTOR_MAX;
else if (newFactor < XsheetGUI::ZOOM_FACTOR_MIN)
newFactor = XsheetGUI::ZOOM_FACTOR_MIN;
zoomOnFrame(targetFrame, newFactor);
event->accept();
return;
}
@ -1246,6 +1215,7 @@ void XsheetViewer::keyPressEvent(QKeyEvent *event) {
// display the upper-directional smart tab only when the ctrl key is pressed
m_cellArea->onControlPressed(true);
m_columnArea->onControlPressed(true);
m_layerFooterPanel->onControlPressed(true);
break;
default: {
@ -1290,6 +1260,7 @@ void XsheetViewer::keyReleaseEvent(QKeyEvent *event) {
if (event->key() == Qt::Key_Control) {
m_cellArea->onControlPressed(false);
m_columnArea->onControlPressed(false);
m_layerFooterPanel->onControlPressed(false);
}
}
@ -1725,7 +1696,8 @@ void XsheetViewer::load(QSettings &settings) {
QVariant name = settings.value("orientation");
if (zoomFactor.canConvert(QVariant::Int)) {
m_frameZoomSlider->setValue(zoomFactor.toInt());
m_frameZoomFactor = zoomFactor.toInt();
m_layerFooterPanel->setZoomSliderValue(m_frameZoomFactor);
}
if (name.canConvert(QVariant::String)) {
@ -1766,9 +1738,7 @@ void XsheetViewer::zoomOnFrame(int frame, int factor) {
QPoint xyOrig = positionToXY(CellPosition(frame, 0));
m_frameZoomFactor = factor;
m_frameZoomSlider->blockSignals(true);
m_frameZoomSlider->setValue(factor);
m_frameZoomSlider->blockSignals(false);
m_layerFooterPanel->setZoomSliderValue(m_frameZoomFactor);
QPoint xyNew = positionToXY(CellPosition(frame, 0));
@ -1776,14 +1746,6 @@ void XsheetViewer::zoomOnFrame(int frame, int factor) {
scroll(QPoint(viewShift, 0));
onFrameZoomSliderReleased();
}
void XsheetViewer::onFrameZoomSliderValueChanged(int val) {
zoomOnFrame(getCurrentRow(), val);
}
void XsheetViewer::onFrameZoomSliderReleased() {
TApp::instance()->getCurrentXsheet()->notifyXsheetChanged();
m_rowArea->update();
}

View file

@ -11,6 +11,7 @@
#include "xshrowviewer.h"
#include "xshnoteviewer.h"
#include "xshtoolbar.h"
#include "layerfooterpanel.h"
#include "cellkeyframeselection.h"
#include "saveloadqsettings.h"
#include "toonzqt/spreadsheetviewer.h"
@ -497,6 +498,7 @@ class XsheetViewer final : public QFrame, public SaveLoadQSettings {
XsheetGUI::CellArea *m_cellArea;
XsheetGUI::NoteArea *m_noteArea;
XsheetGUI::XSheetToolbar *m_toolbar;
LayerFooterPanel *m_layerFooterPanel;
Spreadsheet::FrameScroller m_frameScroller;
@ -526,7 +528,6 @@ class XsheetViewer final : public QFrame, public SaveLoadQSettings {
QString m_xsheetLayout;
int m_frameZoomFactor;
QSlider *m_frameZoomSlider;
public:
enum FrameDisplayStyle { Frame = 0, SecAndFrame, SixSecSheet, ThreeSecSheet };
@ -1095,8 +1096,6 @@ protected:
void scrollToRow(int row);
void scrollToVerticalRange(int y0, int y1);
void paintEvent(QPaintEvent *) override;
void showEvent(QShowEvent *) override;
void hideEvent(QHideEvent *) override;
void resizeEvent(QResizeEvent *event) override;
@ -1147,9 +1146,6 @@ public slots:
int getFrameZoomAdjustment();
void zoomOnFrame(int frame, int factor);
void onFrameZoomSliderValueChanged(int val);
void onFrameZoomSliderReleased();
};
#endif // XSHEETVIEWER_H

View file

@ -676,6 +676,12 @@ TopToBottomOrientation::TopToBottomOrientation() {
QRect(soundTopLeft, QSize(TRACKLEN, 3)));
}
// 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
//
@ -992,6 +998,25 @@ LeftToRightOrientation::LeftToRightOrientation() {
addRect(PredefinedRect::VOLUME_TRACK,
QRect(soundTopLeft, QSize(TRACKLEN, 3)));
// Layer footer panel
QRect layerFooterPanel(QRect(0, 0, LAYER_HEADER_WIDTH + 2, 16));
addRect(PredefinedRect::LAYER_FOOTER_PANEL, layerFooterPanel);
QRect zoomSlider, zoomIn, zoomOut;
zoomSlider = QRect(layerFooterPanel.width() - 100, 0, 81, 16);
addRect(PredefinedRect::ZOOM_SLIDER_AREA, zoomSlider);
addRect(PredefinedRect::ZOOM_SLIDER, zoomSlider.adjusted(1, 0, 0, 0));
zoomIn = QRect(zoomSlider.right() + 1, 0, 16, 16);
addRect(PredefinedRect::ZOOM_IN_AREA, zoomIn);
addRect(PredefinedRect::ZOOM_IN, zoomIn.adjusted(1, 1, 0, 0));
zoomOut = QRect(zoomSlider.left() - 16, 0, 16, 16);
addRect(PredefinedRect::ZOOM_OUT_AREA, zoomOut);
addRect(PredefinedRect::ZOOM_OUT, zoomOut.adjusted(1, 1, 0, 0));
// Flags
addFlag(PredefinedFlag::DRAG_LAYER_BORDER, false);
addFlag(PredefinedFlag::DRAG_LAYER_VISIBLE, true);
addFlag(PredefinedFlag::LAYER_NAME_BORDER, false);