rexx-things/modules/windows/oodialog/oowalk2.rex
2025-03-12 20:50:48 +00:00

294 lines
11 KiB
Rexx
Executable File

/*----------------------------------------------------------------------------*/
/* */
/* Copyright (c) 1995, 2004 IBM Corporation. All rights reserved. */
/* Copyright (c) 2005-2014 Rexx Language Association. All rights reserved. */
/* */
/* This program and the accompanying materials are made available under */
/* the terms of the Common Public License v1.0 which accompanies this */
/* distribution. A copy is also available at the following address: */
/* https://www.oorexx.org/license.html */
/* */
/* Redistribution and use in source and binary forms, with or */
/* without modification, are permitted provided that the following */
/* conditions are met: */
/* */
/* Redistributions of source code must retain the above copyright */
/* notice, this list of conditions and the following disclaimer. */
/* Redistributions in binary form must reproduce the above copyright */
/* notice, this list of conditions and the following disclaimer in */
/* the documentation and/or other materials provided with the distribution. */
/* */
/* Neither the name of Rexx Language Association nor the names */
/* of its contributors may be used to endorse or promote products */
/* derived from this software without specific prior written permission. */
/* */
/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */
/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */
/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS */
/* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */
/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */
/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */
/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, */
/* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY */
/* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */
/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */
/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
/* */
/*----------------------------------------------------------------------------*/
/**
* oowalk2.rex Animation demonstration (using a compiled binary resource
* for the dialog template. A DLL file.)
*
* The only real difference between this sample and the oowalker.rex sample is
* the way the bitmaps for the animation are loaded. Look at the initDialog()
* method of the .WalkerDialog to see this difference.
*
* An animated button is used to simulate a man walking across the dialog. The
* user can adjust the pace of the waling by setting the amount the man is
* moved each time the button is redrawn and the delay between redrawing the
* button. The button is drawn using a sequence of bitmaps that show the man
* with different leg and arm positions. The user can also set how the man
* 'walking' off the edge of the dialog is handled, smoothly or bouncy, by
* using the "smooth corner wrap" check box.
*
* A 'got cha' point (!!!) is periodically drawn and if the man is close enough
* to this 'danger,' the man is 'gotten' and the animation is stopped. Each
* time the button is drawn, the !!! is over-drawn, so the !!! is only seen
* as a flicker.
*
* Normally the dialog ends when the walker is gotten. However there is a
* check box that allows the user to cancel this behavior and then restart the
* animation.
*/
srcDir = locate()
.application~setDefaults('O', srcDir'rc\walker.h', .false)
dlg = .WalkerDialog~new(srcDir'res\oowalk2.dll', IDD_WALKER)
if dlg~initCode \= 0 then do
mgr~goBack
return 99
end
dlg~execute("SHOWTOP")
return
/*---------------------------- requires -----------------------------*/
::requires "ooDialog.cls"
::requires "samplesSetup.rex"
/*---------------------------- walker dialog ------------------------*/
::class 'WalkerDialog' subclass ResDialog
::method initDialog
expose bitmaps spriteButton quitCheckBox restartButton okButton
-- Make button IDC_DRAW_BUTTON a bitmap button. Bitmap buttons are owner-
-- drawn and ooDialog will manage the 'drawing' of the button by painting a
-- series of bitmaps on the button, using the AnimatedButton class.
self~installBitmapButton(IDC_DRAW_BUTTON, '', 0);
-- The bitmaps are loaded from the resource DLL by specifying their resouce
-- IDs in the DLL file, res\oowalk2.dll.
--
-- We use symbolic IDs for the bitmaps, and we assigned the IDs in order.
-- In the new() method, the 2nd arg is the first bitmap ID and the 3rd is the
-- last bitmap ID and they are assumed to be in order. The AnimatedButton
-- class was never updated to accept symbolic IDs, so we need to convert the
-- IDs to numeric IDs
bmpFirst = .constDir[ID_BMP_FIG1]
bmpLast = .constDir[ID_BMP_FIG8]
spriteButton = .WalkButton~new(IDC_DRAW_BUTTON, bmpFirst, bmpLast, 10, 2, 70, 120, 60, 10, 10, self)
-- Use 'bouncy' operation when hitting edges.
spriteButton~setSmooth(.false)
-- Size of the step through the bitmap IDs.
spriteButton~setstep(1)
-- Get things set up.
self~connectButtonEvent(IDC_PB_RESTART, "CLICKED", onRestart)
quitCheckBox = self~newCheckBox(IDC_CB_GOTCHA)
restartButton = self~newPushButton(IDC_PB_RESTART)
okButton = self~newPushButton(IDOK)
quitCheckBox~check
spriteButton~fillData(data.)
spriteButton~suspendGotCha(.false)
self~doValueStemSet(data.)
ret = Play(srcDir"tada.wav", n) -- TODO not playing in Win7
-- Animate the button.
spriteButton~run
::method doValueStemGet unguarded
use strict arg data.
data.IDC_EDIT_MOVEX = self~newEdit(IDC_EDIT_MOVEX)~getText
data.IDC_EDIT_MOVEY = self~newEdit(IDC_EDIT_MOVEY)~getText
data.IDC_EDIT_DELAY = self~newEdit(IDC_EDIT_DELAY)~getText
if self~newCheckBox(IDC_CB_SMOOTH)~checked then data.IDC_CB_SMOOTH = 1
else data.IDC_CB_SMOOTH = 0
::method doValueStemSet unguarded
use strict arg data.
self~newEdit(IDC_EDIT_MOVEX)~setText(data.IDC_EDIT_MOVEX)
self~newEdit(IDC_EDIT_MOVEY)~setText(data.IDC_EDIT_MOVEY)
self~newEdit(IDC_EDIT_DELAY)~setText(data.IDC_EDIT_DELAY)
if data.IDC_CB_SMOOTH == 1 then self~newCheckBox(IDC_CB_SMOOTH)~check
else self~newCheckBox(IDC_CB_SMOOTH)~uncheck
::method onGotCha
expose okButton
use strict arg animatedButton, x, y
okButton~disable
self~writetoButton(IDC_DRAW_BUTTON, x, y, "Got-cha", "Arial", 28, "BOLD")
ret = play('gotcha.wav')
animatedButton~stop
call msSleep 1000
::method maybeQuit
expose quitCheckBox restartButton okButton
if quitCheckBox~checked then return self~ok
restartButton~enable
okButton~enable
::method onRestart
expose spriteButton restartButton
restartButton~disable
spriteButton~stopped = .false
-- Suspend the 'GotCha' before we start the animated button. Otherwise the
-- walker will be 'gotten' as soon as he starts.
spriteButton~suspendGotCha(.true)
spriteButton~run
-- Give the walker time to 'walk' out of the danger zone before reactivating
-- the 'GotCha.'
delay = self~newEdit(IDC_EDIT_DELAY)~getText
j = msSleep(2 * delay)
spriteButton~suspendGotCha(.false)
::method ok unguarded
self~stopAnimation
return self~ok:super
::method cancel unguarded
self~stopAnimation
return self~cancel:super
::method stopAnimation private
expose bitmaps spriteButton
spriteButton~stop
-- Wait until the animation sequence is finished.
do while spriteButton~isRunning
j = msSleep(30)
end
/*------------------------------ animated button --------------------*/
::class 'WalkButton' subclass AnimatedButton
::method run unguarded
expose xDanger yDanger running
xDanger = 300; yDanger = 70; running = .true
reply 0
do until self~stopped | self~parentStopped
self~doAnimatedSequence
end
-- Have the walker do one more sequence, gives the appearance of walking 'in
-- place.'
self~doAnimatedSequence
-- We are no longer running, tell the parent dialog to maybe quit.
running = .false
self~parentDlg~maybeQuit
::method doAnimatedSequence private unguarded
expose xDanger yDanger
self~parentDlg~doValueStemGet(data.)
do k over data.
if \ data.k~datatype('N') then data.k = 0
end
self~moveseq
self~setmove(data.IDC_EDIT_MOVEX, data.IDC_EDIT_MOVEY)
self~setdelay(data.IDC_EDIT_DELAY)
self~setsmooth(data.IDC_CB_SMOOTH)
if \ self~stopped then
self~parentDlg~writetoButton(IDC_DRAW_BUTTON,xDanger,yDanger,"!!!","Arial",20,"BOLD")
::method isRunning unguarded
expose running
return running
::method suspendGotCha unguarded
expose gotCha
use strict arg suspend
if suspend then gotCha = .false
else gotCha = .true
::method hitright
ret = play('ding.wav', 'YES')
return 1
::method hitleft
ret = play('ding.wav', 'YESY')
return 1
::method hitbottom
self~getsprite(s.)
ret = play('chord.wav', 'YES')
s.movey = -s.movey
self~setsprite(s.)
self~fillData(data.)
self~parentDlg~doValueStemSet(data.)
return 0
::method hittop
expose sprite.
self~getsprite(s.)
ret = play('chimes.wav', 'YES')
s.movey = -s.movey
self~setsprite(s.)
self~fillData(data.)
self~parentDlg~doValueStemSet(data.)
return 0
::method fillData
expose quitCheckBox
use arg data.
if \ quitCheckBox~isA(.CheckBox) then quitCheckBox = self~parentDlg~newCheckBox(IDC_CB_GOTCHA)
self~getSprite(msprite.)
data.IDC_EDIT_MOVEX = msprite.movex
data.IDC_EDIT_MOVEY = msprite.movey
data.IDC_EDIT_DELAY = msprite.delay
data.IDC_CB_SMOOTH = msprite.smooth
if quitCheckBox~checked then data.IDC_CB_GOTCHA = 1
else data.IDC_CB_GOTCHA = 0
::method movepos
use arg px, py
if \ self~stopped then do
self~movepos:super(px,py)
self~checkDanger
end
::method checkDanger
expose xDanger yDanger gotCha
self~getpos(cur.)
if abs(cur.x+10-xDanger) <= 10 & abs(cur.y+55-yDanger) <= 30 then do
if gotCha then self~parentDlg~onGotCha(self, xDanger-50, yDanger)
end