1 /* ColorCode, a free MasterMind clone with built in solver
2  * Copyright (C) 2009  Dirk Laebisch
3  * http://www.laebisch.com/
4  *
5  * ColorCode is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * ColorCode is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with ColorCode. If not, see <http://www.gnu.org/licenses/>.
17 */
18 
19 #include <QtWidgets>
20 
21 #include "colorpeg.h"
22 #include "pegrow.h"
23 #include "rowhint.h"
24 
25 using namespace std;
26 
PegRow(QObject *)27 PegRow::PegRow(QObject*)
28 {
29     setAcceptedMouseButtons(0);
30 
31     mIx = -1;
32     mPegCnt = 0;
33     mXOffs = 0;
34     mPend = QColor("#646568");
35     mPenl = QColor("#ecedef");
36     mGrad0 = QColor("#cccdcf");
37     mGrad1 = QColor("#fcfdff");
38 
39     mColorPegs = NULL;
40 
41     Reset(0, 0);
42 }
43 
~PegRow()44 PegRow::~PegRow()
45 {
46     for (int i = 0; i < mPegCnt; ++i)
47     {
48         delete mColorPegs[i];
49     }
50     delete [] mColorPegs;
51     mColorPegs = NULL;
52 }
53 
IsActive() const54 bool PegRow::IsActive() const
55 {
56     return mIsActive;
57 }
58 
Reset(const int pegcnt,const int gamemode)59 void PegRow::Reset(const int pegcnt, const int gamemode)
60 {
61     ClearRow();
62     mSolution.clear();
63     SetActive(false);
64     mSolved = false;
65     SetPegCnt(pegcnt);
66     SetGameMode(gamemode);
67 }
68 
ClearRow()69 void PegRow::ClearRow()
70 {
71     if (mColorPegs == NULL) { return; };
72 
73     for (int i = 0; i < mPegCnt; ++i)
74     {
75         if (mColorPegs[i] != NULL)
76         {
77             emit(RemovePegSignal(mColorPegs[i]));
78         }
79     }
80 }
81 
GetIx() const82 int PegRow::GetIx() const
83 {
84     return mIx;
85 }
86 
SetIx(const int ix)87 void PegRow::SetIx(const int ix)
88 {
89     mIx = ix;
90 }
91 
SetPegCnt(const int pegcnt)92 void PegRow::SetPegCnt(const int pegcnt)
93 {
94     ClearRow();
95     for (int i = 0; i < mPegCnt; ++i)
96     {
97         delete mColorPegs[i];
98     }
99     delete [] mColorPegs;
100     mColorPegs = NULL;
101 
102     mPegCnt = pegcnt;
103     mColorPegs = new ColorPeg* [mPegCnt];
104     for (int i = 0; i < mPegCnt; ++i)
105     {
106         mColorPegs[i] = NULL;
107     }
108     SetXOffs();
109 }
110 
SetGameMode(const int gamemode)111 void PegRow::SetGameMode(const int gamemode)
112 {
113     mGameMode = gamemode;
114 }
115 
SetXOffs()116 void PegRow::SetXOffs()
117 {
118     mXOffs = 100 - mPegCnt * 20;
119 }
120 
GetPegCnt() const121 int PegRow::GetPegCnt() const
122 {
123     if (mColorPegs == NULL) { return 0; };
124 
125     int cnt = 0;
126     int i = 0;
127     for (i = 0; i < mPegCnt; ++i)
128     {
129         if (mColorPegs[i] != NULL)
130         {
131             ++cnt;
132         }
133     }
134     return cnt;
135 }
136 
GetPegs()137 ColorPeg** PegRow::GetPegs()
138 {
139     return mColorPegs;
140 }
141 
SetActive(const bool b)142 void PegRow::SetActive(const bool b)
143 {
144     mIsActive = b;
145     update(boundingRect());
146 }
147 
SnapCP(ColorPeg * cp)148 bool PegRow::SnapCP(ColorPeg *cp)
149 {
150     if (mColorPegs == NULL)
151     {
152         return false;
153     }
154 
155     bool snapped = false;
156     if (mIsActive)
157     {
158         QPointF p = mapFromParent(cp->pos());
159 
160         p.rx() += 18;
161         p.ry() += 18;
162 
163         int ix = -1;
164         int i;
165 
166         if (p.y() >= 0 && p.y() <= 40)
167         {
168             for (i = 0; i < mPegCnt; ++i)
169             {
170                 if (p.x() >= mXOffs + i * 40 && p.x() < mXOffs + (i + 1) * 40)
171                 {
172                     if (mColorPegs[i] != NULL)
173                     {
174                         emit RemovePegSignal(mColorPegs[i]);
175                         mColorPegs[i] = NULL;
176                     }
177                     mColorPegs[i] = cp;
178                     cp->SetPegRow(this);
179                     ix = i;
180                     cp->setPos(mapToParent(mXOffs + i * 40 + 2, 2));
181                     break;
182                 }
183             }
184         }
185 
186         snapped = ix > -1;
187         CheckSolution();
188     }
189 
190     return snapped;
191 }
192 
ForceSnap(ColorPeg * cp,int posix)193 void PegRow::ForceSnap(ColorPeg* cp, int posix)
194 {
195     if (mColorPegs == NULL)
196     {
197         return;
198     }
199 
200     if (posix > mPegCnt - 1)
201     {
202         return;
203     }
204 
205     if (mIsActive)
206     {
207         if (mColorPegs[posix] != NULL)
208         {
209             emit RemovePegSignal(mColorPegs[posix]);
210             mColorPegs[posix] = NULL;
211         }
212         mColorPegs[posix] = cp;
213         cp->setSelected(false);
214         cp->SetPegRow(this);
215         cp->setPos(mapToParent(mXOffs + posix * 40 + 2, 2));
216 
217         CheckSolution();
218     }
219 }
220 
CloseRow()221 void PegRow::CloseRow()
222 {
223     mSolved = true;
224     if (mColorPegs == NULL)
225     {
226         ;
227     }
228     else
229     {
230         for (int i = 0; i < mPegCnt; ++i)
231         {
232             if (mColorPegs[i] != NULL)
233             {
234                 mColorPegs[i]->SetEnabled(false);
235             }
236         }
237     }
238     SetActive(false);
239 }
240 
OpenRow()241 void PegRow::OpenRow()
242 {
243     mSolved = false;
244     if (mColorPegs == NULL)
245     {
246         ;
247     }
248     else
249     {
250         for (int i = 0; i < mPegCnt; ++i)
251         {
252             if (mColorPegs[i] != NULL)
253             {
254                 mColorPegs[i]->SetEnabled(true);
255             }
256         }
257     }
258     SetActive(true);
259 }
260 
CheckSolution()261 void PegRow::CheckSolution()
262 {
263     mSolution.clear();
264     if (mColorPegs == NULL)
265     {
266         ;
267     }
268     else
269     {
270         for (int i = 0; i < mPegCnt; ++i)
271         {
272             if (mColorPegs[i] != NULL)
273             {
274                 mSolution.push_back(mColorPegs[i]->GetPegType()->ix);
275             }
276         }
277     }
278     emit RowSolutionSignal(mIx);
279 }
280 
GetSolution() const281 std::vector<int> PegRow::GetSolution() const
282 {
283     return mSolution;
284 }
285 
RemovePeg(ColorPeg * cp)286 void PegRow::RemovePeg(ColorPeg *cp)
287 {
288     if (mColorPegs == NULL)
289     {
290         return;
291     }
292 
293     for (int i = 0; i < mPegCnt; ++i)
294     {
295         if (mColorPegs[i] == cp)
296         {
297             mColorPegs[i] = NULL;
298             if (mIsActive)
299             {
300                 CheckSolution();
301             }
302         }
303     }
304 }
305 
shape() const306 QPainterPath PegRow::shape() const
307 {
308     QPainterPath path;
309     path.addRect(boundingRect());
310     return path;
311 }
312 
boundingRect() const313 QRectF PegRow::boundingRect() const
314 {
315     const int Margin = 1;
316     return outlineRect().adjusted(-Margin, -Margin, +Margin, +Margin);
317 }
318 
outlineRect() const319 QRectF PegRow::outlineRect() const
320 {
321     return QRectF(0.0, 0.0, 200.0, 40.0);
322 }
323 
paint(QPainter * painter,const QStyleOptionGraphicsItem *,QWidget *)324 void PegRow::paint(QPainter* painter, const QStyleOptionGraphicsItem* , QWidget* )
325 {
326     if (mPegCnt == 0)
327     {
328         return;
329     }
330 
331     painter->setRenderHint(QPainter::Antialiasing, true);
332 
333     if (mIsActive)
334     {
335         mPend.setAlpha(0xff);
336         mPenl.setAlpha(0xff);
337         mGrad0.setAlpha(0xff);
338         mGrad1.setAlpha(0xff);
339     }
340     else if (mSolved)
341     {
342         mPend.setAlpha(0xa0);
343         mPenl.setAlpha(0xa0);
344         mGrad0.setAlpha(0xa0);
345         mGrad1.setAlpha(0xa0);
346     }
347     else
348     {
349         mPend.setAlpha(0x32);
350         mPenl.setAlpha(0x50);
351         mGrad0.setAlpha(0x32);
352         mGrad1.setAlpha(0x32);
353     }
354     painter->setPen(Qt::NoPen);
355     int i;
356     for (i = 0; i < mPegCnt; i++)
357     {
358         painter->setBrush(QBrush(mPenl));
359         painter->drawRect(QRectF(mXOffs + i * 40, 0.0, 39, 1));
360         painter->drawRect(QRectF(mXOffs + i * 40, 0.0, 1, 39));
361         painter->setBrush(QBrush(mPend));
362         painter->drawRect(QRectF(mXOffs + i * 40, 39.0, 40, 1));
363         painter->drawRect(QRectF(mXOffs + i * 40 + 39, 0.0, 1, 40));
364 
365         QRadialGradient grad(QPointF(mXOffs + i * 40 + 10, 10), 100);
366         grad.setColorAt(0, mGrad0);
367         grad.setColorAt(1, mGrad1);
368         painter->setBrush(QBrush(grad));
369         painter->drawRect(QRectF(mXOffs + i * 40 + 1, 1.0, 38.0, 38.0));
370     }
371 }
372