1/*******************************************************************
2 *
3 * Copyright 2006 Dmitry Suzdalev <dimsuz@gmail.com>
4 * Copyright 2007 Carsten Niehaus <cniehaus@kde.org>
5 * Copyright 2010 Brian Croom <brian.s.croom@gmail.com>
6 *
7 * This file is part of the KDE project "KAtomic"
8 *
9 * KAtomic is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2, or (at your option)
12 * any later version.
13 *
14 * KAtomic is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with KAtomic; see the file COPYING. If not, write to
21 * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
22 * Boston, MA 02110-1301, USA.
23 *
24 ********************************************************************/
25
26#include "fielditem.h"
27
28#include <QPainter>
29#include <QTimeLine>
30
31#include <kdebug.h>
32#include <klocale.h>
33#include "molecule.h"
34#include "playfield.h"
35
36FieldItem::FieldItem( KGameRenderer* renderer, const QString& spriteKey, QGraphicsScene* scene )
37 : KGameRenderedItem( renderer, spriteKey ), m_fieldX(0), m_fieldY(0)
38{
39 if( scene )
40 scene->addItem( this );
41 setShapeMode( BoundingRectShape );
42}
43
44
45static const char* arrow_spriteKeys[] = {"arrow_Up", "arrow_Down", "arrow_Left", "arrow_Right"};
46
47ArrowFieldItem::ArrowFieldItem( KGameRenderer* renderer, PlayField::Direction dir, QGraphicsScene* scene )
48 : FieldItem( renderer, arrow_spriteKeys[dir], scene )
49{
50 setOpacity(0.0); //start invisible
51 m_timeLine = new QTimeLine(200);
52 m_timeLine->setFrameRange( 0, 30 );
53 connect(m_timeLine, SIGNAL(valueChanged(qreal)), SLOT(setOpacity(qreal)) );
54}
55
56ArrowFieldItem::~ArrowFieldItem()
57{
58 delete m_timeLine;
59}
60
61void ArrowFieldItem::setOpacity( qreal opacity )
62{
63 //NOTE: This method is only there because QGI::setOpacity is not a slot.
64 QGraphicsItem::setOpacity(opacity);
65}
66
67QVariant ArrowFieldItem::itemChange( GraphicsItemChange change, const QVariant& value )
68{
69 if(change == ItemVisibleChange)
70 {
71 if(value.toBool())
72 {
73 m_timeLine->stop();
74 m_timeLine->setCurrentTime(0);
75 m_timeLine->start();
76 }
77 }
78 return value;
79}
80
81
82
83AtomFieldItem::AtomFieldItem( KGameRenderer* renderer, const atom& at, QGraphicsScene* scene )
84 : FieldItem(renderer, s_names.value(at.obj), scene), m_atomNum(-1)
85{
86 if(s_names.empty())
87 {
88 fillNameHashes();
89 setSpriteKey(s_names.value(at.obj)); // It wasn't yet filled in when the constructor was called
90 }
91
92 // create the bonds as child items
93 for (int c = 0; c < MAX_CONNS_PER_ATOM; c++)
94 {
95 char conn = at.conn[c];
96 if (!conn)
97 break;
98
99 KGameRenderedItem* bond = new KGameRenderedItem(renderer, s_bondNames.value(conn), this);
100 bond->setFlag(QGraphicsItem::ItemStacksBehindParent);
101 }
102}
103
104void AtomFieldItem::setRenderSize(const QSize& renderSize)
105{
106 KGameRenderedItem::setRenderSize(renderSize);
107
108 QList<QGraphicsItem*> bonds = childItems();
109 foreach(QGraphicsItem* item, bonds)
110 {
111 dynamic_cast<KGameRenderedItem*>(item)->setRenderSize(renderSize);
112 }
113}
114
115QHash<char, QString> AtomFieldItem::s_names;
116QHash<char, QString> AtomFieldItem::s_bondNames;
117
118void AtomFieldItem::fillNameHashes()
119{
120 s_names['1'] = "atom_H";
121 s_names['2'] = "atom_C";
122 s_names['3'] = "atom_O";
123 s_names['4'] = "atom_N";
124 s_names['5'] = "atom_S";
125 s_names['6'] = "atom_F";
126 s_names['7'] = "atom_Cl";
127 s_names['8'] = "atom_Br";
128 s_names['9'] = "atom_P";
129 s_names['0'] = "atom_J";
130 s_names['o'] = "atom_Crystal";
131 s_names['A'] = "connector_Hor";
132 s_names['B'] = "connector_Slash";
133 s_names['C'] = "connector_Ver";
134 s_names['D'] = "connector_Backslash";
135 s_names['#'] = "wall";
136 s_names['<'] = "arrow_Left";
137 s_names['>'] = "arrow_Right";
138 s_names['^'] = "arrow_Up";
139 s_names['_'] = "arrow_Down";
140 s_names['E'] = "atom_flask0";
141 s_names['F'] = "atom_flask1";
142 s_names['G'] = "atom_flask2";
143 s_names['H'] = "atom_flask3";
144 s_names['I'] = "atom_flask4";
145 s_names['J'] = "atom_flask5";
146 s_names['K'] = "atom_flask6";
147 s_names['L'] = "atom_flask7";
148
149 s_bondNames['a'] = "bond_I_Top";
150 s_bondNames['b'] = "bond_I_TopRight";
151 s_bondNames['c'] = "bond_I_Right";
152 s_bondNames['d'] = "bond_I_BotRight";
153 s_bondNames['e'] = "bond_I_Bottom";
154 s_bondNames['f'] = "bond_I_BotLeft";
155 s_bondNames['g'] = "bond_I_Left";
156 s_bondNames['h'] = "bond_I_TopLeft";
157
158 s_bondNames['A'] = "bond_II_Top";
159 s_bondNames['B'] = "bond_II_Right";
160 s_bondNames['C'] = "bond_II_Bottom";
161 s_bondNames['D'] = "bond_II_Left";
162
163 s_bondNames['E'] = "bond_III_Top";
164 s_bondNames['F'] = "bond_III_Right";
165 s_bondNames['G'] = "bond_III_Bottom";
166 s_bondNames['H'] = "bond_III_Left";
167}
168
169QPixmap AtomFieldItem::renderAtom( KGameRenderer* renderer, const atom& at, int size )
170{
171 if (size == 0) return QPixmap();
172
173 QPixmap atomPix = renderer->spritePixmap(s_names.value(at.obj), QSize(size, size));
174
175 QPainter p;
176 QPixmap bonds(size,size);
177 bonds.fill(Qt::transparent);
178 for (int c = 0; c < MAX_CONNS_PER_ATOM; c++)
179 {
180 char conn = at.conn[c];
181 if (!conn)
182 break;
183
184 QPixmap pix = renderer->spritePixmap(s_bondNames.value(conn), QSize(size, size));
185
186 p.begin(&bonds);
187 p.drawPixmap(0,0, pix);
188 p.end();
189 }
190
191 p.begin(&bonds);
192 p.drawPixmap(0,0, atomPix);
193 p.end();
194 return bonds;
195}
196
197// ----------------- MoleculePreviewItem ----------------------------
198
199MoleculePreviewItem::MoleculePreviewItem( PlayField* scene )
200 : QGraphicsItem( 0, scene ), m_renderer(scene->renderer()), m_width(0),
201 m_atomSize(20), m_maxAtomSize(30), m_mol( 0 )
202{
203}
204
205MoleculePreviewItem::~MoleculePreviewItem()
206{
207}
208
209void MoleculePreviewItem::setMolecule( const Molecule* mol )
210{
211 m_mol = mol;
212 setWidth( m_width ); // trigger atom size update
213}
214
215void MoleculePreviewItem::setMaxAtomSize(int maxSize)
216{
217 m_maxAtomSize = maxSize;
218 setWidth( m_width ); // trigger atom size update
219}
220
221void MoleculePreviewItem::setWidth(int width)
222{
223 m_width = width;
224
225 if(!m_mol)
226 return;
227 int w = m_mol->width();
228 int h = m_mol->height();
229 int atomSize = width / qMax(w,h);
230 m_atomSize = qMin(atomSize, m_maxAtomSize);
231 update();
232}
233
234void MoleculePreviewItem::paint( QPainter * painter, const QStyleOptionGraphicsItem*, QWidget *)
235{
236 if ( m_width == 0 || m_mol == 0 )
237 return;
238
239 painter->save();
240 painter->setBrush(Qt::gray);
241 painter->setOpacity(0.5);
242 painter->drawRect(boundingRect());
243 painter->setOpacity(1.0);
244
245 int originX = m_width/2 - m_atomSize*m_mol->width()/2;
246 int originY = m_width/2 - m_atomSize*m_mol->height()/2;
247
248 // Paint the playing field
249 for (int i = 0; i < MOLECULE_SIZE; i++)
250 for (int j = 0; j < MOLECULE_SIZE; j++)
251 {
252 int x = originX + i * m_atomSize;
253 int y = originY + j * m_atomSize;
254
255 if (m_mol->getAtom(i,j) == 0)
256 continue;
257
258 int atomIdx = m_mol->getAtom(i,j);
259 QPixmap aPix = AtomFieldItem::renderAtom(m_renderer, m_mol->getAtom(atomIdx), m_atomSize);
260 painter->drawPixmap(x, y, aPix);
261 }
262 painter->restore();
263}
264
265#include "fielditem.moc"
266