1 /* BurrTools
2  *
3  * BurrTools is the legal property of its developers, whose
4  * names are listed in the COPYRIGHT file, which is included
5  * within the source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11 
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16 
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20  */
21 #include "statuswindow.h"
22 #include "piececolor.h"
23 
24 #include "../lib/voxel.h"
25 #include "../lib/puzzle.h"
26 #include "../lib/problem.h"
27 #include "../lib/millable.h"
28 #include "../lib/voxeltable.h"
29 
30 #include <FL/Fl.H>
31 
32 class LFl_Line : public Fl_Box, public layoutable_c {
33 
34   private:
35 
36     int thickness;
37 
38   public:
39 
LFl_Line(int x,int y,int w,int h,int thick=1,Fl_Color col=FL_BLACK)40   LFl_Line(int x, int y, int w, int h, int thick = 1, Fl_Color col = FL_BLACK) : Fl_Box(0, 0, 0, 0), layoutable_c(x, y, w, h), thickness(thick) {
41     color(col);
42     box(FL_FLAT_BOX);
43   }
44 
getMinSize(int * width,int * height) const45   virtual void getMinSize(int *width, int *height) const {
46     *width = thickness;
47     *height = thickness;
48   }
49 };
50 
cb_Close_stub(Fl_Widget *,void * v)51 static void cb_Close_stub(Fl_Widget*, void* v) { ((statusWindow_c*)v)->hide(); }
cb_RemoveSelected_stub(Fl_Widget *,void * v)52 static void cb_RemoveSelected_stub(Fl_Widget*, void* v) { ((statusWindow_c*)v)->cb_removeSelected(); }
53 
54 class StatusProgress : public LFl_Double_Window {
55 
56   private:
57 
58     LFl_Progress * p;
59 
60   public:
61 
StatusProgress(void)62     StatusProgress(void) : LFl_Double_Window(false) {
63 
64       label("Progress");
65 
66       (new LFl_Box("Calculating Status information.\n"
67                   "This might take some time...", 0, 0, 1, 1))->pitch(3);
68 
69       p = new LFl_Progress(0, 1, 1, 1);
70       p->minimum(0);
71       p->maximum(1);
72       p->selection_color((Fl_Color)4);
73       p->pitch(3);
74 
75       LFl_Button * btn = new LFl_Button("Cancel", 0, 2, 1, 1);
76       btn->pitch(3);
77       btn->callback(cb_Close_stub, this);
78 
79       end();
80 
81       set_modal();
82     }
83 
setProgress(float value)84     void setProgress(float value) {
85       p->value(value);
86     }
87 };
88 
cb_removeSelected(void)89 void statusWindow_c::cb_removeSelected(void) {
90 
91   bt_assert(selection.size() <= puz->shapeNumber());
92 
93   /* we have to go up from the bottom as otherwise the indixes may shift
94    *
95    * we hafe to use the selection size as starting point as
96    * the user may have pressed cancel during calculation leaving us
97    * with an incomplete list
98    */
99   for (unsigned int s = selection.size(); s > 0; s--)
100   {
101     if (selection[s-1]->value())
102     {
103       for (unsigned int i = 0; i < puz->problemNumber(); i++)
104         if (puz->getProblem(i)->usesShape(s-1))
105           puz->getProblem(i)->removeAllSolutions();
106 
107       puz->removeShape(s-1);
108     }
109   }
110 
111   again = true;
112   hide();
113 }
114 
statusWindow_c(puzzle_c * p)115 statusWindow_c::statusWindow_c(puzzle_c * p) : LFl_Double_Window(true), puz(p), again(false) {
116 
117   StatusProgress *  stp = new StatusProgress;
118   stp->show();
119 
120   begin();
121 
122   char tmp[200];
123 
124   label("Shape Information");
125 
126   unsigned int lines = p->shapeNumber();
127   unsigned int head = 3;
128 
129   layouter_c * fr = new layouter_c(0, 0, 1, 1);
130   fr->pitch(7);
131 
132   (new LFl_Scroll(0, 0, 1, 1))->type(Fl_Scroll::VERTICAL_ALWAYS);
133 
134   unsigned int cols = 27;
135 
136   // 2 more columns for notchable and millable
137   if (p->getGridType()->getType() == gridType_c::GT_BRICKS)
138     cols += 4;
139 
140   voxelTablePuzzle_c shapeTab(p);
141 
142   for (unsigned int s = 0; s < p->shapeNumber(); s++) {
143 
144     LFl_Box * b;
145 
146     if (s & 1) {
147       b = new LFl_Box("", 0, s+head, cols, 1);
148       b->color(fl_rgb_color(150, 150, 150));
149       b->box(FL_FLAT_BOX);
150     }
151 
152     const voxel_c * v = p->getShape(s);
153 
154     unsigned int col = 0;
155 
156     selection.push_back(new LFl_Check_Button(" ", col, s+head));
157     col+=2;
158 
159     if (v->getName().length())
160       snprintf(tmp, 200, "S%i - %s", s+1, v->getName().c_str());
161     else
162       snprintf(tmp, 200, "S%i", s+1);
163 
164     b = new LFl_Box("", col, s+head);
165     b->copy_label(tmp);
166     b->color(fltkPieceColor(s));
167     b->labelcolor(contrastPieceColor(s));
168     b->box(FL_FLAT_BOX);
169     col += 2;
170 
171     snprintf(tmp, 200, "%i", v->countState(voxel_c::VX_FILLED));
172     (new LFl_Box("", col, s+head))->copy_label(tmp);
173     col += 2;
174 
175     snprintf(tmp, 200, "%i", v->countState(voxel_c::VX_VARIABLE));
176     (new LFl_Box("", col, s+head))->copy_label(tmp);
177     col += 2;
178 
179     snprintf(tmp, 200, "%i", v->countState(voxel_c::VX_VARIABLE) + v->countState(voxel_c::VX_FILLED));
180     (new LFl_Box("", col, s+head))->copy_label(tmp);
181     col += 2;
182     Fl::wait(0);
183 
184     unsigned int shapeIdx;
185     unsigned char shapeTrans;
186     bool shapeKnown = shapeTab.getSpace(v, &shapeIdx, &shapeTrans, voxelTable_c::PAR_MIRROR);
187 
188     if (shapeKnown)
189     {
190       snprintf(tmp, 200, "%i", shapeIdx+1);
191       b = new LFl_Box("", col, s+head);
192       b->copy_label(tmp);
193       b->color(fltkPieceColor(shapeIdx));
194       b->labelcolor(contrastPieceColor(shapeIdx));
195       b->box(FL_FLAT_BOX);
196     }
197     col += 2;
198     Fl::wait(0);
199 
200     shapeKnown = shapeTab.getSpace(v, &shapeIdx, &shapeTrans, 0);
201 
202     if (shapeKnown)
203     {
204       snprintf(tmp, 200, "%i", shapeIdx+1);
205       b = new LFl_Box("", col, s+head);
206       b->copy_label(tmp);
207       b->color(fltkPieceColor(shapeIdx));
208       b->labelcolor(contrastPieceColor(shapeIdx));
209       b->box(FL_FLAT_BOX);
210     }
211     col += 2;
212     Fl::wait(0);
213 
214     shapeKnown = shapeTab.getSpace(v, &shapeIdx, &shapeTrans, voxelTable_c::PAR_COLOUR);
215 
216     if (shapeKnown && shapeTrans < p->getGridType()->getSymmetries()->getNumTransformations())
217     {
218       snprintf(tmp, 200, "%i", shapeIdx+1);
219       b = new LFl_Box("", col, s+head);
220       b->copy_label(tmp);
221       b->color(fltkPieceColor(shapeIdx));
222       b->labelcolor(contrastPieceColor(shapeIdx));
223       b->box(FL_FLAT_BOX);
224     }
225     col +=2 ;
226     Fl::wait(0);
227 
228     if (v->connected(0, true, 0)) {
229       new LFl_Box("X", col, s+head);
230     } else {
231       b = new LFl_Box("", col, s+head);
232       b->color(fl_rgb_color(pieceColorRi(s), pieceColorGi(s), pieceColorBi(s)));
233       b->box(FL_FLAT_BOX);
234     }
235     col += 2;
236     Fl::wait(0);
237 
238     if (v->connected(1, true, 0)) {
239       new LFl_Box("X", col, s+head);
240     } else {
241       b = new LFl_Box("", col, s+head);
242       b->color(fl_rgb_color(pieceColorRi(s), pieceColorGi(s), pieceColorBi(s)));
243       b->box(FL_FLAT_BOX);
244     }
245     col += 2;
246     Fl::wait(0);
247 
248     if (v->connected(2, true, 0)) {
249       new LFl_Box("X", col, s+head);
250     } else {
251       b = new LFl_Box("", col, s+head);
252       b->color(fl_rgb_color(pieceColorRi(s), pieceColorGi(s), pieceColorBi(s)));
253       b->box(FL_FLAT_BOX);
254     }
255     col += 2;
256     Fl::wait(0);
257 
258     if (!v->connected(0, false, 0, false)) {
259       b = new LFl_Box("X", col, s+head);
260       b->color(fltkPieceColor(s));
261       b->labelcolor(contrastPieceColor(s));
262       b->box(FL_FLAT_BOX);
263     }
264     col += 2;
265     Fl::wait(0);
266 
267     if (!v->connected(0, false, 0)) {
268       b = new LFl_Box("X", col, s+head);
269       b->color(fltkPieceColor(s));
270       b->labelcolor(contrastPieceColor(s));
271       b->box(FL_FLAT_BOX);
272     }
273     col += 2;
274     Fl::wait(0);
275 
276     if (p->getGridType()->getType() == gridType_c::GT_BRICKS) {
277       if (isNotchable(v))
278         b = new LFl_Box("X", col, s+head);
279 
280       col += 2;
281 
282       if (isMillable(v))
283         b = new LFl_Box("X", col, s+head);
284 
285       col += 2;
286     }
287 
288     if (!p->getGridType()->getSymmetries()->symmetryKnown(v)) {
289       b = new LFl_Box("---", col, s+head);
290       b->color(fltkPieceColor(s));
291       b->labelcolor(contrastPieceColor(s));
292       b->box(FL_FLAT_BOX);
293     } else {
294       snprintf(tmp, 200, "%i", p->getGridType()->getSymmetries()->calculateSymmetry(v));
295       b = new LFl_Box("", col, s+head);
296       b->copy_label(tmp);
297       b->box(FL_NO_BOX);
298     }
299     col += 2;
300 
301     stp->setProgress(1.0*s/p->shapeNumber());
302     Fl::wait(0);
303     if (!stp->visible())
304       break;
305 
306     shapeTab.addSpace(s, voxelTable_c::PAR_MIRROR);
307     shapeTab.addSpace(s, voxelTable_c::PAR_MIRROR | voxelTable_c::PAR_COLOUR);
308   }
309 
310   stp->hide();
311   delete stp;
312 
313   unsigned int col = 1;
314 
315   new LFl_Line(col++, 0, 1, lines+head, 2);
316 
317   (new LFl_Box("Shape", col++, 0))->pitch(2);
318   new LFl_Line(col++, 0, 1, lines+head, 2);
319 
320   (new LFl_Box("Units", col, 0, 5))->pitch(2);
321   (new LFl_Box("Normal", col++, 1))->pitch(2);
322   new LFl_Line(col++, 1, 1, lines+head-1, 1);
323   (new LFl_Box("Variable", col++, 1))->pitch(2);
324   new LFl_Line(col++, 1, 1, lines+head-1, 1);
325   (new LFl_Box("Total", col++, 1))->pitch(2);
326   new LFl_Line(col++, 0, 1, lines+head, 2);
327 
328   (new LFl_Box("Identical", col, 0, 5))->pitch(2);
329   (new LFl_Box("Mirror", col++, 1))->pitch(2);
330   new LFl_Line(col++, 1, 1, lines+head-1, 1);
331   (new LFl_Box("Shape", col++, 1))->pitch(2);
332   new LFl_Line(col++, 1, 1, lines+head-1, 1);
333   (new LFl_Box("Complete", col++, 1))->pitch(2);
334   new LFl_Line(col++, 0, 1, lines+head, 2);
335 
336   (new LFl_Box("Connectivity", col, 0, 5))->pitch(2);
337   (new LFl_Box("Face", col++, 1))->pitch(2);
338   new LFl_Line(col++, 1, 1, lines+head-1, 1);
339   (new LFl_Box("Edge", col++, 1))->pitch(2);
340   new LFl_Line(col++, 1, 1, lines+head-1, 1);
341   (new LFl_Box("Corner", col++, 1))->pitch(2);
342   new LFl_Line(col++, 0, 1, lines+head, 2);
343 
344   (new LFl_Box("Holes", col, 0, 3))->pitch(2);
345   (new LFl_Box("2D", col++, 1))->pitch(2);
346   new LFl_Line(col++, 1, 1, lines+head-1, 1);
347   (new LFl_Box("3D", col++, 1))->pitch(2);
348   new LFl_Line(col++, 0, 1, lines+head, 2);
349 
350   if (p->getGridType()->getType() == gridType_c::GT_BRICKS) {
351 
352     (new LFl_Box("Tools", col, 0, 3))->pitch(2);
353     (new LFl_Box("Notch", col++, 1))->pitch(2);
354     new LFl_Line(col++, 1, 1, lines+head-1, 1);
355     (new LFl_Box("Mill", col++, 1))->pitch(2);
356     new LFl_Line(col++, 0, 1, lines+head, 2);
357   }
358 
359   (new LFl_Box("Sym", col++, 0, 1))->pitch(2);
360 
361   new LFl_Line(0, 2, cols, 1, 2);
362 
363   fr->end();
364   fr->setMinimumSize(10, 200);
365   fr->weight(1, 1);
366 
367   fr = new layouter_c(0, 1, 1, 1);
368   fr->pitch(7);
369 
370   LFl_Button * btn = new LFl_Button("Close", 0, 1);
371   btn->callback(cb_Close_stub, this);
372   btn->weight(1, 0);
373 
374   (new LFl_Box(1, 1))->setMinimumSize(5, 0);
375 
376   btn = new LFl_Button("Remove selected", 2, 1);
377   btn->callback(cb_RemoveSelected_stub, this);
378   btn->weight(1, 0);
379 
380   fr->end();
381 
382 
383   set_modal();
384 }
385