From bfd7bd588bf9e12b5cacb6629ef7d6e546162991 Mon Sep 17 00:00:00 2001 From: Robin Dunn Date: Fri, 12 Apr 2019 16:29:53 -0700 Subject: [PATCH] Add doodle sample --- .gitignore | 3 + samples/doodle/ChangeLog.txt | 61 + samples/doodle/README.txt | 21 + samples/doodle/doodle.py | 258 + samples/doodle/mondrian.icns | Bin 0 -> 41904 bytes samples/doodle/mondrian.ico | Bin 0 -> 766 bytes samples/doodle/sample.ddl | 8339 +++++++++++++++++++++++++++++++ samples/doodle/setup.py | 73 + samples/doodle/superdoodle.py | 434 ++ samples/doodle/superdoodle.spec | 48 + samples/doodle/tmp.ddl | Bin 0 -> 11023 bytes samples/doodle/version.py | 1 + 12 files changed, 9238 insertions(+) create mode 100644 samples/doodle/ChangeLog.txt create mode 100644 samples/doodle/README.txt create mode 100644 samples/doodle/doodle.py create mode 100644 samples/doodle/mondrian.icns create mode 100644 samples/doodle/mondrian.ico create mode 100644 samples/doodle/sample.ddl create mode 100644 samples/doodle/setup.py create mode 100644 samples/doodle/superdoodle.py create mode 100644 samples/doodle/superdoodle.spec create mode 100644 samples/doodle/tmp.ddl create mode 100644 samples/doodle/version.py diff --git a/.gitignore b/.gitignore index b690e33c..fa15edfc 100644 --- a/.gitignore +++ b/.gitignore @@ -63,3 +63,6 @@ mydbstub.py* ubuntu-xenial-16.04-cloudimg-console.log ubuntu-bionic-18.04-cloudimg-console.log .pytest_cache + +/samples/doodle/build +/samples/doodle/dist diff --git a/samples/doodle/ChangeLog.txt b/samples/doodle/ChangeLog.txt new file mode 100644 index 00000000..36dac8f6 --- /dev/null +++ b/samples/doodle/ChangeLog.txt @@ -0,0 +1,61 @@ +Recent changes for the SuperDoodle application +============================================== + +This is not a real change-log, but rather serves as an example that goes +along with SuperDoodle's example of self-updating functionality. To see it +in action download and unzip either the Windows or Mac version of +SuperDoodle 1.0.0 from http://wxPython.org/software-update-test/. When you +run the 1.0.0 version there will be a "Check for Updates..." item on the +help menu that you can use to see how the self-updating UI works. The +application will download the latest version available, install it, and +will restart SuperDoodle for you. Be sure to check the version numbers in +the About dialog before and after the update so you can see that it is +changing. (That is the only real change in each of the application +updates.) + +And now we return you to the totally fake change log, already in +progress... + + +Version 1.0.3 +------------- + * A little of this, a little of that. + * Fixed the foozlehopper. + * Added a whatsamagigit + * There's a wocket in my pocket. + + +Version 1.0.2 +------------- + * "I don't believe there's a power in the 'verse that can stop Kaylee + from being cheerful." + + * "Ten percent of nuthin' is...let me do the math here...nuthin' into + nuthin'...carry the nuthin'..." + + * "Well, what about you, Shepherd? How come you're flying about with us + brigands? I mean, shouldn't you be off bringing religiosity to the + Fuzzie-Wuzzies or some such?" + + * "Do you know what the chain of command is here? It's the chain I go + get and beat you with to show you who's in command." + + * "A man walks down the street in that hat, people know he's not afraid + of anything." + + + +Version 1.0.1 +------------- + * "Time is an illusion. Lunchtime doubly so." + + * "The ships hung in the sky in much the same way that bricks don't." + + * "Forty-two." + + * "Reality is frequently inaccurate." + + +Version 1.0.0 +------------- + * Initial release. diff --git a/samples/doodle/README.txt b/samples/doodle/README.txt new file mode 100644 index 00000000..18584d2d --- /dev/null +++ b/samples/doodle/README.txt @@ -0,0 +1,21 @@ +Doodle +------ + +This little sample is a doodle application. It shows you how to draw +on a canvas, deal with mouse events, popup menus, update UI events, +and much more. + + doodle.py A class for the main drawing window. You can also + run it directly to see just this window. + + + superdoodle.py Takes the DoodleWindow from doodle.py and puts it + in a more full featured application with a control + panel, and the ability to save and load doodles. + + setup.py This sample also shows you how to make your + applications automatically self-update when new + releases are available. There is a bit of code in + the superdoodle module to use the softwareupdate + module from the library, but the real magic + happens here in the distutils setup module. diff --git a/samples/doodle/doodle.py b/samples/doodle/doodle.py new file mode 100644 index 00000000..216de32f --- /dev/null +++ b/samples/doodle/doodle.py @@ -0,0 +1,258 @@ +# doodle.py + +""" +This module contains the DoodleWindow class which is a window that you +can do simple drawings upon. +""" + + +import wx + +#---------------------------------------------------------------------- + +class DoodleWindow(wx.Window): + menuColours = { 100 : 'Black', + 101 : 'Yellow', + 102 : 'Red', + 103 : 'Green', + 104 : 'Blue', + 105 : 'Purple', + 106 : 'Brown', + 107 : 'Aquamarine', + 108 : 'Forest Green', + 109 : 'Light Blue', + 110 : 'Goldenrod', + 111 : 'Cyan', + 112 : 'Orange', + 113 : 'Navy', + 114 : 'Dark Grey', + 115 : 'Light Grey', + } + maxThickness = 16 + + + def __init__(self, parent, ID): + wx.Window.__init__(self, parent, ID, style=wx.NO_FULL_REPAINT_ON_RESIZE) + self.SetBackgroundColour("WHITE") + self.listeners = [] + self.thickness = 1 + self.SetColour("Black") + self.lines = [] + self.pos = wx.Point(0,0) + self.MakeMenu() + + self.InitBuffer() + + self.SetCursor(wx.Cursor(wx.CURSOR_PENCIL)) + + # hook some mouse events + self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown) + self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp) + self.Bind(wx.EVT_RIGHT_UP, self.OnRightUp) + self.Bind(wx.EVT_MOTION, self.OnMotion) + + # the window resize event and idle events for managing the buffer + self.Bind(wx.EVT_SIZE, self.OnSize) + self.Bind(wx.EVT_IDLE, self.OnIdle) + + # and the refresh event + self.Bind(wx.EVT_PAINT, self.OnPaint) + + # When the window is destroyed, clean up resources. + self.Bind(wx.EVT_WINDOW_DESTROY, self.Cleanup) + + + def Cleanup(self, evt): + if hasattr(self, "menu"): + self.menu.Destroy() + del self.menu + + + def InitBuffer(self): + """Initialize the bitmap used for buffering the display.""" + size = self.GetClientSize() + self.buffer = wx.Bitmap(max(1,size.width), max(1,size.height)) + dc = wx.BufferedDC(None, self.buffer) + dc.SetBackground(wx.Brush(self.GetBackgroundColour())) + dc.Clear() + self.DrawLines(dc) + self.reInitBuffer = False + + + def SetColour(self, colour): + """Set a new colour and make a matching pen""" + self.colour = colour + self.pen = wx.Pen(self.colour, self.thickness, wx.SOLID) + self.Notify() + + + def SetThickness(self, num): + """Set a new line thickness and make a matching pen""" + self.thickness = num + self.pen = wx.Pen(self.colour, self.thickness, wx.SOLID) + self.Notify() + + + def GetLinesData(self): + return self.lines[:] + + + def SetLinesData(self, lines): + self.lines = lines[:] + self.InitBuffer() + self.Refresh() + + + def MakeMenu(self): + """Make a menu that can be popped up later""" + menu = wx.Menu() + keys = list(self.menuColours.keys()) + keys.sort() + for k in keys: + text = self.menuColours[k] + menu.Append(k, text, kind=wx.ITEM_CHECK) + self.Bind(wx.EVT_MENU_RANGE, self.OnMenuSetColour, id=100, id2=200) + self.Bind(wx.EVT_UPDATE_UI_RANGE, self.OnCheckMenuColours, id=100, id2=200) + menu.Break() + + for x in range(1, self.maxThickness+1): + menu.Append(x, str(x), kind=wx.ITEM_CHECK) + + self.Bind(wx.EVT_MENU_RANGE, self.OnMenuSetThickness, id=1, id2=self.maxThickness) + self.Bind(wx.EVT_UPDATE_UI_RANGE, self.OnCheckMenuThickness, id=1, id2=self.maxThickness) + self.menu = menu + + + # These two event handlers are called before the menu is displayed + # to determine which items should be checked. + def OnCheckMenuColours(self, event): + text = self.menuColours[event.GetId()] + if text == self.colour: + event.Check(True) + event.SetText(text.upper()) + else: + event.Check(False) + event.SetText(text) + + def OnCheckMenuThickness(self, event): + if event.GetId() == self.thickness: + event.Check(True) + else: + event.Check(False) + + + def OnLeftDown(self, event): + """called when the left mouse button is pressed""" + self.curLine = [] + self.pos = event.GetPosition() + self.CaptureMouse() + + + def OnLeftUp(self, event): + """called when the left mouse button is released""" + if self.HasCapture(): + self.lines.append( (self.colour, self.thickness, self.curLine) ) + self.curLine = [] + self.ReleaseMouse() + + + def OnRightUp(self, event): + """called when the right mouse button is released, will popup the menu""" + pt = event.GetPosition() + self.PopupMenu(self.menu, pt) + + + + def OnMotion(self, event): + """ + Called when the mouse is in motion. If the left button is + dragging then draw a line from the last event position to the + current one. Save the coordinants for redraws. + """ + if event.Dragging() and event.LeftIsDown(): + dc = wx.BufferedDC(wx.ClientDC(self), self.buffer) + dc.SetPen(self.pen) + pos = event.GetPosition() + coords = (self.pos.x, self.pos.y, pos.x, pos.y) + self.curLine.append(coords) + dc.DrawLine(*coords) + self.pos = pos + + + def OnSize(self, event): + """ + Called when the window is resized. We set a flag so the idle + handler will resize the buffer. + """ + self.reInitBuffer = True + + + def OnIdle(self, event): + """ + If the size was changed then resize the bitmap used for double + buffering to match the window size. We do it in Idle time so + there is only one refresh after resizing is done, not lots while + it is happening. + """ + if self.reInitBuffer: + self.InitBuffer() + self.Refresh(False) + + + def OnPaint(self, event): + """ + Called when the window is exposed. + """ + # Create a buffered paint DC. It will create the real + # wx.PaintDC and then blit the bitmap to it when dc is + # deleted. Since we don't need to draw anything else + # here that's all there is to it. + dc = wx.BufferedPaintDC(self, self.buffer) + + + def DrawLines(self, dc): + """ + Redraws all the lines that have been drawn already. + """ + for colour, thickness, line in self.lines: + pen = wx.Pen(colour, thickness, wx.SOLID) + dc.SetPen(pen) + for coords in line: + dc.DrawLine(*coords) + + + # Event handlers for the popup menu, uses the event ID to determine + # the colour or the thickness to set. + def OnMenuSetColour(self, event): + self.SetColour(self.menuColours[event.GetId()]) + + def OnMenuSetThickness(self, event): + self.SetThickness(event.GetId()) + + + # Observer pattern. Listeners are registered and then notified + # whenever doodle settings change. + def AddListener(self, listener): + self.listeners.append(listener) + + def Notify(self): + for other in self.listeners: + other.Update(self.colour, self.thickness) + + +#---------------------------------------------------------------------- + +class DoodleFrame(wx.Frame): + def __init__(self, parent): + wx.Frame.__init__(self, parent, -1, "Doodle Frame", size=(800,600), + style=wx.DEFAULT_FRAME_STYLE | wx.NO_FULL_REPAINT_ON_RESIZE) + doodle = DoodleWindow(self, -1) + +#---------------------------------------------------------------------- + +if __name__ == '__main__': + app = wx.App() + frame = DoodleFrame(None) + frame.Show(True) + app.MainLoop() + diff --git a/samples/doodle/mondrian.icns b/samples/doodle/mondrian.icns new file mode 100644 index 0000000000000000000000000000000000000000..43fbff2c4c3e888b9a36eaf5f6dde53ba6fd9871 GIT binary patch literal 41904 zcmeG^3tUWT`zIk$$*$e~u$GPe_G2b8(=J)7tZA*>sixZuWx7miL$Pjg-sxf{n%N>M zB_Wh9l!PvukhPkXN>(+wl$D76e1BBZ`9J5(rHNQ}?dtn}=gcbovl*J;t!1xfnLK3B!0f7#3BH=~y&j1Fz>`Hi<<0xF3+t z;yDProPl~tw;)}f4eA~F3F_??iS!@Zpk9`~sBga$XkgDv2*XU^?^F2uSo22^*AZq2 ze@2ODI)iMxB4gQg)U$6QIriJWgo}O5F{}q=2W?&c!)9Az>PvTW|4#7UiTAZ(qf;rJ z;A@Jc4t|3Y#gHGaX<&nr4?q4X9n-)i%re82Ygm8P*lo1dO4xuo`EXS_v&dcr8x}PU{h=mDwO=Wsity8k%4K+9VOg% zzTBjwG_S-|MVFh_-ODN~DpJ%a>G`>e^z`)ne1;M>s8(P-tI|_a_;QMFR70wC{?dtb z6~D?rzZpIQ_rIr0~5Uj^3K|2HN70P1RviRlElNF<%%=x69Lo$1Y8(lukL8sG;L zFs$cue()?GF@m}X)y%YS)h2Bi@nU-Q$4jc)UQ9=fswJ5(ra#fOLrlCp zlVmaU7G1Sqvrt)C8KEL5Z_GYyftU}yv-kowiwz8&=#TnX@TlI`#A3b$n+Xy+(H~pz zrK0{^G4WKuXLF5MFhq;Cd<%Cm+ky>(xhx~55sPVLig?=ehi&3MEFRCCWz>gh#Dwmw zRtIf5!@*o2u9d*xJfMLbev7R(oyX>hT6r5K(o{*Rm@nY-1oql=Cfdlg$FN5%B+0Cm zWQtS8;+AHu{>Yx8G}fcXEFR)N5sTaG?X~DiqUIYYJg#3^p-Uqlya1il+bf3I4HGNf#F0SL3@PITFopb z3~yXNe=M>6up8i15<-c-H-5c+|5!r%Nx; zZZCGTE_Dr}Mh_wkt8P|gdB(Q?=w_XCuH02bp+!Xhni~~+g*zXdbF*H(qo}OZ6;T94 z3}{f4WqI%V&smotJV{)({8G6qt|AS*S`_ELrZ&slaJVQf|J21xmrI3WH7y-2J$~lo z&u23;s%|x2zw*nK3Sp?4cF$$Sor;94)3vwm-l?lsRQ_DNJWfq3-hEc=H_O#;!}nWH zR+pSC%sD99t)|8NknR!|;yZV?le3+VY}4i_v1~6z!-@BP@>sVyfgozKMe}T?TFzL& z_gW;|ry}<7NGJ*-3~Ejt2oGNC*!I7BG;N>6=AuQ;KYl<4J|hv^K0W;oH?qdtDwAd*2$^gCCue}|}E z!T}f%;2Rf?9?#vex_%2_aKM0DWTqa?-Vs>89WazzWMu66b{<|I%Nex8P2(1sS=+tF ztgMgc3|hP`(M{tP1&3l5n61AM_w^ui$4&d<+%#@+?Qn$WnDwQx9HY^b?AGo&u-i@J z7H3w@FrAkjI;W?Rxho1wIIus_YaL}%L=0SRIx#RbC?B%W6NnY#Kv|CU&v701;D@3ts+P9l~+b68|2RX%v&7Dqgs5V%EUg7b(W?-~zhuqTa|?xH&4gvu={k4E}=I8U2C?hC2X zVU%vMTzZh=Q$l~-Eig>9R?B-N;7V@}p>mi0Q&sNr!PNKrE8WHY^!xn>E8WG;bHC4E zmAm96M{b$yIco&KN_Q!ajgHPrBl)FUALb=l{Jm-%Xyrv_H zL`AHdH=5pYVI zBUzSC9cEAdaqm=6tpT}b8LKsRJvI# zv{NtsEfceCTNl_a#G`iajE&zaMr-_)4=~6q{(9bL69x?%{W-^GMFjF+?zIRJs(yVO zy{DUe=QU~YQ2bwgCd``l&75gcB@LYBfV<5GaGLU1yAKB%^&9d}2HQ-k^fquBcPf^Y zXG(<&?Z2AJ_)MCh>k+hj31K7OBeU+#Axz); zq+%&Ha=UKsA#BPRL=f$tI}-KTcC$X)fE#0ns(vUm>tz=(7B}uuSCvy}_TG%_Ik<7Z z?G>LCn!TTrY=aw{TK9}9G#hL_e>84v=p=cs(CnS2BPqBsWBd|Z;Gg~UIBx8%TX46~ z%nJLY3O62(Ef`g323m!Id`#y9sx6_~x>Or=Y7c{%=@x!w$0bO-uCHz(%Vb0~wDF)E z;P2Uwhwy>My7!?yWkfE;qkwksySb>U;Le5nIsa43{g+J!{0Qn#139~{ovedB!*6i6cH+G*`0oxq zlm49i!jh6A`MsvntDWVSlrVEY9Fx+7b=Ie(N00L-a~tnrSSS9HqQbn3%-nPZ;I;KB z8D1nm-0wtsDd4s2bC+3^|8dcYv}!235$&X9?vr0t@*dT>c|!_rC>lK;5l=}ITqVB@ zhUa~f`(Z&!eoeK9hhGQ2sN{0;DUp{o9zNgL z{zX|0bm)*%RF=(9Fo?!-MOg{+yh0;i&bV=RX!V^YQ+Wxqq_zWpq;Xc+X}N+4*rFnN zu7=<6U|vl=lUY(zadl ziZP0+#zv>c{M^jiS#mXhVLqd}L|$<(B|W7eyP$*Luv!5{LV0d_N@GgOohA*xqNb2C z-f2bC9p|J}jeLU=5{(tY!vB;9ebw?Qtn#aWslf~IhUxdZ=C8ThB_3Ar&EmDZ2%4l{ zDdp#?FQTQTMGLR2Xu>xXF(tAN{tkRhOiV%-cmnvl!nZ`n#B?QxkVJPWrzJ)b-IW|d z64SN(m}sSZ<#VB)RxS|(^J;=8rLzS(Ac#XyPu2hZdTK`(Wh<+?M)|2FT3TQDX%W{} zXFhF(dTF(?AUk424eUr>e6gxO7PMilP-al`SHFyZiMNUOk|k|VUrqj_W}fBOOS}~% z|EtJHfSJym!Mfp#-y7p_(Q*j&C@^bk)kM#5y3?|!@-70Dmqh@lxFR{-fJtmZn zxqMx7wgjrj&DhK2Khz^j#ZYNB*JV3MGE=E?@r&i_F_&WBFM`S^CMnqOUt z#`Ku|p>!;eI+*LT`C`dacOI0Jp;nzzRtAs9bMhZTy&j6{B0ek=UzC;!6>s_cBezA04c+a+QFRKr=OU@O$6d?w3+FBU^xozE8$nb)9fO%=(ZK+Z<3 zEzj#uvI_(bP)O(UL}C#S8Z4;ALqVL0c&*Rt&*KZkJoW_k1ejwB+XYscEWYcrOpRCw zIXo|4$6g}l^0^Z(9_ zDoDi!&-*j>?~)tNA(U(oPyR;v>JZb_U8zQA{ev8z{Sdb=Hc+1~_18W#QMQSTZk?|bGlmJF7$!(xMzY%OHI@tT*=i#$&<8kCM3C;8+Zye^%PKokQSiOf=C~mfv_VUdl01qqY$Sm1+BrpN|jr?u1NpD#$)4 z^|tOnMiGXB!|f4)LTfm9(ufQv-fRB%Z+C9iRF)n-^UE3`*E(Q#C+fd%T(3NTEG@D9 zm&0zh)|}l$2Q`c^{`ZYv8*bmPIF@js{bZyYNJfONMz(|)aJQkZ;dWz1Vd{lnu1EUY zg7D4^##gS^-)_8fEH$D1`YB4jh`{iz*gHO#>#ow-{M3q+6Z4IzpktmP#7#FNIN+=YjuidOTo#lyQ+v|P=xk)+a%41zM48g=d z?$z9=uGqU#xbw#c=eD_7FI>GNqp0j63?ouY2_gpn-)%+Jh0_~DL(Y{ewg@ff2~k{X zUTIl53B+R1MFOw%yq_w{%Pv)3{^e4c zaMi{RzVv9cH0t=7Qzw5ue>U@QM%DFOjlW*M0ta)KD}<{;JNWJ;xvV&Jr{Y9HR^I8_ zx?6Y2Bf5G;Rprk=6))cy*TGknwqa-LiQSu5hDF9^9L*~{UwO6WmkaXqrwWd*2~X(Y zD?YOO>;bVKf0nD4-v;sbTMwSBt|&PP2YZJPiXwM+@WrJ5kRIX^CJymkICr+Kle2@J z&w4oH+Z-hm%VPJc_z>~&gPXW)XS{U%nbSo{TZ6n7+Ao+p)85V3Z~2N1YXW4kNg7VQ zn?HFhTeo>z0#3YNb1qxtJj_3mo}gf<>|&`!t+AvpfMe zU+cBR*U5!1OUUTpxsnB52|V{2u2;y5iwg72R~$`~EtMr^s(9de!*GHqM6%u48dNV5 z6=8yNbTlZ6>&J-QZYCNO5Jg&#LNuH^z77JzW5K_)CCKoN&tiz~f>A~=N<%9Vj#;H+ z$045eo}z;dfOr-Lk*qhagPB0s3B#fZJ^fx#7u4aHgkjqV{VQ3ES(uKVp$g3M%;RG^ zhJ#2jisrSNx{*aoP%+jGja-iW{(9? zYLangM(R;GU)>y7U$C8$riw`p85sw5eY?F3#~I|b!>vl~YzALDcQ|65=NS9- zrP;BZQAVTLlkB|K?%I1`w+K#rRc;zY3_G)P<%~(D^MbNNm(1y@Z)85h6@`W+>^-o5 zZ=%=obscC^VJ*|JFdebXFKV(ohm+v zNljJWe*S39@)O6hrK?;m%}4!nGoY3nVOhXS$s4S`FXfHPy1&2xX-_k#%jeabxgWbSADK9 zC+kq!NWtFdRa|LYvPzCBCLLccjX$VCy|tL6gAEIw{7h(*L9Ck`y!O8UtBzZ$S!l&B z9ZnzIL`N07Ho{@NI(B_vI`#c``>SJD=C`v=-yQg#3e0pr?fZWJ_XewCmmS}8f0)l; zP3*c~TXEssxg!aD7bkbysU5MaHZOT+TwMvq~6@)m&T z8E&hBmb+@FbHT(%70H`|1E-8mjYQF^Cx0RJ>EPQfSU* z&0OI01!KstPse^`=ZSCB3y3__kzPV{syZ6E%ER{4vEyAG=a~#1Fp|NtoVzGk5*`}h z+KDem;yj7OE-myg+6|&$0>;DEl z#oM+9EUMt47_DF9@51TeyBumh#n!`P_U99=tepkEEAg;xTV%l~ zaK$p;HBzmFsW|lOc~d`|Flx}SPey{VJ7*=t>-N9yqjErIBIk9#Y9}XN~)bHIP{~X0&v&^Jh)$tP%Ju}^v zc~$wTOzAq|LT7kkVk*PzGwq1j^Gc>NueyEx%GrV=8EFSUc1?`(pDT^oqZ&~a!?Kr1 zckI`o-bM_2Ce3;)AOs=I3bH*_^zouz{P+U}^4Hve((JSaXbaF5pe;aKfVKc_f$nAj z;bMPy@eTXtA-7cbkil=GqPWJ{LGz81f}D(@m}J~D{J1ewWWfvkJ-tB=y!eEPQ!Ev5 z)uyxA0Ac+s_e_LaNq!RvmlPEkHq|N=jG_5{rG}Wi?4Ieba4%CFDKUk+A~&x{4)(l?&z_=FEsERlpmp;Y;!o3hmlCrA~7aUAQdY~n$% z?R>UPsucu0J*;pmgoWZgrVN042%&q0r3e4+RYdfDaOG^evk*t{&q?}~B@89Q7DNDrrJ1tlnlNKwHP;isqnq#ZX zN19Ky*-pXKWa(OA2xZiW;Xhh*RFjQP|l|pu&F1+F;Puu_CV!??q4|K zVyl`^Ud(!1M#qHwR$FpS?dQWvQL9tDlD&ZOsolm%(vt9>yA|JUiV)u%=A(o|ZD(5v z@GWSWl!6<1i;pcEGn8RrnNGpfgsvB)x%$VDu=a%1%MhwrkY`)uL_(=$@uxOb%74}T zdjaErnJ!%HO9s^m59XBiIAm()jFR4&FZ$BB2j1(wRbq?zX)l^P^dp0)*B(nbTtB7n zp@L||J@!Nho)_~C@7Bs|OvmJs!Sj43y#59EGKHcB?glj_S-D>-gQSsmupE-B6)c;6 zKAd})*!eSz13?n|QBk!-(QL2!h^46z1XV#1!&p4=69|%2(1cfJ%=u3qwmz|MZUb%z zisoW2@BY7)K@8qtVW;vfSnPw!Al3r!bHHmO@OlbGf5c-wvPb0m7tKmKj0_PPYiXu} z90ieItr!_ZTO6qi4t^o1L4Qrqy9q(B&A$1Gihir%iTx8{02$;)I+5K8>hlCnGZ1!; zKvL9*ppqBzhu|~tPurmXL6E{xO88@#lLT@?1(Y0XwWL3T%O{WkwWA0mL?BN+yFZUj zCeRIZ9i2zVP$I}bjNC~1Au8+rb<{+1++WdcbRR}efRRrsN0z8Y{;TQn1iFIiVf;I) z@lPqo4_A%<*U|GabQ#s5T66+DZ8yxkm>Rhhxys)tC5rNYcqXdQO;mxh5FFLRXg^Y; zC82Yu9JxmP?K}|#s)3cSKzqTHccKTN2kCLE(GFCE$`Du~oYLuS@r4tp0VzO}EaZ)L zq5q(>$OR2SJS0JJC>zPqCDLvZO2=-(dlf7PZ#|$j;8Ud5hG;kvp){0_PN9pS?`5#6 z5Q&jm=kCUzju2Xkj-xXW1AYd3XQB-7*;^2WufsF?3;b1p{-GNEyBq&K@Q@V{M=BtW zWueos3b)W*fa@T>C{QKLsTeJX6;j*3yYUx86gmt3;fH1+SNPt5zDHYOEviuod>5h| z_!ScYk6Qok#vg-zK@JLCiLbraf*qF`<^h&O8eyA{8LKtCZ5 zv<~!42q9x*HrRR|vO!akC7OX2AU^U!i$MQ~x7(Jh#(&WrVQEB+Mn}4> z+zBY{px$jL?*tY_?m2Xz@&H+R;w!ab{q;jI=)+0GUZoBD22Yd+Bj}((WS`fCVVB?m zzeVwA8QGuI@{eI)H*gO2H2Wb}6M;Ml$O3sGAn(mmAost3jzUI|3nQ(Dk+vvDlE6rR z1r2ijOq2>EX2W=aFy40Mc;PVKo2TVtAsLWaehX0^hp}R*v34Lg`5VG(^8QT7Mz%vF z9)niGIPugti_tdN=ecR}{=ba}^7#UE2*toJni*OT>l=r@2JbOPj_@134IhnS$T5K+dUuV4;#$N_R?JDAH( zjrQGy8}jxe@GI;DPbZn@SHctOj7C6Z;ay}5`*j9lL!=oGn(tC--VOQH`Fkb&Qo`G{ zFdJty4NXVm&=;V0$NuE4@R2z+*mXH*a!_f(KZSX%ydK8w#Q%14dqn1xzmwmq^L{eV zM_9yKH9rmiefH>bAJHH7{px+h@3vu`KLGysQGeA=;uRs-Ke$7kitIO7wV!w`7K26hd3@GBY#`Tb;&Hw)q+$W!en-XI0`48#HX!a9P zkR7jsY;!bX!DtJp(Pp4kkWIL%Pi>$I^fz}Y}pfUYd4^DTm!SvagDyz8&5G;}NO9Qd7|1X`QH zUdzb`TX`_6$F;sY6bIAo0CPUj2Vjo%gWtFg#CWMxPY*gpXF8L^PFM}$bBMQU!R z$rax&=PmFEGuWSR1s}FW3&D4zV9&Xe(snCoir|FDAN*RKmv=Y*V%X8oL!ZIkXb>6( ze)2i!Y6E+T2+-UgGBdJ{jS%D;gtN2hum<0OrjsCs43+!~<}wSS>o?%- z(;%{U=>FDuVSjJ{ov;}Aj&=#OAKwE&e0Br%<0<;Ba3(yvzEkIj< zwg7Db+5)r%XbaF5pe;aKfVKc_0onqz1!xP<7N9LaTY$CzZ2{T>v;}Aj&=#OAKwE&e z0Br%<0<;Ba3(yvzEkIj + +
+ + + +

SuperDoodle %s

+
+

SuperDoodle is a demonstration program for wxPython that +will hopefully teach you a thing or two. Just follow these simple +instructions:

+

+

    +
  1. Read the Source... +
  2. Learn... +
  3. Do! +
+ +

SuperDoodle and wxPython are brought to you by +Robin Dunn and Total Control Software, Copyright +© 1997-2011.

+ + +''' + + def __init__(self, parent): + wx.Dialog.__init__(self, parent, -1, 'About SuperDoodle', + size=(420, 380) ) + + html = wx.html.HtmlWindow(self, -1) + import version + html.SetPage(self.text % version.VERSION) + button = wx.Button(self, wx.ID_OK, "Okay") + + # constraints for the html window + lc = wx.LayoutConstraints() + lc.top.SameAs(self, wx.Top, 5) + lc.left.SameAs(self, wx.Left, 5) + lc.bottom.SameAs(button, wx.Top, 5) + lc.right.SameAs(self, wx.Right, 5) + html.SetConstraints(lc) + + # constraints for the button + lc = wx.LayoutConstraints() + lc.bottom.SameAs(self, wx.Bottom, 5) + lc.centreX.SameAs(self, wx.CentreX) + lc.width.AsIs() + lc.height.AsIs() + button.SetConstraints(lc) + + self.SetAutoLayout(True) + self.Layout() + self.CentreOnParent(wx.BOTH) + + +#---------------------------------------------------------------------- +#---------------------------------------------------------------------- + +if not USE_SOFTWARE_UPDATE: + SoftwareUpdate = object + + +class DoodleApp(wx.App, InspectionMixin, SoftwareUpdate): + def OnInit(self): + if USE_SOFTWARE_UPDATE: + BASEURL='http://wxPython.org/software-update-test/' + self.InitUpdates(BASEURL, + BASEURL + 'ChangeLog.txt', + icon=wx.Icon(os.path.join(HERE, 'mondrian.ico'))) + self.Init() # for InspectionMixin + + frame = DoodleFrame(None) + frame.Show(True) + self.SetTopWindow(frame) + self.SetAppDisplayName('SuperDoodle') + return True + +#---------------------------------------------------------------------- + +if __name__ == '__main__': + app = DoodleApp(redirect=False) + app.MainLoop() + diff --git a/samples/doodle/superdoodle.spec b/samples/doodle/superdoodle.spec new file mode 100644 index 00000000..9332e002 --- /dev/null +++ b/samples/doodle/superdoodle.spec @@ -0,0 +1,48 @@ +# -*- mode: python -*- +# +# This is a spec file for PyInstaller. To make a binary distribution of the +# superdoodle application run a command like this: +# +# pyinstaller superdoodle.spec +# +# And then look in the ./dist folder for the results +# + +block_cipher = None + + +a = Analysis(['superdoodle.py'], + pathex=['.'], + binaries=[], + datas=[('mondrian.ico', '.')], + hiddenimports=[], + hookspath=[], + runtime_hooks=[], + excludes=[], + win_no_prefer_redirects=False, + win_private_assemblies=False, + cipher=block_cipher, + noarchive=False) +pyz = PYZ(a.pure, a.zipped_data, + cipher=block_cipher) +exe = EXE(pyz, + a.scripts, + [], + exclude_binaries=True, + name='superdoodle', + debug=False, + bootloader_ignore_signals=False, + strip=False, + upx=True, + console=False ) +coll = COLLECT(exe, + a.binaries, + a.zipfiles, + a.datas, + strip=False, + upx=True, + name='superdoodle') +app = BUNDLE(coll, + name='superdoodle.app', + icon='mondrian.icns', + bundle_identifier=None) diff --git a/samples/doodle/tmp.ddl b/samples/doodle/tmp.ddl new file mode 100644 index 0000000000000000000000000000000000000000..ae6b3e98b139575be604b73869fb77ed23b7af27 GIT binary patch literal 11023 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 Xq60TArPh~M8_KJVQ1}NAThaReAUci2 literal 0 HcmV?d00001 diff --git a/samples/doodle/version.py b/samples/doodle/version.py new file mode 100644 index 00000000..0c2831a5 --- /dev/null +++ b/samples/doodle/version.py @@ -0,0 +1 @@ +VERSION='1.0.3'