; ; dbx.slider.s ; ; Implementation of sliders as a dbx control ; ; © 1994 Straylight ; ;----- Standard header ------------------------------------------------------ GET libs:header GET libs:swis ;----- External dependencies ------------------------------------------------ GET sapphire:dbox GET sapphire:divide GET sapphire:idle GET sapphire:win GET sapphire:msgs GET sapphire:screen GET sapphire:winUtils GET sapphire:dbx.dbx GET sapphire:dbx._dbxMacs ;----- Main code ------------------------------------------------------------ AREA |Sapphire$$Code|,CODE,READONLY slFlag_vertical EQU (1<<8) slFlag_horizontal EQU 0 slFlag_colData EQU (1<<9) ; --- slider --- ; ; Control data: +0 == slider colour (if flags bit 9 clear) ; +1 == background colour ; +2 == separator colour ; +3 == reserved ; +4 == maximum slider value ; +8 ; ; Workspace: +0 == current slider value ; +4 == slider colour (if flags bit 9 set) ; +5 == reserved, must be 0 ; +8 ; ; Flags: Bit 8 == slider is horizontal if clear, vertical is set ; ; Use: Control type for a slider. EXPORT slider slider ROUT DBXWS slider__wSpace DCD dbxMask_click + dbxMask_redraw CMP R0,#0 ;Is this a click event? BEQ %50slider ;Yes -- handle it ; --- Handle a whole slider redraw operation --- STMFD R13!,{R0-R2,R6-R8,R10,R14} ; --- Get a colour mask --- ; ; We use RISC OS 3.5's peculiar shading algorithm -- clear ; all the colour bits except 1! This is easy -- we just ; set up an AND mask in R10 at the start. MOV R0,R10 ;Get the dialogue box handle BL dbox_window ;Translate to window handle BL winUtils_shaded ;Is the icon shaded, please? MOVCS R10,#2 ;Yes -- leave only bit 1 MOVCC R10,#&FF ;Otherwise leave colour alone ; --- Sort out what needs doing --- LDR R6,[R9,#-12] ;Locate the flags word TST R6,#slFlag_vertical ;Is the slider vertical? SUBNE R7,R5,R3 ;Yes -- calculate the height SUBEQ R7,R4,R2 ;No -- calculate the width ; --- Work out the length to draw out --- LDR R0,[R8,#0] ;Load the slider value MUL R0,R7,R0 ;Multiply the value up LDR R1,[R9,#4] ;Get the slider maximum val BL div_round ;Calculate correct length MOV R6,R0 ;Look after the quotient MOV R7,R2 ;Keep the left hand edge BEQ %10slider ;If slider not vert, skip ; --- Now draw a vertical slider --- LDR R14,[R9,#-12] ;Locate the flags word TST R14,#slFlag_colData ;Is the colour writable? LDREQB R0,[R9,#0] ;Get the slider colour... LDRNEB R0,[R8,#4] ;... from wherever it is AND R0,R0,R10 ;Mask colour for shading SWI Wimp_SetColour ;Start in this colour BL screen_getInfo ;Get some screen information LDR R8,[R0,#screen_dy] ;Load the y pixel size MOV R0,#4 ;Move absolute coordinates MOV R1,R7 ;Left hand side of control MOV R2,R3 ;Bottom edge of control SWI OS_Plot ;Move graphics cursor there MOV R0,#&65 ;Rectangle fill absolute MOV R1,R4 ;Right hand side of control ADD R2,R3,R6 ;Top of the slider bar SUB R2,R2,R8 ;Allow a bit for the crossbar CMP R2,R3 ;Is there any slider bar? SWIGE OS_Plot ;Fill in the slider bar LDRB R0,[R9,#2] ;Get the separator colour AND R0,R0,R10 ;Mask colour for shading SWI Wimp_SetColour ;Use this colour now MOV R0,#4 ;Move cursor absolute ADD R2,R2,R8 ;Top edge of slider bar SWI OS_Plot ;Move the cursor there MOV R0,#5 ;Draw line absolute MOV R1,R7 ;Left hand side of control SWI OS_Plot ;Fill in the middle bit LDRB R0,[R9,#1] ;Get the background colour AND R0,R0,R10 ;Mask colour for shading SWI Wimp_SetColour ;Use this colour now MOV R0,#4 ;Move cursor absolute ADD R2,R2,R8 ;Top edge of slider bar SWI OS_Plot ;Move the cursor there MOV R0,#&65 ;Rectangle fill absolute MOV R1,R4 ;Left hand side of control CMP R2,R5 ;Is there anything to draw? MOV R2,R5 ;Top of the control SWILE OS_Plot ;Fill in the background bit B %90slider ;Skip to the end now ; --- Now draw a horizontal slider --- 10slider LDR R14,[R9,#-12] ;Locate the flags word TST R14,#slFlag_colData ;Is the colour writable? LDREQB R0,[R9,#0] ;Get the slider colour... LDRNEB R0,[R8,#4] ;... from wherever it is AND R0,R0,R10 ;Mask colour for shading SWI Wimp_SetColour ;Start in this colour BL screen_getInfo ;Get some screen information LDR R8,[R0,#screen_dx] ;Load the x pixel size MOV R0,#4 ;Move absolute coordinates MOV R1,R7 ;Left hand side of control MOV R2,R3 ;Bottom edge of control SWI OS_Plot ;Move graphics cursor there MOV R0,#&65 ;Rectangle fill absolute ADD R1,R7,R6 ;Right of the slider bar SUB R1,R1,R8 ;Allow for the crossbar MOV R2,R5 ;Top edge of the control CMP R1,R7 ;Is there anything to draw? SWIGE OS_Plot ;Fill in the slider bar LDRB R0,[R9,#2] ;Get the separator colour AND R0,R0,R10 ;Mask colour for shading SWI Wimp_SetColour ;Use this colour now MOV R0,#4 ;Move cursor absolute ADD R1,R1,R8 ;Top edge of slider bar SWI OS_Plot ;Move the cursor there MOV R0,#5 ;Draw line absolute MOV R2,R3 ;Bottom edge of the control SWI OS_Plot ;Fill in the middle bit LDRB R0,[R9,#1] ;Get the background colour AND R0,R0,R10 ;Mask colour for shading SWI Wimp_SetColour ;Use this colour now MOV R0,#4 ;Move cursor absolute ADD R1,R1,R8 ;Top edge of slider bar SWI OS_Plot ;Move the cursor there MOV R0,#&65 ;Rectangle fill absolute CMP R1,R4 ;Is there anything to draw? MOV R1,R4 ;Right hand side of control MOV R2,R5 ;Top of the control SWILE OS_Plot ;Fill in the background bit 90slider LDMFD R13!,{R0-R2,R6-R8,R10,PC}^ ; --- Handle a mouse click event --- ; ; We start a slider drag operation 50slider TST R2,#5 ;Is this a real mouse click? MOVEQS PC,R14 ;No -- then ignore it STMFD R13!,{R0-R3,R14} ;Save a few registers ; --- Save the slider information away --- MOV R0,R10 ;Get dialogue handle in R0 BL dbx_controlBBox ;Get the control position STMIA R12,{R1-R5,R8,R9} ;Save the state in workspace ; --- Start a drag operation --- SUB R13,R13,#56 ;Make way for a drag block MOV R1,R13 ;Point to the block SWI Wimp_GetPointerInfo ;Get the pointer position LDR R7,[R9,#-12] ;Get the control flags TST R7,#slFlag_vertical ;Is the slider vertical? LDRNE R0,[R13,#0] ;Yes -- read mouse x position LDREQ R0,[R13,#4] ;No -- read mouse y position MOVNE R2,R0 ;Force mouse to straight line MOVNE R4,R0 MOVEQ R3,R0 MOVEQ R5,R0 MOV R0,R10 ;Get the dialogue handle BL dbox_window ;Get the dbox's window handle MOV R1,#7 ;Drag type is user-defined STMIA R13,{R0,R1} ;Store them in the block ADD R14,R13,#24 ;Point to parent box posn STMIA R14,{R2-R5} ;Save them in the block MOV R1,R13 ;Point to the block SWI Wimp_DragBox ;Start a drag operation ADD R13,R13,#56 ;Reclaim all that stack space ADR R0,sl__ukEvents ;Point to unknown handler MOV R1,#0 ;Don't care about R4 MOV R2,R10 ;Pass dialogue box in R10 MOV R3,R12 ;Pass workspace in R12 BL win_unknownHandler ;Add the handler MOVVC R0,#2 ;Call me every TV frame ADRVC R1,sl__idles ;Point to idle handler BLVC idle_handler ;Add in the idle handler BL sl__idles ;Do one now for luck 60slider LDMIA R13!,{R0-R3,R14} ;Load the registers back ORRS PC,R14,#C_flag ;Claim this event slider__wSpace DCD 0 LTORG ; --- sl__idles --- ; ; On entry: R10 == dialogue box handle for dbox ; R12 == my workspace ; ; On exit: -- ; ; Use: Handles idle events during a slider drag sl__idles ROUT STMFD R13!,{R0-R5,R8,R9,R14} ;Save a barrelload of regs LDMIB R12,{R2-R5,R8,R9} ;Load registers for readVal MOV R0,#slider_event ;My very own event code MOV R1,#slider_sliding ;Indicate it's still going BL sl__readVal ;Perform the update BLCS dbx_sendEvent ;Send the event if it changed LDMFD R13!,{R0-R5,R8,R9,PC}^ ;Return to caller LTORG ; --- sl__ukEvents --- ; ; On entry: R0 == event code ; R1 == pointer to event data ; R4 == 0! ; R10 == dialogue box handle ; R12 == my workspace ; ; On exit: If R0 == 7 on entry, C set, otherwise all preserved ; ; Use: Handles unknown events for sliders. sl__ukEvents ROUT CMP R0,#7 ;Is this a drag event? MOVNES PC,R14 ;No -- not interested then STMFD R13!,{R0-R5,R8,R9,R14} ;Save a bucketload of regs ; --- Update the slider one last time --- LDMIB R12,{R2-R5,R8,R9} ;Load registers for readVal MOV R0,#slider_event ;My very own event code MOV R1,#slider_slid ;Indicate it's over now BL sl__readVal ;Perform the update BL dbx_sendEvent ;Send the event regardless ; --- Close down the idle and unknown handlers --- ADR R0,sl__ukEvents ;Point to unknown handler MOV R1,#0 ;Don't care about R4 MOV R2,R10 ;Pass dialogue box in R10 MOV R3,R12 ;Pass workspace in R12 BL win_removeUnknownHandler;Add the handler MOV R0,#2 ;Call me every TV frame ADR R1,sl__idles ;Point to idle handler BL idle_removeHandler ;Add in the idle handler LDMFD R13!,{R0-R5,R8,R9,PC}^ ;Return to caller at last LTORG ; --- sl__readVal --- ; ; On entry: R0 == event code for dialogue box (slider_event) ; R1 == subreason code to send (slider_sliding or slider_slid) ; R2-R5 == position of icon on screen ; R8 == pointer to control workspace ; R9 == pointer to control definition ; R10 == dialogue box handle ; ; On exit: R2,R3 set up for slider event ; CS if the slider position has changed ; ; Use: Reads a slider value from mouse position, and sends the ; dialogue box an event sl__readVal ROUT STMFD R13!,{R0,R1,R6,R14} ;Save some registers ; --- Read the mouse position --- SUB R13,R13,#20 ;Make space for a mouse blk MOV R1,R13 ;Point to the block SWI Wimp_GetPointerInfo ;Get the pointer position LDR R14,[R9,#-12] ;Load the control flags TST R14,#slFlag_vertical ;Is the control vertical? LDRNE R0,[R1,#4] ;Yes -- get the y coordinate SUBNE R0,R0,R3 ;And chop off bottom posn LDREQ R0,[R1,#0] ;No -- get the x coordinate SUBEQ R0,R0,R2 ;And chop of the left posn ADD R13,R13,#20 ;Reclaimt the stack now ; --- Scale this value to user's units --- LDR R6,[R9,#4] ;Get user's maximum value MUL R0,R6,R0 ;Multiply position up nicely SUBNE R1,R5,R3 ;Vertical -- get height SUBEQ R1,R4,R2 ;Horizontal -- get width BL div_round ;Divide and round to nearest CMP R0,R6 ;Is the value too large? MOVGT R0,R6 ;Yes -- force it down then CMP R0,#0 ;Is it too small? MOVLT R0,#0 ;Yes -- force it up then LDR R3,[R8,#0] ;Get the old slider value CMP R0,R3 ;Is this the same as then? STRNE R0,[R8,#0] ;No -- Store the new value MOVNE R3,R0 ;Keep a copy for later ; --- Update the picture of the slider --- MOV R0,R10 ;Get the dialogue handle LDR R1,slider__icon ;Get the icon handle BLNE dbx_update ;Update the slider display MOV R2,R1 ;Get icon handle in R2 LDMFD R13!,{R0,R1,R6,R14} ;Restore registers ORRNES PC,R14,#C_flag ;If new value, set C on exit BICEQS PC,R14,#C_flag ;Otherwise clear it LTORG ;----- Slider event codes --------------------------------------------------- slider_event EQU &80000001 slider_sliding EQU 0 slider_slid EQU 1 ;----- Workspace ------------------------------------------------------------ ^ 0,R12 slider__wStart # 0 slider__icon # 4 ;Icon handle for slider slider__iconPos # 16 ;Icon coordinates on screen slider__work # 4 ;Pointer to user's workarea slider__defn # 4 ;Pointer to slider definition slider__wSize EQU {VAR}-slider__wStart AREA |Sapphire$$LibData|,CODE,READONLY DCD slider__wSize DCD slider__wSpace DCD 0 DCD 0 ;----- That's all, folks ---------------------------------------------------- END