1 #include "historypane.h"
2 
3 #include "tundo.h"
4 #include "historytypes.h"
5 
6 #include <QApplication>
7 #include <QPainter>
8 #include <QScrollBar>
9 #include <QFrame>
10 #include <QPaintEvent>
11 #include <QVBoxLayout>
12 
13 #include <QMutex>
14 
15 const int HISTORY_ITEM_HEIGHT = 20;
16 
17 namespace {
18 
19 const struct {
20   int historyType;
21   const char *pixmapFilename;
22 } historyTypeInfo[] = {
23     {HistoryType::Unidentified, "history_normal"},
24     {HistoryType::BrushTool, "history_brush"},
25     {HistoryType::EraserTool, "history_eraser"},
26     {HistoryType::FillTool, "history_fill"},
27     {HistoryType::PaintBrushTool, "history_paintbrush"},
28     {HistoryType::AutocloseTool, "history_autoclose"},
29     {HistoryType::GeometricTool, "history_geometric"},
30     {HistoryType::ControlPointEditorTool, "history_controlpointeditor"},
31     {HistoryType::EditTool_Move, "history_move"},
32     {HistoryType::FingerTool, "history_finger"},
33     //{HistoryType::PickTool,			"history_pick"},
34     {HistoryType::Palette, "history_palette"},
35     {HistoryType::Fx, "history_fx"},
36     {HistoryType::Schematic, "history_schematic"},
37     {HistoryType::Xsheet, "history_xsheet"},
38     {HistoryType::FilmStrip, "history_filmstrip"},
39 
40     {0, 0}};
41 };
42 
43 class HistoryPixmapManager {  // singleton
44 
45   std::map<int, QPixmap> m_pms;
46 
HistoryPixmapManager()47   HistoryPixmapManager() {}
48 
49 public:
instance()50   static HistoryPixmapManager *instance() {
51     static HistoryPixmapManager _instance;
52     return &_instance;
53   }
54 
getHistoryPm(int type)55   const QPixmap &getHistoryPm(int type) {
56     std::map<int, QPixmap>::iterator it;
57     it = m_pms.find(type);
58     if (it != m_pms.end()) return it->second;
59 
60     int i;
61     for (i = 0; historyTypeInfo[i].pixmapFilename; i++)
62       if (type == historyTypeInfo[i].historyType) {
63         QString path =
64             QString(":Resources/") + historyTypeInfo[i].pixmapFilename + ".png";
65         it = m_pms.insert(std::make_pair(type, QPixmap(path))).first;
66         return it->second;
67       }
68 
69     static const QPixmap standardCursorPixmap("history_unidentified.png");
70     it = m_pms.insert(std::make_pair(type, standardCursorPixmap)).first;
71     return it->second;
72   }
73 };
74 //-----------------------------------------------------------------------------
75 #if QT_VERSION >= 0x050500
HistoryField(QScrollArea * parent,Qt::WindowFlags flags)76 HistoryField::HistoryField(QScrollArea *parent, Qt::WindowFlags flags)
77 #else
78 HistoryField::HistoryField(QScrollArea *parent, Qt::WFlags flags)
79 #endif
80     : QFrame(parent, flags), m_scrollArea(parent) {
81   setObjectName("filmStripFrames");
82   setFrameStyle(QFrame::StyledPanel);
83 
84   setFocusPolicy(Qt::StrongFocus); /*-- KeyboadでもTabキーでもFocusされる --*/
85 
86   setFixedHeight(parentWidget()->height());
87   setMinimumWidth(std::max(parentWidget()->width(), 600));
88 }
89 //-----------------------------------------------------------------------------
90 
updateContentHeight(int minimumHeight)91 void HistoryField::updateContentHeight(int minimumHeight) {
92   if (minimumHeight < 0)
93     minimumHeight = visibleRegion().boundingRect().bottom();
94   int contentHeight =
95       TUndoManager::manager()->getHistoryCount() * HISTORY_ITEM_HEIGHT;
96   if (contentHeight < minimumHeight) contentHeight = minimumHeight;
97   int parentHeight                                 = parentWidget()->height();
98   if (contentHeight < parentHeight) contentHeight  = parentHeight;
99   if (contentHeight != height()) setFixedHeight(contentHeight);
100 }
101 
102 //-----------------------------------------------------------------------------
103 
paintEvent(QPaintEvent * evt)104 void HistoryField::paintEvent(QPaintEvent *evt) {
105   QPainter p(this);
106 
107   QRect clipRect = evt->rect();
108 
109   int i0 = y2index(clipRect.top());
110   int i1 = y2index(clipRect.bottom());
111 
112   int currentHistoryIndex = TUndoManager::manager()->getCurrentHistoryIndex();
113   int currentHistoryCount = TUndoManager::manager()->getHistoryCount();
114 
115   QRect undoChipRect(0, 0, width(), HISTORY_ITEM_HEIGHT);
116   QRect undoIconRect(7, 2, 17, 17);
117 
118   for (int i = i0; i <= i1; i++) {
119     if (0 <= i && i <= currentHistoryCount) {
120       QRect tmpRect = undoChipRect.translated(0, HISTORY_ITEM_HEIGHT * (i - 1));
121 
122       bool isCurrent = (i == currentHistoryIndex);
123       bool isFuture  = (i > currentHistoryIndex);
124 
125       p.setPen(QColor(64, 64, 64));
126       p.setBrush((isFuture) ? QColor(150, 150, 150) : QColor(192, 192, 192));
127       if (isCurrent) p.setBrush(QColor(0, 0, 128));
128       p.drawRect(tmpRect);
129 
130       // draw text
131       QFont fon = p.font();
132       fon.setItalic(isFuture);
133       p.setFont(fon);
134 
135       p.setPen((isFuture) ? QColor(64, 64, 64) : Qt::black);
136       if (isCurrent) p.setPen(Qt::white);
137 
138       tmpRect.adjust(30, 0, 0, 0);
139 
140       TUndo *tmpUndo = TUndoManager::manager()->getUndoItem(i);
141       p.drawText(tmpRect, Qt::AlignLeft | Qt::AlignVCenter,
142                  tmpUndo->getHistoryString());
143 
144       QRect tmpIconRect = undoIconRect.translated(0, 20 * (i - 1));
145       p.drawPixmap(tmpIconRect, HistoryPixmapManager::instance()->getHistoryPm(
146                                     tmpUndo->getHistoryType()));
147     }
148   }
149 }
150 
151 //-----------------------------------------------------------------------------
152 
y2index(int y) const153 int HistoryField::y2index(int y) const { return y / HISTORY_ITEM_HEIGHT + 1; }
154 
155 //-----------------------------------------------------------------------------
156 
index2y(int index) const157 int HistoryField::index2y(int index) const {
158   return (index - 1) * HISTORY_ITEM_HEIGHT;
159 }
160 
161 //-----------------------------------------------------------------------------
162 
mousePressEvent(QMouseEvent * event)163 void HistoryField::mousePressEvent(QMouseEvent *event) {
164   int index        = y2index(event->pos().y());
165   int historyCount = TUndoManager::manager()->getHistoryCount();
166 
167   if (index > historyCount || index <= 0) return;
168 
169   int currentIndex = TUndoManager::manager()->getCurrentHistoryIndex();
170 
171   if (index == currentIndex) return;
172 
173   if (index < currentIndex)  // undo
174   {
175     for (int i = 0; i < (currentIndex - index); i++)
176       TUndoManager::manager()->undo();
177   } else  // redo
178   {
179     for (int i = 0; i < (index - currentIndex); i++)
180       TUndoManager::manager()->redo();
181   }
182 }
183 
184 //-----------------------------------------------------------------------------
185 
exposeCurrent()186 void HistoryField::exposeCurrent() {
187   int currentIndex = TUndoManager::manager()->getCurrentHistoryIndex();
188 
189   m_scrollArea->ensureVisible(0, index2y(currentIndex) + 10, 50, 10);
190 }
191 
192 //-----------------------------------------------------------------------------
193 //-----------------------------------------------------------------------------
194 #if QT_VERSION >= 0x050500
HistoryPane(QWidget * parent,Qt::WindowFlags flags)195 HistoryPane::HistoryPane(QWidget *parent, Qt::WindowFlags flags)
196 #else
197 HistoryPane::HistoryPane(QWidget *parent, Qt::WFlags flags)
198 #endif
199     : QWidget(parent) {
200   m_frameArea = new QScrollArea(this);
201   m_field     = new HistoryField(m_frameArea);
202 
203   m_frameArea->setObjectName("filmScrollArea");
204   m_frameArea->setFrameStyle(QFrame::StyledPanel);
205   m_frameArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
206   m_frameArea->verticalScrollBar()->setObjectName("LevelStripScrollBar");
207 
208   m_frameArea->setWidget(m_field);
209 
210   // layout
211   QVBoxLayout *mainLayout = new QVBoxLayout();
212   mainLayout->setMargin(0);
213   { mainLayout->addWidget(m_frameArea, 1); }
214   setLayout(mainLayout);
215 
216   setFocusProxy(m_field);
217 }
218 //-----------------------------------------------------------------------------
219 
onHistoryChanged()220 void HistoryPane::onHistoryChanged() {
221   m_field->updateContentHeight();
222   m_field->exposeCurrent();
223   update();
224 }
225 
226 //-----------------------------------------------------------------------------
227 
resizeEvent(QResizeEvent * e)228 void HistoryPane::resizeEvent(QResizeEvent *e) {
229   m_field->updateContentHeight();
230   m_field->setFixedWidth(std::max(width(), 600));
231 }
232 
233 //-----------------------------------------------------------------------------
234 
showEvent(QShowEvent *)235 void HistoryPane::showEvent(QShowEvent *) {
236   connect(TUndoManager::manager(), SIGNAL(historyChanged()), this,
237           SLOT(onHistoryChanged()));
238   onHistoryChanged();
239 }
240 
241 //-----------------------------------------------------------------------------
242 
hideEvent(QHideEvent *)243 void HistoryPane::hideEvent(QHideEvent *) {
244   disconnect(TUndoManager::manager(), SIGNAL(historyChanged()), this,
245              SLOT(onHistoryChanged()));
246 }