UnderwareDESIGN

PlayBASIC => Resources => Source Codes => Topic started by: Alex777 on March 01, 2006, 08:21:23 PM

Title: simple windows
Post by: Alex777 on March 01, 2006, 08:21:23 PM
I know there are several very good windows packages on here.  So, why am I posting another one?  Well, sometimes you just need something simple to display a bit of text or get a couple of option selections  from the user.  That's what this is - simple windows for when you don't need anything more complex.

[pbcode]

RemStart
SIMPLE WINDOWS:
Instructions: press "G" repeatedly (come on - you can handle that).
Alex Henderson
alexhenderson7@yahoo.ca
copyright: public domain
RemEnd

Constant White = RGB(255, 255, 255)
Constant Black = RGB(8, 8, 8)
Constant Trans = RGB(0, 0, 0)
Constant GrayDark = RGB(64, 64, 64)
Constant GrayMedium = RGB(128, 128, 128)
Constant GrayLight = RGB(192, 192, 192)
Constant Red = RGB(255, 0, 0)
Constant Buff = RGB(169, 212, 140)

Global FontSmall = GetFreeFont()
LoadFont "Arial", FontSmall, 18, 0
Global FontMedium = GetFreeFont()
LoadFont "Arial", FontMedium, 21, 0
Global FontMediumUnd = GetFreeFont()
LoadFont "Arial", FontMediumUnd, 21, 4
Ink Black

OpenScreen 1024, 768, 16, 2
Dim gameOptions(4)
gameOptions(2) = On
gameOptions(4) = On

; I threw in the camera to demonstrate that the routine works with it
thisCam = GetFreeCamera()
CreateCamera thisCam

Do
   CaptureToScene
   ClsScene
   KeyCode = ScanCode()
   If KeyCode = 34
   ; G key was pressed
    FlushKeys
    TestWindows()
   EndIf
   DrawCamera thisCam
   Cls Buff  ; ***
   Sync
Loop

; ------------------------------------------------------------------------------

Psub TestWindows()
; demo code

Static testNum

Inc testNum
Select testNum
Case 1
 message$ = "|SIMPLE WINDOWS^^You can^display text^centered^~or "
 message$ = message$ + "left-justified in either of^|~2 fonts (per window)."
 buttons$ = "OK"
 button = IO_DrawWindow(message$, buttons$, gameOptions(), _
  FontSmall, FontMediumUnd)
Case 2
 message$ = "|A SIMPLE TABLE^^~A{{order 1 beer^~B{{order 2^~C{{make it 3"
 buttons$ = "OK^Cancel"
 button = IO_DrawWindow(message$, buttons$, gameOptions(), _
  FontSmall, FontMedium)
Case 3
 message$ = "|COMMAND BUTTONS^^~When the user left-clicks any button,^~the "
 message$ = message$ + "window closes and the button no. is returned"
 buttons$ = "Move^Fire^Code^Drink"
 button = IO_DrawWindow(message$, buttons$, gameOptions(), _
  FontSmall, FontMedium)
Case 4
 message$ = "You selected command button no. " + Str$(button)
 buttons$ = "OK"
 button = IO_DrawWindow(message$, buttons$, gameOptions(), _
  FontSmall, FontMedium)
Case 5
 message$ = "|OPTION BOXES^^~Left-click a box to toggle its status^~the "
 message$ = message$ + "status of all boxes is returned^"
 message$ = message$ + "^~cancel order{{}"
 message$ = message$ + "^~order beer again{}"
 message$ = message$ + "^~return to coding{}"
 message$ = message$ + "^~play a game{{}"
 buttons$ = "OK^Cancel"
 button = IO_DrawWindow(message$, buttons$, gameOptions(), _
  FontSmall, FontMediumUnd)
Case 6
 message$ = "|Your box settings:^"
 message$ = message$ + "^~Box 1{{{" + Str$(gameOptions(1))
 message$ = message$ + "^~Box 2{{{" + Str$(gameOptions(2))
 message$ = message$ + "^~Box 3{{{" + Str$(gameOptions(3))
 message$ = message$ + "^~Box 4{{{" + Str$(gameOptions(4))
 buttons$ = "OK"
 button = IO_DrawWindow(message$, buttons$, gameOptions(), _
  FontSmall, FontMedium)
Default
 End
EndSelect

EndPsub

; ------------------------------------------------------------------------------

Psub IO_DrawWindow(message$, buttons$, gameOptions(), font1, font2)

   RemStart
   A simple routine to draw a text window centered on the screen.  
   Each string separated by "^" in message$ is a line of text.  
   Text will be displayed in font1 unless "|" is the 1st character in the
     line, in which case it will be in font2.
   Text will be centered horizontally in window unless "~" is the 1st or 2nd
     character in the line, in which case it will be left-justified.
   The "{" character placed anywhere in a left-justified line = a TAB stop,
     of distance = tabWidth.
   The "}" character placed anywhere in a left-justified line will display
     a selection box.
   Selection boxes are initialized according to the contents of gameOptions().
   Each element in gameOptions() = On or Off.
   Left-clicking a selection box will toggle the selected box on or off.
   The "^", "~", "|", "{" and "}" characters are non-displayable.
   Each string in buttons$ separated by "^" contains text for a button.
   All buttons are displayed in a single row at the bottom, centered.
   The routine calculates the window width & height for you.
   Focus is restricted to window until selection is made by a left-click.
   returns: buttonSelected = the index number in button$() of the button clicked.
        Button 1 is the first button.
            gameOptions(n) = status (On or Off) of the selections made.
              gameOptions(1) is the first selection box.
   RemEnd

; all these constants are in pixels
; size of 1 tab stop
  Constant tabWidth = 50
; the width of the window border
  Constant borderWidth = 10
; indent from window border
  Constant LIndent = 40
; height of 1 line & space below it
  Constant pitchY = 30
; width of a button
  Constant buttWidth = 76
; height of a button
  Constant buttHeight = 18
; space bewtween 2 buttons
  Constant buttPitchX = 20
; width & height of a selection box / 2
  Constant boxSize = 20 / 2

  Local x, y, temp, n, temp$, copy$, posX, posTab, storefont, posBox
  Local messCount, buttCount, cursorX, cursorY
  Local winX, winY, winX1, winY1, winWidth, winHeight
 
  winX = 0 : winY = 0 : winX1 = 0 : winY1 = 0
  winWidth = 0 : winHeight = 0
 
  Dim message$(0)
; parse the parameter string into an array
  messCount = SplitToArray(message$, "^", message$(), 1)
  Dim buttons$(0)
  buttCount = SplitToArray(buttons$, "^", buttons$(), 1)
 
  Ink Black
; needed by GetTextWidth() - note that this assumes the widest line will be
;    in font1 not font2
  SetFont font1

; get the window dimensions:
; get width of the widest line of text, taking TAB stops & boxes into account:
For n = 1 To messCount
 copy$ = message$(n)
 posTab = 0 : posX = 0
 
 Repeat
; search for TAB stop character
   posTab = InString(copy$, "{", 1, False)
   
    If posTab > 0
   ; TAB stop found
     temp$ = Left$(copy$, posTab - 1)
     copy$ = CutLeft$(copy$, posTab)
   ; & move to next TAB stop
  posX = posX + GetTextWidth(temp$) + (tabWidth - _
    Mod(posX, tabWidth))
 Else
  posX = posX + GetTextWidth(copy$)
 EndIf

 posBox = 0
 Repeat
  posBox = InString(copy$, "}", posBox + 1, False)
  If posBox > 0 Then posX = posX + boxSize
 Until posBox = 0

Until posTab = 0

; store width of widest line
 If posX > winWidth Then winWidth = posX
 Next n
 
; add borders to width
 winWidth = winWidth + borderWidth * 2 + LIndent * 2
; get width of the row of buttons
 x = buttCount * buttWidth + buttCount * (buttPitchX - 1) + LIndent _
  + borderWidth * 2
; which is wider?
 If x > winWidth Then winWidth = x
 
; get height of window:
winHeight = borderWidth * 2 + (messCount + 2) * pitchY + buttHeight
 
; get window position - it is centered on screen:
winX = MidPoint(0, GetScreenWidth()) - MidPoint(0, winWidth)
winY = MidPoint(0, GetScreenHeight()) - MidPoint(0, winHeight)
winX1 = winX + winWidth : winY1 = winY + winHeight
 
 ; holds command button indices in (n, 0) and the x,y pos where shape is
;    drawn in (n, 1 - 2)
  Dim shapes(buttCount, 2)
; create buttons:
shapes(1, 0) = GetFreeShape()
  CreateShape shapes(1, 0), 6, 6
  SetShapeVertex shapes(1, 0), 1, 0, 0
  SetShapeVertex shapes(1, 0), 2, 76, 0
  SetShapeVertex shapes(1, 0), 3, 76, 24
  SetShapeVertex shapes(1, 0), 4, 0, 24
  SetShapeEdge shapes(1, 0), 1, 1, 2
  SetShapeEdge shapes(1, 0), 2, 2, 3
  SetShapeEdge shapes(1, 0), 3, 3, 4
  SetShapeEdge shapes(1, 0), 4, 4, 1
 
; create the buttons
  For n = 2 To buttCount
   shapes(n, 0) = GetFreeShape()
   CopyShape shapes(1, 0), shapes(n, 0)
Next n
 
  boxes = GetArrayElements(gameOptions(), 1)
  If boxes > 0
   
  ; holds box indices in (n, 0) and the x,y pos where shape is
  ;    drawn in (n, 1 - 2)
   Dim boxes(boxes, 2)
   boxes(1, 0) = GetFreeShape()
   CreateShape boxes(1, 0), 6, 6
   SetShapeVertex boxes(1, 0), 1, boxSize, - boxSize
   SetShapeVertex boxes(1, 0), 2, boxSize, boxSize
   SetShapeVertex boxes(1, 0), 3, - boxSize, boxSize
   SetShapeVertex boxes(1, 0), 4, - boxSize, - boxSize
   SetShapeEdge boxes(1, 0), 1, 1, 2
   SetShapeEdge boxes(1, 0), 2, 2, 3
   SetShapeEdge boxes(1, 0), 3, 3, 4
   SetShapeEdge boxes(1, 0), 4, 4, 1
 
 ; create the boxes
   For n = 2 To GetArrayElements(boxes(), 1)
    boxes(n, 0) = GetFreeShape()
    CopyShape boxes(1, 0), boxes(n, 0)
 Next n
   boxNum = 0
  EndIf
 
  ScreenViewPort winX, winY, winX1, winY1
  NewWin = GetFreeImage()
  CreateImage NewWin, winWidth, winHeight
  RenderToImage NewWin
  DrawGFXImmediate
 
; window background color:
  Cls White
 
; draw window border:
; left
  ShadeBox 0, 0, BorderWidth, winHeight, GrayDark, GrayLight, _
    GrayLight, GrayDark
; right
  ShadeBox winWidth - BorderWidth, 0, winWidth, winHeight, GrayLight, _
    GrayDark, GrayDark, GrayLight
; top
  ShadeBox 0, 0, winWidth, BorderWidth, GrayDark, GrayDark, _
    GrayLight, GrayLight
; bottom
  ShadeBox 0, winHeight - BorderWidth, winWidth, winHeight, GrayLight,_
     GrayLight, GrayDark, GrayDark
     
; draw text onto window:
  For n = 1 To messCount
   
; choose font for this line
  If Left$(message$(n), 1) = "|"
   SetFont font2
   message$(n) = CutLeft$(message$(n), 1)
  Else
   SetFont font1
EndIf

  If Left$(message$(n), 1) <> "~"  
 ; centered text
   CenterText MidPoint(0, winWidth), pitchY * n, message$(n)
   
Else
; left-justified text
 message$(n) = CutLeft$(message$(n), 1)
 posX = borderWidth + LIndent
 posTab = 0
 
 Repeat
; search for TAB stop character or selection box character
     posTab = InString(message$(n), "{", 1, False)
     posBox = InString(message$(n), "}", 1, False)
     
     If (posTab > 0) Or (posBox > 0)
    ; TAB stop or box found
     
      If posTab > 0
       thisPos = posTab
      Else
       thisPos = posBox
      EndIf
 
      temp$ = Left$(message$(n), thisPos - 1)
      message$(n) = CutLeft$(message$(n), thisPos)
    ; display text before TAB character or box
      Text posX, pitchY * n, temp$
     
      If posTab > 0
     ; move to next TAB stop
    posX = posX + GetTextWidth(temp$)
    posX = posX + (tabWidth - Mod(posX, tabWidth))
   
   Else
  ; display option box
    posX = posX + GetTextWidth(temp$) + 20
    Inc boxNum
    posY = pitchY * n + boxSize
    DrawShape boxes(boxNum, 0), posX, posY, 1
    boxes(boxNum, 1) = posX
    boxes(boxNum, 2) = posY
   
  ; initialize the boxes with gameOptions() values
    If gameOptions(boxNum) = On
      ; use this to place "X"s in the boxes
      ;Text boxes(boxNum, 1) - boxSize / 2, boxes(boxNum, 2)_
      ;    - boxSize, "X"
      ; or this to fill boxes with black
        CircleC boxes(boxNum, 1), boxes(boxNum, 2), 5, 1, Black
       EndIf
     
    posX = posX + boxSize + 20
   EndIf
 
  Else
   Text posX, pitchY * n, message$(n)
  EndIf
   
 Until (posTab = 0) And (posBox = 0)
EndIf
   
Next n

; font for the buttons:
SetFont FontMedium

; 1/2 the width of the button row:
x = (buttCount * (buttWidth + buttPitchX) - buttPitchX) / 2
x1 = winWidth / 2
; X pos of left-most button
posX = x1 - x

; draw buttons & button text onto window:
  For n = 1 To buttCount
   
 shapes(n, 1) = posX + (n - 1) * (buttWidth + buttPitchX)
 shapes(n, 2) = winHeight - (borderWidth + pitchY + buttHeight / 2)
 
   DrawShape shapes(n, 0), shapes(n, 1), shapes(n, 2), 1
   
   CenterText MidPoint(shapes(n, 1), shapes(n, 1) + buttWidth), _
    shapes(n, 2) + 1, buttons$(n)
   
  Next n

SetMouse MidPoint(winX, winX1), MidPoint(winY, winY1)

buttonSelected = - 1
; get user input - focus stays in window until a button is selected:
  Repeat

    Repeat
 
; display everything
     RenderToScreen
       DrawImage NewWin, winX, winY, 1
       cursorX = MouseX() : cursorY = MouseY()
 CircleC cursorX, cursorY, 5, 1, Red
       Sync

    Until LeftMouseButton()
   
   ; test for a left-click in a box
     If GetArrayStatus(boxes())
     
      For n = 1 To boxes
       
      If PointHitShape(cursorX, cursorY, boxes(n, 0), _
       winX + boxes(n, 1), winY + Boxes(n, 2))
       
     ; user has clicked on a box, so reverse the setting
       gameOptions(n) = Not gameOptions(n)
       
       RenderToImage NewWin
       
       If gameOptions(n) = On
      ; use this to place "X"s in the boxes
      ;Text boxes(n, 1) - boxSize / 2, boxes(n, 2) - boxSize, "X"
      ; or this to place a filled circle in box
        CircleC boxes(n, 1), boxes(n, 2), 5, 1, Black
       Else
      ; setting is "off", so place an empty box
        Ink white
        DrawShape boxes(n, 0), boxes(n, 1), boxes(n, 2), 2
        Ink black
        DrawShape boxes(n, 0), boxes(n, 1), boxes(n, 2), 1
       EndIf
     
       RenderToScreen
       ExitFor n
      EndIf
    Next n
 EndIf

 For n = 1 To buttCount
     If PointHitShape(cursorX, cursorY, shapes(n, 0), _
      winX + shapes(n, 1), winY + shapes(n, 2))
    ; a button has been clicked
      buttonSelected = n
      ExitFor n
     EndIf
   Next n
 
    FlushMouse

  Until buttonSelected > - 1

DeleteImage NewWin
UnDim shapes()
UnDim message$()
UnDim buttons$()
UnDim boxes()
ScreenViewPort 0, 0, GetScreenWidth(), GetScreenHeight()

EndPsub buttonSelected

; ==============================================================================


[/pbcode]

Title: simple windows
Post by: Ian Price on March 02, 2006, 01:56:53 AM
That's pretty good - although I'm not overly keen on the mushy-pea green colour scheme :P

I thought it was borked at first as the screen remained green - it wasn't until I read the code that I realised you had to press "G" - seems like a strange keychoice, but nevermind.

Good stuff :)
Title: simple windows
Post by: Alex777 on March 02, 2006, 05:21:54 AM
"G" for Go.  Or, G for Green, I guess.   :rolleyes:   Anyway, thanks!
Title: simple windows
Post by: kevin on March 08, 2006, 10:26:59 AM
Very nice !
Title: simple windows
Post by: kevin on March 12, 2006, 04:18:14 AM
because it's so handy i've moved this to the source code forum
Title: simple windows
Post by: Alex777 on March 12, 2006, 07:31:51 AM
Thanks, Kevin!