~toolpart/+junk/pythoncard

« back to all changes in this revision

Viewing changes to samples/lsystem/lsystem.py

  • Committer: Bazaar Package Importer
  • Author(s): Mohammed Adnène Trojette
  • Date: 2006-11-12 17:52:13 UTC
  • mfrom: (2.1.5 feisty)
  • Revision ID: james.westby@ubuntu.com-20061112175213-tv8bnl6rtpa2qw1o
Tags: 0.8.1-8.1
* Non-maintainer upload.
* Fix path to findfiles, codeEditor and resourceEditor:
   + patch from Ernest ter Kuile <ernestjw@xs4all.nl>. (Closes: #397018)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/python
 
2
 
 
3
"""
 
4
__version__ = "$Revision: 1.5 $"
 
5
__date__ = "$Date: 2004/08/12 19:18:54 $"
 
6
"""
 
7
 
 
8
from PythonCard import clipboard, dialog, graphic, model
 
9
from PythonCard.turtle import AbstractTurtle, BitmapTurtle
 
10
import wx
 
11
import os
 
12
import time
 
13
 
 
14
class LSystem(model.Background):
 
15
 
 
16
    def on_initialize(self, event):
 
17
        self.filename = None
 
18
        self.on_iterations_select(None)
 
19
        self.on_angle_select(None)
 
20
    
 
21
    def on_iterations_select(self, event):
 
22
        self.components.iterationDisplay.text = \
 
23
            str(self.components.iterations.value)
 
24
    
 
25
    def on_angle_select(self, event):
 
26
        self.components.angleDisplay.text = \
 
27
            str(self.components.angle.value)
 
28
    
 
29
    def on_angleDisplay_textUpdate(self, event):
 
30
        self.components.angle.value = \
 
31
            int(self.components.angleDisplay.text)
 
32
        
 
33
    def on_Render_command(self, event):
 
34
        self.statusBar.text = "Drawing, please wait..."
 
35
        starttime = time.time()
 
36
 
 
37
        fractalString = self.expand(
 
38
                self.components.scriptField.text,
 
39
                self.components.iterations.value)
 
40
        borderWidth = 5.0
 
41
        angle = self.components.angle.value
 
42
        self.components.bufOff.autoRefresh = False
 
43
        bounds = drawAbstractFractal(
 
44
            fractalString,
 
45
            1,
 
46
            angle,
 
47
            (0,0))
 
48
        width, height = self.components.bufOff.size
 
49
        scale = min(
 
50
            (width - 2 * borderWidth) / (bounds[2]-bounds[0]),
 
51
            (height - 2 * borderWidth) / (bounds[3]-bounds[1]))
 
52
        startPos = (bounds[0] * -scale + borderWidth,
 
53
                    bounds[1] * -scale + borderWidth) 
 
54
        self.components.bufOff.autoRefresh = True
 
55
        self.drawFractal(
 
56
            fractalString,
 
57
            'blue',
 
58
            scale,
 
59
            angle,
 
60
            startPos)
 
61
 
 
62
        stoptime = time.time()
 
63
        self.statusBar.text = "Draw time: %.2f seconds" % (stoptime - starttime)
 
64
 
 
65
    def drawFractal(self, aFractalString, color, legLength, angle, startPos):
 
66
        self.components.bufOff.clear()
 
67
        t = BitmapTurtle(self.components.bufOff)
 
68
        t.color(color)
 
69
        t.lt(90)
 
70
        t.moveTo(startPos[0], startPos[1])
 
71
        for char in aFractalString:
 
72
            if char=='F':
 
73
                t.fd(legLength)
 
74
            elif char=='B':
 
75
                t.bk(legLength)
 
76
            elif char=='+':
 
77
                t.rt(angle)
 
78
            elif char=='-':
 
79
                t.lt(angle)
 
80
            elif char=='[':
 
81
                t.push()
 
82
            elif char==']':
 
83
                t.pop()
 
84
            
 
85
    def expand(self, fractalRules, iterations):
 
86
        lines = fractalRules.upper().split('\n')
 
87
        rules = {}
 
88
        for rule in lines:
 
89
            name, value = rule.split('=')
 
90
            assert(name=='AXIOM' or len(name)==1)
 
91
            rules[name] = value
 
92
        ret = rules['AXIOM']
 
93
        for i in range(iterations):
 
94
            l = list(ret)
 
95
            for pos, char in enumerate(l):
 
96
                repl = rules.get(char, None)
 
97
                if repl:
 
98
                    l[pos] = repl
 
99
            ret = ''.join(l)
 
100
        return ret
 
101
        
 
102
    def initSizers(self):
 
103
        sizer1 = wx.BoxSizer(wx.VERTICAL)
 
104
        comp = self.components
 
105
        flags = wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.ALIGN_BOTTOM
 
106
        # Mac wxButton needs 7 pixels on bottom and right
 
107
        macPadding = 7
 
108
        sizer1.Add(comp.btnColor, 0, flags, macPadding)
 
109
        sizer1.Add(comp.bufOff, 1, wx.EXPAND)
 
110
        
 
111
        sizer1.Fit(self)
 
112
        sizer1.SetSizeHints(self)
 
113
        self.panel.SetSizer(sizer1)
 
114
        self.panel.SetAutoLayout(1)
 
115
        self.panel.Layout()
 
116
 
 
117
    def on_btnColor_mouseClick(self, event):
 
118
        result = dialog.colorDialog(self)
 
119
        if result.accepted:
 
120
            self.components.bufOff.foregroundColor = result.color
 
121
            event.target.backgroundColor = result.color
 
122
 
 
123
    def openFile(self):
 
124
        result = dialog.openFileDialog(None, "Import which file?")
 
125
        if result.accepted:
 
126
            path = result.paths[0]
 
127
            os.chdir(os.path.dirname(path))
 
128
            self.filename = path
 
129
            bmp = graphic.Bitmap(self.filename)
 
130
            self.components.bufOff.drawBitmap(bmp, (0, 0))
 
131
 
 
132
    def on_menuFileOpen_select(self, event):
 
133
        self.openFile()
 
134
 
 
135
    def on_menuFileSaveAs_select(self, event):
 
136
        if self.filename is None:
 
137
            path = ''
 
138
            filename = ''
 
139
        else:
 
140
            path, filename = os.path.split(self.filename)
 
141
        result = dialog.saveFileDialog(None, "Save As", path, filename)
 
142
        if result.accepted:
 
143
            path = result.paths[0]
 
144
            fileType = graphic.bitmapType(path)
 
145
            print fileType, path
 
146
            try:
 
147
                bmp = self.components.bufOff.getBitmap()
 
148
                bmp.SaveFile(path, fileType)
 
149
                return True
 
150
            except:
 
151
                return False
 
152
        else:
 
153
            return False
 
154
 
 
155
    def on_menuEditCopy_select(self, event):
 
156
        widget = self.findFocus()
 
157
        if hasattr(widget, 'editable') and widget.canCopy():
 
158
            widget.copy()
 
159
        else:
 
160
            clipboard.setClipboard(self.components.bufOff.getBitmap())
 
161
 
 
162
    def on_menuEditPaste_select(self, event):
 
163
        widget = self.findFocus()
 
164
        if hasattr(widget, 'editable') and widget.canPaste():
 
165
            widget.paste()
 
166
        else:
 
167
            bmp = clipboard.getClipboard()
 
168
            if isinstance(bmp, wx.Bitmap):
 
169
                self.components.bufOff.drawBitmap(bmp)
 
170
 
 
171
    def on_editClear_command(self, event):
 
172
        self.components.bufOff.clear()
 
173
 
 
174
def drawAbstractFractal(aFractalString, legLength, angle, startPos):
 
175
    def recalcBounds(bounds, turtle):
 
176
        x, y = turtle.getXY()
 
177
        bounds[0] = min(bounds[0], x)
 
178
        bounds[1] = min(bounds[1], y)
 
179
        bounds[2] = max(bounds[2], x)
 
180
        bounds[3] = max(bounds[3], y)
 
181
        
 
182
    t = AbstractTurtle((1,1))
 
183
    t.lt(90)
 
184
    t.moveTo(startPos[0], startPos[1])
 
185
    bounds = list(startPos + startPos)
 
186
    for char in aFractalString:
 
187
        if char=='F':
 
188
            t.fd(legLength)
 
189
            recalcBounds(bounds, t)
 
190
        elif char=='B':
 
191
            t.bk(legLength)
 
192
            recalcBounds(bounds, t)
 
193
        elif char=='+':
 
194
            t.rt(angle)
 
195
        elif char=='-':
 
196
            t.lt(angle)
 
197
        elif char=='[':
 
198
            t.push()
 
199
        elif char==']':
 
200
            t.pop()
 
201
    return bounds
 
202
 
 
203
from PythonCard.tests import pyunit
 
204
 
 
205
class LSystemTests(pyunit.TestCase):
 
206
  def setUp(self):
 
207
    pass
 
208
 
 
209
  def tearDown(self):
 
210
    pass
 
211
 
 
212
  def testBoundsCheckBackwardMoves(self):
 
213
    bounds = drawAbstractFractal('BB+B', 1, 90, (10.0,20.0))
 
214
    # remember that down is positive in this coordinate system
 
215
    self.assertEqual([9.0, 20.0, 10.0, 22.0], bounds)
 
216
 
 
217
  def testBoundsCheckForwardMoves(self):
 
218
    bounds = drawAbstractFractal('FF-F', 1, 90, (10.0,20.0))
 
219
    # remember that down is positive in this coordinate system
 
220
    self.assertEqual([9.0, 18.0, 10.0, 20.0], bounds)
 
221
 
 
222
if __name__ == '__main__':
 
223
    app = model.Application(LSystem)
 
224
    app.MainLoop()