view src/App.cpp @ 10:9efbc0c6637b

Removed commented out code
author Eris Caffee <discordia@eldalin.com>
date Wed, 17 Nov 2010 22:09:15 -0600
parents 00de693e73be
children bdd2e7b37220 bdfe3327f4ce
line source
1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // Fracter - A simple Mandelbrot Set viewer.
4 //
5 // Copyright (C) 2010 Sarah Eris Horsley Caffee
6 //
7 // This file is part of Fracter.
8 //
9 // Fracter 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 3 of the License, or
12 // (at your option) any later version.
13 //
14 // This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
21 //
22 //
23 // App.cpp
24 // Application class implementation
25 //
26 ////////////////////////////////////////////////////////////////////////////////
28 #include <iomanip>
29 #include <iostream>
30 #include <sstream>
31 #include <typeinfo>
32 #include <vector>
34 #if defined(WIN32)
35 #include <cstdlib>
36 #include <windows.h>
37 #include <Shlwapi.h>
39 #else
40 #include <cctype>
41 #include <cstring>
42 #include <cstdio>
44 #include <dirent.h>
45 #endif
48 #include "SDL.h"
50 #include "App.h"
52 #include "Options.h"
53 #include "Mandelbrot.h"
54 #include "Julia.h"
57 ////////////////////////////////////////////////////////////////////////////////
59 App::App() :
60 running (true),
61 redraw (false),
62 surf_display (NULL),
63 surf_selection (NULL),
64 surf_fractal (NULL),
65 selection_x (-1),
66 selection_y (-1),
67 selection_width (-1),
68 setting_zoom (false),
69 can_set_julia_k (false),
70 setting_julia_k (false),
71 old_views (),
72 fractal (NULL)
73 {
74 }
77 ////////////////////////////////////////////////////////////////////////////////
78 App::~App()
79 {
80 old_views.clear();
81 }
84 ////////////////////////////////////////////////////////////////////////////////
86 int App::run()
87 {
88 if (init() == false)
89 return 1;
91 SDL_Event event;
93 while (running)
94 {
95 SDL_WaitEvent(&event);
96 do
97 {
98 on_Event(&event);
99 }
100 while (SDL_PollEvent(&event));
102 update();
104 if (redraw)
105 render();
106 }
108 cleanup();
110 return 0;
111 }
114 ////////////////////////////////////////////////////////////////////////////////
116 bool App::init()
117 {
118 if ((SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER)) == -1)
119 {
120 std::cerr << "SDL_Init() failed: " << SDL_GetError() << std::endl;
121 return false;
122 }
124 if ((surf_display = SDL_SetVideoMode(Options::width,
125 Options::height,
126 Options::bpp,
127 SDL_HWSURFACE | SDL_DOUBLEBUF)) == NULL)
128 {
129 std::cerr << "SDL_SetVideoMode() failed: "
130 << SDL_GetError() << std::endl;
131 return false;
132 }
134 SDL_EnableKeyRepeat(500, 100);
137 if (!create_new_surface(surf_selection)) { return false; }
138 if (!create_new_surface(surf_fractal)) { return false; }
141 std::cerr << "Available fractal types are" << std::endl;
142 std::map <std::string, FractalFactory *> mymap = get_Fractal_map();
143 std::map <std::string, FractalFactory *>::iterator it;
144 for ( it=mymap.begin() ; it != mymap.end(); it++ )
145 std::cerr << " " << (*it).first << std::endl;
147 FractalFactory * fractal_factory =
148 get_Fractal_map()[typeid(Mandelbrot).name()];
149 if (!fractal_factory)
150 {
151 std::cerr << "Mandelbrot set not available!" << std::endl;
152 return false;
153 }
154 fractal = fractal_factory->create();
155 fractal->init(surf_fractal);
156 redraw = true;
158 can_set_julia_k = true;
161 set_caption();
163 SDL_AddTimer(10, App::timer_callback, NULL);
165 return true;
166 }
169 ////////////////////////////////////////////////////////////////////////////////
171 void App::update()
172 {
173 }
176 ////////////////////////////////////////////////////////////////////////////////
178 void App::render()
179 {
180 if (redraw)
181 {
182 // Start with a clean slate.
183 SDL_FillRect(surf_display, &surf_display->clip_rect,
184 SDL_MapRGB(surf_display->format, 0, 0, 255));
186 fractal->calc_set();
187 SDL_BlitSurface(surf_fractal, NULL, surf_display, NULL);
189 // draw a selection box
190 if (setting_zoom)
191 {
192 SDL_BlitSurface(surf_selection, NULL, surf_display, NULL);
193 }
195 // Show it to the user.
196 SDL_Flip(surf_display);
198 redraw = false;
199 }
200 }
203 ////////////////////////////////////////////////////////////////////////////////
205 void App::cleanup()
206 {
208 if (surf_selection)
209 {
210 SDL_FreeSurface(surf_selection);
211 surf_selection = NULL;
212 }
213 if (surf_display)
214 {
215 SDL_FreeSurface(surf_display);
216 surf_display = NULL;
217 }
219 SDL_Quit();
220 }
223 ////////////////////////////////////////////////////////////////////////////////
225 void App::on_InputFocus()
226 {
227 SDL_EventState(SDL_MOUSEMOTION, SDL_ENABLE);
228 SDL_EventState(SDL_MOUSEBUTTONDOWN, SDL_ENABLE);
229 SDL_EventState(SDL_MOUSEBUTTONUP, SDL_ENABLE);
230 }
233 ////////////////////////////////////////////////////////////////////////////////
235 void App::on_InputBlur()
236 {
237 SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE);
238 SDL_EventState(SDL_MOUSEBUTTONDOWN, SDL_IGNORE);
239 SDL_EventState(SDL_MOUSEBUTTONUP, SDL_IGNORE);
240 }
243 ////////////////////////////////////////////////////////////////////////////////
245 void App::on_KeyDown(SDL_KeyboardEvent key)
246 {
247 switch (key.keysym.sym)
248 {
249 case SDLK_ESCAPE:
250 case SDLK_q:
251 SDL_Event event;
252 event.type = SDL_QUIT;
253 SDL_PushEvent(&event);
254 break;
256 case SDLK_b:
257 restore_view();
258 redraw = true;
259 set_caption();
260 break;
262 case SDLK_s:
263 save_image();
264 break;
266 case SDLK_UP:
267 fractal->inc_max_iter();
268 set_caption();
269 break;
270 case SDLK_DOWN:
271 fractal->dec_max_iter();
272 set_caption();
273 break;
276 case SDLK_m:
277 if (fractal)
278 {
279 FractalFactory * fractal_factory =
280 get_Fractal_map()[typeid(Mandelbrot).name()];
281 if (!fractal_factory)
282 {
283 std::cerr << "Mandelbrot set not available!" << std::endl;
284 SDL_Event event;
285 event.type = SDL_QUIT;
286 SDL_PushEvent(&event);
287 }
288 else
289 {
290 save_view();
291 delete fractal;
292 fractal = fractal_factory->create();
293 fractal->init(surf_fractal);
294 redraw = true;
295 set_caption();
296 can_set_julia_k = true;
297 }
298 }
299 break;
301 case SDLK_j:
302 if (fractal)
303 {
304 FractalFactory * fractal_factory =
305 get_Fractal_map()[typeid(Julia).name()];
306 if (!fractal_factory)
307 {
308 std::cerr << "Julia set not available!" << std::endl;
309 }
310 else
311 {
312 save_view();
313 delete fractal;
314 fractal = fractal_factory->create();
315 fractal->init(surf_fractal);
316 redraw = true;
317 set_caption();
318 can_set_julia_k = false;
319 }
320 }
321 break;
323 case SDLK_k:
324 if (can_set_julia_k)
325 {
326 if (setting_julia_k) setting_julia_k = false;
327 else setting_julia_k = true;
328 }
329 break;
331 default:
332 break;
333 }
334 }
337 ////////////////////////////////////////////////////////////////////////////////
338 void App::on_KeyUp(SDL_KeyboardEvent key)
339 {
340 switch (key.keysym.sym)
341 {
342 case SDLK_UP:
343 fractal->set_calc_needed();
344 redraw = true;
345 break;
346 case SDLK_DOWN:
347 fractal->set_calc_needed();
348 redraw = true;
349 break;
350 default:
351 break;
352 }
353 }
356 ////////////////////////////////////////////////////////////////////////////////
357 void App::on_MouseMove(SDL_MouseMotionEvent motion)
358 {
359 if (setting_zoom)
360 {
361 Uint32 clear = SDL_MapRGBA(surf_selection->format,
362 0, 0, 0, SDL_ALPHA_TRANSPARENT);
363 Uint32 white = SDL_MapRGBA(surf_selection->format,
364 255, 255, 255, SDL_ALPHA_OPAQUE);
366 SDL_FillRect(surf_selection, &surf_selection->clip_rect, clear);
368 SDL_Rect rect;
369 rect.x = selection_x;
370 rect.y = selection_y;
371 int w = mouse_move_width(motion.x, motion.y);
372 rect.w = rect.h = w;
374 SDL_FillRect(surf_selection, &rect, white);
376 rect.x = selection_x + 1;
377 rect.y = selection_y + 1;
378 rect.w = rect.h = w - 2;
380 SDL_FillRect(surf_selection, &rect, clear);
382 redraw = true;
383 }
384 }
386 ////////////////////////////////////////////////////////////////////////////////
388 void App::on_LButtonDown(SDL_MouseButtonEvent button)
389 {
390 if (setting_julia_k)
391 {
392 set_julia_k(button.x, button.y);
393 }
394 else
395 {
396 selection_x = button.x;
397 selection_y = button.y;
398 setting_zoom = true;
399 }
400 }
403 ////////////////////////////////////////////////////////////////////////////////
405 void App::on_LButtonUp(SDL_MouseButtonEvent button)
406 {
407 if (setting_zoom)
408 {
409 selection_width = mouse_move_width(button.x, button.y);
410 if ( (button.x <= 0) ||
411 (button.x >= surf_display->w - 1) ||
412 (button.y <= 0) ||
413 (button.y >= surf_display->h - 1) ||
414 (selection_width == 0))
415 {
416 // Selection cancelled
417 setting_zoom = false;
418 return;
419 }
421 // calculate new min/max re/im
422 double Re_scale = (fractal->get_size())/(surf_fractal->w - 1);
423 double Im_scale = (fractal->get_size())/(surf_fractal->h - 1);
425 double new_re_min = fractal->get_re_min() + (selection_x) * Re_scale;
426 double new_im_max = fractal->get_im_max() - (selection_y) * Im_scale;
427 double new_size = selection_width * Re_scale;
429 save_view();
431 fractal->set_re_min(new_re_min);
432 fractal->set_im_max(new_im_max);
433 fractal->set_size(new_size);
434 fractal->set_calc_needed();
435 redraw = true;
437 set_caption();
439 setting_zoom = false;
440 }
441 }
444 ////////////////////////////////////////////////////////////////////////////////
445 void App::on_Expose()
446 {
447 redraw = true;
448 }
451 ////////////////////////////////////////////////////////////////////////////////
453 void App::on_Quit()
454 {
455 running = false;
456 }
459 ////////////////////////////////////////////////////////////////////////////////
460 int App::mouse_move_width(int mx, int my)
461 {
462 int move_width = (mx - selection_x);
463 if (mx > selection_x)
464 {
465 move_width *= -1;
466 }
468 int tmp_i = (my - selection_y);
469 if (my < selection_y)
470 {
471 tmp_i *= -1;
472 }
474 if (tmp_i > move_width)
475 move_width = tmp_i;
477 return move_width;
478 }
481 ////////////////////////////////////////////////////////////////////////////////
482 bool App::create_new_surface(SDL_Surface * &surface)
483 {
484 if (surface)
485 {
486 SDL_FreeSurface(surface);
487 surface = NULL;
488 }
490 SDL_Surface * tmp;
491 if ((tmp = SDL_CreateRGBSurface(SDL_HWSURFACE|SDL_SRCALPHA,
492 Options::width, Options::height,
493 Options::bpp, 0, 0, 0, 0))
494 == NULL)
495 {
496 std::cerr << "SDL_CreateRGBSurface() failed in "
497 << "App::create_new_surface(): "
498 << SDL_GetError() << std::endl;
499 return false;
500 }
502 surface = SDL_DisplayFormatAlpha(tmp);
503 SDL_FreeSurface(tmp);
505 return true;
506 }
509 ////////////////////////////////////////////////////////////////////////////////
510 void App::set_julia_k(int x, int y)
511 {
512 FractalFactory * fractal_factory = get_Fractal_map()[typeid(Julia).name()];
513 if (!fractal_factory)
514 {
515 std::cerr << "Julia set not available!" << std::endl;
516 return;
517 }
518 else
519 {
520 save_view();
522 delete fractal;
523 fractal = fractal_factory->create();
524 fractal->init(surf_fractal);
526 double k[2];
527 k[0]= fractal->get_re_min() + x *
528 (fractal->get_size())/(surf_fractal->w - 1);
529 k[1] = fractal->get_im_max() - y *
530 (fractal->get_size())/(surf_fractal->h - 1);
532 fractal->set_option("k", k);
533 fractal->set_calc_needed();
534 redraw = true;
536 set_caption();
537 setting_julia_k = false;
538 }
539 }
542 ////////////////////////////////////////////////////////////////////////////////
544 void App::restore_view()
545 {
546 if (old_views.size() > 0)
547 {
548 View * v = old_views.back();
549 old_views.pop_back();
551 if (v->get_type().compare(fractal->get_fractal_name()) != 0)
552 {
553 delete fractal;
554 FractalFactory * fractal_factory = get_Fractal_map()[v->get_type()];
555 if (!fractal_factory)
556 {
557 std::cerr << "Cannot restore old view: unknown Fractal type "
558 << v->get_type() << std::endl;
559 SDL_Event event;
560 event.type = SDL_QUIT;
561 SDL_PushEvent(&event);
562 return;
563 }
564 fractal = fractal_factory->create();
565 fractal->init(surf_fractal);
566 }
568 fractal->restore_view(v);
569 delete v;
570 }
571 }
574 ////////////////////////////////////////////////////////////////////////////////
575 void App::save_view()
576 {
577 View * v = fractal->save_view();
578 old_views.push_back(v);
579 }
582 ////////////////////////////////////////////////////////////////////////////////
583 void App::set_caption()
584 {
585 std::stringstream ss;
586 ss << fractal->get_display_name() << " / "
587 << "Real: " << fractal->get_re_min()
588 << " to "<< fractal->get_re_min() + fractal->get_size()
589 << " / Imaginary: " << fractal->get_im_max() - fractal->get_size()
590 << " to " << fractal->get_im_max()
591 << " / Max iterations: " << fractal->get_max_iter();
592 SDL_WM_SetCaption(ss.str().c_str(), NULL);
593 }
596 ////////////////////////////////////////////////////////////////////////////////
597 bool App::save_image()
598 {
599 int i = App::get_next_file_num();
600 std::stringstream name;
601 name << "fracter-" << std::setw(3) << std::setfill('0') << i << ".bmp";
603 if (SDL_SaveBMP(surf_display, name.str().c_str()) != 0)
604 {
605 std::cerr << "Unable to save image file " << name.str() << "" << std::endl;
606 return false;
607 }
609 std::cerr << "Saved image as " << name.str() << std::endl;
611 return true;
612 }
615 ////////////////////////////////////////////////////////////////////////////////
616 Uint32 App::timer_callback(Uint32 interval, void *param)
617 {
618 SDL_Event e;
620 e.type = SDL_USEREVENT;
621 e.user.code = 0;
622 e.user.data1 = NULL;
623 e.user.data2 = NULL;
624 SDL_PushEvent(& e);
626 return interval;
627 }
630 #if defined(WIN32)
631 ////////////////////////////////////////////////////////////////////////////////
632 //Code for Windows
633 int App::get_next_file_num()
634 {
635 static int i = 0;
637 if (i == 0)
638 {
639 WIN32_FIND_DATA ffd;
640 HANDLE hFind = INVALID_HANDLE_VALUE;
642 char * file_spec = "fracter-???.bmp";
643 hFind = FindFirstFile(file_spec, &ffd);
644 if (hFind != INVALID_HANDLE_VALUE)
645 {
646 std::string s;
647 std::stringstream ss;
648 do
649 {
650 std::cerr << ffd.cFileName << std::endl;
651 ss << ffd.cFileName;
652 if (ss.str().size() == 18)
653 {
654 s = ss.str().substr(0, 11);
655 if ( StrCmpI(s.c_str(), "fracter-") == 0 )
656 {
657 s = ss.str().substr(14, 4);
658 if (StrCmpI(s.c_str(), ".bmp") == 0)
659 {
660 s = ss.str().substr(11, 3);
661 int j = atoi(s.c_str());
662 if (j > i) i = j;
663 }
664 }
665 }
666 }
667 while (FindNextFile(hFind, &ffd) != 0);
668 }
669 }
671 i++;
672 return i;
673 }
677 #else
678 ////////////////////////////////////////////////////////////////////////////////
679 // Code for Linux
681 int App::scandir_filter(const struct dirent * d)
682 {
683 if (memcmp(d->d_name, "fracter-", 8) != 0) return 0;
684 if (memcmp(d->d_name+11, ".bmp", 4) != 0) return 0;
685 if (isdigit(d->d_name[8])
686 && isdigit(d->d_name[9])
687 && isdigit(d->d_name[10]))
688 return 1;
689 return 0;
690 }
693 int App::get_next_file_num()
694 {
695 static int i = 0;
697 if (i == 0)
698 {
699 struct dirent ** file_list;
700 int num_files = scandir(".", &file_list, scandir_filter, alphasort);
701 if (num_files != 0)
702 sscanf(file_list[num_files-1]->d_name, "fracter-%03d.bmp", &i);
703 }
704 i++;
706 return i;
707 }
709 #endif