Blob Blame Raw
#include "historypane.h"

#include "tundo.h"
#include "historytypes.h"

#include <QApplication>
#include <QPainter>
#include <QScrollBar>
#include <QFrame>
#include <QPaintEvent>
#include <QVBoxLayout>

#include <QMutex>

const int HISTORY_ITEM_HEIGHT = 20;

namespace
{

const struct {
	int historyType;
	const char *pixmapFilename;
} historyTypeInfo[] = {
	{HistoryType::Unidentified, "history_normal"},
	{HistoryType::BrushTool, "history_brush"},
	{HistoryType::EraserTool, "history_eraser"},
	{HistoryType::FillTool, "history_fill"},
	{HistoryType::PaintBrushTool, "history_paintbrush"},
	{HistoryType::AutocloseTool, "history_autoclose"},
	{HistoryType::GeometricTool, "history_geometric"},
	{HistoryType::ControlPointEditorTool, "history_controlpointeditor"},
	{HistoryType::EditTool_Move, "history_move"},
	{HistoryType::FingerTool, "history_finger"},
	//{HistoryType::PickTool,			"history_pick"},
	{HistoryType::Palette, "history_palette"},
	{HistoryType::Fx, "history_fx"},
	{HistoryType::Schematic, "history_schematic"},
	{HistoryType::Xsheet, "history_xsheet"},
	{HistoryType::FilmStrip, "history_filmstrip"},

	{0, 0}};
};

class HistoryPixmapManager
{ // singleton

	std::map<int, QPixmap> m_pms;

	HistoryPixmapManager() {}
public:
	static HistoryPixmapManager *instance()
	{
		static HistoryPixmapManager _instance;
		return &_instance;
	}

	const QPixmap &getHistoryPm(int type)
	{
		std::map<int, QPixmap>::iterator it;
		it = m_pms.find(type);
		if (it != m_pms.end())
			return it->second;

		int i;
		for (i = 0; historyTypeInfo[i].pixmapFilename; i++)
			if (type == historyTypeInfo[i].historyType) {
				QString path = QString(":Resources/") + historyTypeInfo[i].pixmapFilename + ".png";
				it = m_pms.insert(std::make_pair(type, QPixmap(path))).first;
				return it->second;
			}

		static const QPixmap standardCursorPixmap("history_unidentified.png");
		it = m_pms.insert(std::make_pair(type, standardCursorPixmap)).first;
		return it->second;
	}
};
//-----------------------------------------------------------------------------
#if QT_VERSION >= 0x050500
HistoryField::HistoryField(QScrollArea *parent, Qt::WindowFlags flags)
#else
HistoryField::HistoryField(QScrollArea *parent, Qt::WFlags flags)
#endif
	: QFrame(parent, flags), m_scrollArea(parent)
{
	setObjectName("filmStripFrames");
	setFrameStyle(QFrame::StyledPanel);

	setFocusPolicy(Qt::StrongFocus); /*-- KeyboadでもTabキーでもFocusされる --*/

	setFixedHeight(parentWidget()->height());
	setMinimumWidth(tmax(parentWidget()->width(), 600));
}
//-----------------------------------------------------------------------------

void HistoryField::updateContentHeight(int minimumHeight)
{
	if (minimumHeight < 0)
		minimumHeight = visibleRegion().boundingRect().bottom();
	int contentHeight = TUndoManager::manager()->getHistoryCount() * HISTORY_ITEM_HEIGHT;
	if (contentHeight < minimumHeight)
		contentHeight = minimumHeight;
	int parentHeight = parentWidget()->height();
	if (contentHeight < parentHeight)
		contentHeight = parentHeight;
	if (contentHeight != height())
		setFixedHeight(contentHeight);
}

//-----------------------------------------------------------------------------

void HistoryField::paintEvent(QPaintEvent *evt)
{
	QPainter p(this);

	QRect clipRect = evt->rect();

	int i0 = y2index(clipRect.top());
	int i1 = y2index(clipRect.bottom());

	int currentHistoryIndex = TUndoManager::manager()->getCurrentHistoryIndex();
	int currentHistoryCount = TUndoManager::manager()->getHistoryCount();

	QRect undoChipRect(0, 0, width(), HISTORY_ITEM_HEIGHT);
	QRect undoIconRect(7, 2, 17, 17);

	for (int i = i0; i <= i1; i++) {

		if (0 <= i && i <= currentHistoryCount) {
			QRect tmpRect = undoChipRect.translated(0, HISTORY_ITEM_HEIGHT * (i - 1));

			bool isCurrent = (i == currentHistoryIndex);
			bool isFuture = (i > currentHistoryIndex);

			p.setPen(QColor(64, 64, 64));
			p.setBrush((isFuture) ? QColor(150, 150, 150) : QColor(192, 192, 192));
			if (isCurrent)
				p.setBrush(QColor(0, 0, 128));
			p.drawRect(tmpRect);

			//draw text
			QFont fon = p.font();
			fon.setItalic(isFuture);
			p.setFont(fon);

			p.setPen((isFuture) ? QColor(64, 64, 64) : Qt::black);
			if (isCurrent)
				p.setPen(Qt::white);

			tmpRect.adjust(30, 0, 0, 0);

			TUndo *tmpUndo = TUndoManager::manager()->getUndoItem(i);
			p.drawText(tmpRect, Qt::AlignLeft | Qt::AlignVCenter, tmpUndo->getHistoryString());

			QRect tmpIconRect = undoIconRect.translated(0, 20 * (i - 1));
			p.drawPixmap(tmpIconRect, HistoryPixmapManager::instance()->getHistoryPm(tmpUndo->getHistoryType()));
		}
	}
}

//-----------------------------------------------------------------------------

int HistoryField::y2index(int y) const
{
	return y / HISTORY_ITEM_HEIGHT + 1;
}

//-----------------------------------------------------------------------------

int HistoryField::index2y(int index) const
{
	return (index - 1) * HISTORY_ITEM_HEIGHT;
}

//-----------------------------------------------------------------------------

void HistoryField::mousePressEvent(QMouseEvent *event)
{

	int index = y2index(event->pos().y());
	int historyCount = TUndoManager::manager()->getHistoryCount();

	if (index > historyCount || index <= 0)
		return;

	int currentIndex = TUndoManager::manager()->getCurrentHistoryIndex();

	if (index == currentIndex)
		return;

	if (index < currentIndex) //undo
	{
		for (int i = 0; i < (currentIndex - index); i++)
			TUndoManager::manager()->undo();
	} else //redo
	{
		for (int i = 0; i < (index - currentIndex); i++)
			TUndoManager::manager()->redo();
	}
}

//-----------------------------------------------------------------------------

void HistoryField::exposeCurrent()
{
	int currentIndex = TUndoManager::manager()->getCurrentHistoryIndex();

	m_scrollArea->ensureVisible(0, index2y(currentIndex) + 10, 50, 10);
}

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
#if QT_VERSION >= 0x050500
HistoryPane::HistoryPane(QWidget *parent, Qt::WindowFlags flags)
#else
HistoryPane::HistoryPane(QWidget *parent, Qt::WFlags flags)
#endif
	: QWidget(parent)
{
	m_frameArea = new QScrollArea(this);
	m_field = new HistoryField(m_frameArea);

	m_frameArea->setObjectName("filmScrollArea");
	m_frameArea->setFrameStyle(QFrame::StyledPanel);
	m_frameArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
	m_frameArea->verticalScrollBar()->setObjectName("LevelStripScrollBar");

	m_frameArea->setWidget(m_field);

	// layout
	QVBoxLayout *mainLayout = new QVBoxLayout();
	mainLayout->setMargin(0);
	{
		mainLayout->addWidget(m_frameArea, 1);
	}
	setLayout(mainLayout);

	setFocusProxy(m_field);
}
//-----------------------------------------------------------------------------

void HistoryPane::onHistoryChanged()
{
	m_field->updateContentHeight();
	m_field->exposeCurrent();
	update();
}

//-----------------------------------------------------------------------------

void HistoryPane::resizeEvent(QResizeEvent *e)
{
	m_field->updateContentHeight();
	m_field->setFixedWidth(tmax(width(), 600));
}

//-----------------------------------------------------------------------------

void HistoryPane::showEvent(QShowEvent *)
{
	connect(TUndoManager::manager(), SIGNAL(historyChanged()), this, SLOT(onHistoryChanged()));
	onHistoryChanged();
}

//-----------------------------------------------------------------------------

void HistoryPane::hideEvent(QHideEvent *)
{
	disconnect(TUndoManager::manager(), SIGNAL(historyChanged()), this, SLOT(onHistoryChanged()));
}