]> git.saurik.com Git - wxWidgets.git/blame - demos/fractal/fractal.cpp
Show EVT_ACTIVATE and EVT_ACTIVATE_APP events in action.
[wxWidgets.git] / demos / fractal / fractal.cpp
CommitLineData
025e88c5
JS
1///////////////////////////////////////////////////////////////////////////////
2// Name: fractal.cpp
3// Purpose: demo of wxConfig and related classes
4// Author: Andrew Davison
5// Modified by:
6// Created: 05.04.94
7// RCS-ID: $Id$
8// Copyright: (c) 1994 Andrew Davison
9// Licence: wxWindows licence
10///////////////////////////////////////////////////////////////////////////////
11
12
13/*
14Date: Tue, 5 Apr 1994 12:01:18 +1000
15From: Andrew Davison <andrewd@au.com.sfe>
16To: wxwin-users@ed.aiai
17Subject: Fractal mountains
18
19Hi,
20
21This is a quick port of a fractal mountain generator originally
22done for MS-Windows. On a Sun the colours look a little washed
23out and there is not as much snow or high mountains (maybe the
24random number generators fault). The viewing plane is not
25quite right as the original code used SetViewportOrg() which there
be5a51fb 26doesn't seem to be an equivalent of under wxWidgets, and my quick
025e88c5
JS
27hack doesn't fix.
28*/
29
30#ifdef __GNUG__
31#pragma implementation
32#pragma interface
33#endif
34
35#include "wx/wxprec.h"
36
c4b77901
JS
37#ifdef __BORLANDC__
38 #pragma hdrstop
39#endif
40
025e88c5
JS
41#ifndef WX_PRECOMP
42 #include "wx/wx.h"
43#endif //precompiled headers
44
45#include <stdlib.h>
46#include <math.h>
47#include <time.h>
48
49#define Random(x) (rand() % x)
50#define Randomize() (srand((unsigned int)time(NULL)))
51
e0e31ccd 52static int detail = 9; // CHANGE THIS... 7,8,9 etc
025e88c5 53
e0e31ccd 54static bool running = false;
025e88c5
JS
55static wxMenuBar *menuBar = NULL;
56
57// Define a new application type
58class MyApp: public wxApp
e0e31ccd
WS
59{
60public:
61 bool OnInit();
025e88c5
JS
62};
63
64IMPLEMENT_APP(MyApp)
65
66// Define a new frame type
67class MyFrame: public wxFrame
68{
69public:
e0e31ccd 70 MyFrame(wxFrame *frame, const wxString& title, const wxPoint& pos, const wxSize& size);
025e88c5 71
e0e31ccd 72 void OnCloseWindow(wxCloseEvent& event);
025e88c5 73 void OnExit(wxCommandEvent& event);
e0e31ccd
WS
74
75 DECLARE_EVENT_TABLE()
025e88c5
JS
76};
77
78// Define a new canvas which can receive some events
79class MyCanvas: public wxWindow
80{
81public:
e0e31ccd
WS
82 MyCanvas(wxFrame *frame);
83 void Draw(wxDC& dc);
025e88c5
JS
84
85private:
e0e31ccd
WS
86 void OnPaint(wxPaintEvent& event);
87 void Fractal(wxDC& dc, int X1, int Y1, int X2, int Y2, int Z1, int Z2, int Z3, int Z4, int Iteration, double Std, double Ratio);
88 wxPen SnowPen, MtnPen, GreenPen;
89 wxBrush WaterBrush;
90 int Sealevel;
025e88c5
JS
91
92DECLARE_EVENT_TABLE()
93};
94
95// `Main program' equivalent, creating windows and returning main app frame
96bool MyApp::OnInit()
97{
98 // Create the main frame window
e0e31ccd 99 MyFrame *frame = new MyFrame(NULL, _T("Fractal Mountains for wxWidgets"), wxDefaultPosition, wxSize(640, 480));
025e88c5
JS
100
101 // Make a menubar
102 wxMenu *file_menu = new wxMenu;
f37c24e0 103 file_menu->Append(wxID_EXIT, _T("E&xit"));
025e88c5 104 menuBar = new wxMenuBar;
f37c24e0 105 menuBar->Append(file_menu, _T("&File"));
025e88c5
JS
106 frame->SetMenuBar(menuBar);
107
108 int width, height;
109 frame->GetClientSize(&width, &height);
110
111 (void) new MyCanvas(frame);
112
113 // Show the frame
e0e31ccd 114 frame->Show(true);
025e88c5 115
e0e31ccd 116 return true;
025e88c5
JS
117}
118
119BEGIN_EVENT_TABLE(MyFrame, wxFrame)
120 EVT_CLOSE(MyFrame::OnCloseWindow)
121 EVT_MENU(wxID_EXIT, MyFrame::OnExit)
122END_EVENT_TABLE()
123
124// My frame constructor
125MyFrame::MyFrame(wxFrame *frame, const wxString& title, const wxPoint& pos, const wxSize& size):
e0e31ccd 126 wxFrame(frame, wxID_ANY, title, pos, size, wxDEFAULT_FRAME_STYLE | wxFULL_REPAINT_ON_RESIZE )
025e88c5
JS
127{
128}
129
130// Intercept menu commands
babd36de 131void MyFrame::OnExit(wxCommandEvent& WXUNUSED(event))
025e88c5
JS
132{
133 this->Destroy();
134}
135
babd36de 136void MyFrame::OnCloseWindow(wxCloseEvent& WXUNUSED(event))
025e88c5 137{
e0e31ccd 138 static bool destroyed = false;
025e88c5
JS
139 if (destroyed)
140 return;
141
142 this->Destroy();
143
e0e31ccd 144 destroyed = true;
025e88c5
JS
145}
146
147BEGIN_EVENT_TABLE(MyCanvas, wxWindow)
148 EVT_PAINT(MyCanvas::OnPaint)
149END_EVENT_TABLE()
150
151// Define a constructor for my canvas
152MyCanvas::MyCanvas(wxFrame *frame):
e0e31ccd 153 wxWindow(frame, wxID_ANY)
025e88c5
JS
154{
155 wxColour wxCol1(255,255,255);
156 SnowPen = wxPen(wxCol1, 2, wxSOLID);
157
158 wxColour wxCol2(128,0,0);
159 MtnPen = wxPen(wxCol2, 1, wxSOLID);
160
161 wxColour wxCol3(0,128,0);
162 GreenPen = wxPen(wxCol3, 1, wxSOLID);
163
164 wxColour wxCol4(0,0,128);
165 WaterBrush = wxBrush(wxCol4, wxSOLID);
166}
167
babd36de 168void MyCanvas::OnPaint(wxPaintEvent& WXUNUSED(event))
025e88c5
JS
169{
170 wxPaintDC dc(this);
e0e31ccd
WS
171 PrepareDC(dc);
172 Draw(dc);
025e88c5
JS
173}
174
175void MyCanvas::Draw(wxDC& dc)
176{
177 if (running) return;
178
e0e31ccd
WS
179 running = true;
180 menuBar->EnableTop(0, false);
181
182 Randomize();
025e88c5 183
e0e31ccd
WS
184 dc.SetBackground(*wxLIGHT_GREY_BRUSH);
185 dc.Clear();
025e88c5 186
e0e31ccd
WS
187 int Left, Top, Right, Bottom;
188 GetClientSize(&Right, &Bottom);
025e88c5 189
e0e31ccd
WS
190 Right *= 3; Right /= 4;
191 Bottom *= 3; Bottom /= 4;
192 Left = 0;
193 Top = Bottom/8;
025e88c5 194
e0e31ccd
WS
195 wxPoint Water[4];
196 Water[0].x = Left; Water[0].y = Top;
197 Water[1].x = Right; Water[1].y = Top;
198 Water[2].x = Right+Bottom/2; Water[2].y = Bottom;
199 Water[3].x = Bottom/2; Water[3].y = Bottom;
025e88c5 200
e0e31ccd
WS
201 dc.SetBrush(WaterBrush);
202 dc.DrawPolygon(4, Water);
025e88c5 203
e0e31ccd
WS
204 double H = 0.75;
205 double Scale = Bottom;
206 double Ratio = 1.0 / pow(2.0, H);
207 double Std = Scale * Ratio;
208 Sealevel = Random(18) - 8;
025e88c5 209
e0e31ccd 210 Fractal(dc, Left, Top, Right, Bottom, 0, 0, 0, 0, detail, Std, Ratio);
025e88c5 211
e0e31ccd
WS
212 menuBar->EnableTop(0, true);
213 running = false;
025e88c5
JS
214}
215
216void MyCanvas::Fractal(wxDC& dc, int X1, int Y1, int X2, int Y2, int Z1, int Z2, int Z3, int Z4, int Iteration, double Std, double Ratio)
217{
e0e31ccd
WS
218 int Xmid = (X1 + X2) / 2;
219 int Ymid = (Y1 + Y2) / 2;
220 int Z23 = (Z2 + Z3) / 2;
221 int Z41 = (Z4 + Z1) / 2;
222 int Newz = (int)((Z1 + Z2 + Z3 + Z4) / 4 + (double)(Random(17) - 8) / 8.0 * Std);
223
224 if (--Iteration)
225 {
226 int Z12 = (Z1 + Z2) / 2;
227 int Z34 = (Z3 + Z4) / 2;
228 double Stdmid = Std * Ratio;
229
230 Fractal(dc, Xmid, Y1, X2, Ymid, Z12, Z2, Z23, Newz, Iteration, Stdmid, Ratio);
231 Fractal(dc, X1, Y1, Xmid, Ymid, Z1, Z12, Newz, Z41, Iteration, Stdmid, Ratio);
232 Fractal(dc, Xmid, Ymid, X2, Y2, Newz, Z23, Z3, Z34, Iteration, Stdmid, Ratio);
233 Fractal(dc, X1, Ymid, Xmid, Y2, Z41, Newz, Z34, Z4, Iteration, Stdmid, Ratio);
234 }
235 else
236 {
237 if (Newz <= Sealevel)
238 {
239 wxPoint P[4];
240 P[0].x = Y1 / 2 + X1; P[0].y = Y1 + Z1;
241 P[1].x = Y1 / 2 + X2; P[1].y = Y1 + Z2;
242 P[2].x = Y2 / 2 + X2; P[2].y = Y2 + Z3;
243 P[3].x = Y2 / 2 + X1; P[3].y = Y2 + Z4;
244
245 dc.SetPen(* wxBLACK_PEN);
246 dc.SetBrush(* wxBLACK_BRUSH);
247
248 dc.DrawPolygon(4, P);
249
250 if (Z1 >= -(60+Random(25)))
251 dc.SetPen(GreenPen);
252 else if (Z1 >= -(100+Random(25)))
253 dc.SetPen(MtnPen);
254 else
255 dc.SetPen(SnowPen);
256
257 dc.DrawLine(Ymid/2+X2, Ymid+Z23, Ymid/2+X1, Ymid+Z41);
258 }
259 }
025e88c5
JS
260}
261