Shape "Gadgets"

Share your advanced PureBasic knowledge/code with the community.
Xombie
Addict
Addict
Posts: 898
Joined: Thu Jul 01, 2004 2:51 am
Location: Tacoma, WA
Contact:

Shape "Gadgets"

Post by Xombie »

Code updated For 5.20+

Well, kind of shape gadgets. I really missed having the little line control thing in VB. It made it nice to visually separate controls and add a little bit of formatting to a form. So I figured I'd take it upon myself to make this simple little thing. It basically allows you to draw lines, circles and boxes on a window. Big deal, you say, right? Well, it keeps track of them and automatically redraws them when needed. You can also get the x/y/width/height of them (so you can use it for positioning other gadgets) and you can resize them as needed.

It still needs work but I thought I'd see if anyone was interested. I just worked on it a bit today so it's nothing great. Here's a simple screenshot.


THat's a box under the Hightlight button and some lines drawn. Like I said, nothing special :D

Here's the main form (that I almost always just call "Main.pb")

Code: Select all

; By Xombie - 12/12/2005
;
Enumeration ; Window List
  #WindowMain
EndEnumeration
Enumeration ; Menu List
  #MenuMain
EndEnumeration
Enumeration ; Control List
  #ButtonTest
  #StringTest
  #StringTest2
  #ComboTest
  #Line01
  #Line02
  #Circle01
  #Button01
  #Button02
  #Button03
  #Button04
  #Button05
  #LineDiv01
  #LineDiv02
  #LineDiv03
  #Box01
EndEnumeration
;- Includes
XIncludeFile "FormDraw.pb"
;- Main Program
DoQuit.b
;
If OpenWindow(#WindowMain, 100, 300, 300, 200, "Test", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget)
  ;
  
  ;
  ;           AdvancedGadgetEvents(#True)
  ;
  StringGadget(#StringTest, 0, 0, 100, 20, "")
  ;
  ButtonGadget(#Button01, GadgetX(#StringTest) + GadgetWidth(#StringTest), GadgetY(#StringTest), 40, 20, "1")
  fd_LineGadget(#WindowMain, #LineDiv01, GadgetX(#Button01) + GadgetWidth(#Button01) + 3, GadgetY(#Button01), GadgetX(#Button01) + GadgetWidth(#Button01) + 3, GadgetHeight(#Button01), 0)
  ButtonGadget(#Button02, fd_GadgetX(#LineDiv01) + fd_GadgetWidth(#LineDiv01) + 3, fd_GadgetY(#LineDiv01), 40, 20, "2")
  fd_LineGadget(#WindowMain, #LineDiv02, GadgetX(#Button02) + GadgetWidth(#Button02) + 3, GadgetY(#Button02), GadgetX(#Button02) + GadgetWidth(#Button02) + 3, GadgetHeight(#Button02), 0)
  ButtonGadget(#Button03, fd_GadgetX(#LineDiv02) + fd_GadgetWidth(#LineDiv02) + 3, fd_GadgetY(#LineDiv02), 40, 20, "3")
  fd_LineGadget(#WindowMain, #LineDiv03, GadgetX(#Button03) + GadgetWidth(#Button03) + 3, GadgetY(#Button03), GadgetX(#Button03) + GadgetWidth(#Button03) + 3, GadgetHeight(#Button03), 0)
  ButtonGadget(#Button04, fd_GadgetX(#LineDiv03) + fd_GadgetWidth(#LineDiv03) + 3, fd_GadgetY(#LineDiv03), 40, 20, "4")
  ;
  StringGadget(#StringTest2, 0, 21, 100, 20, "")
  ComboBoxGadget(#ComboTest, GadgetX(#StringTest2), GadgetY(#StringTest2) + GadgetHeight(#StringTest2) + 1, 100, 200, #PB_ComboBox_Editable)
  ButtonGadget(#ButtonTest, GadgetX(#ComboTest), GadgetY(#ComboTest) + GadgetHeight(#ComboTest) + 1, 100, 20, "Test")
  fd_LineGadget(#WindowMain, #Line01, 0, 100, 50, 100, 255)
  ;
  ButtonGadget(#Button05, GadgetX(#ButtonTest) + 200, GadgetY(#ButtonTest), 50, 20, "Highlight")
  fd_BoxGadget(#WindowMain, #Box01, GadgetX(#Button05) - 10, GadgetY(#Button05) - 10, GadgetWidth(#Button05) + 20, GadgetHeight(#Button05) + 20, RGB(128, 50, 50))
  ;
  ;        EndIf
  ;
  ;{ Create autocomplete lists
  ;
  ;/ Create items for the combobox.
  AddGadgetItem(#ComboTest, -1, "One")
  AddGadgetItem(#ComboTest, -1, "Two")
  AddGadgetItem(#ComboTest, -1, "Three")
  AddGadgetItem(#ComboTest, -1, "Four")
  AddGadgetItem(#ComboTest, -1, "Five")
  AddGadgetItem(#ComboTest, -1, "Six")
  AddGadgetItem(#ComboTest, -1, "Seven")
  AddGadgetItem(#ComboTest, -1, "Eight")
  AddGadgetItem(#ComboTest, -1, "Nine")
  AddGadgetItem(#ComboTest, -1, "Ten")
  AddGadgetItem(#ComboTest, -1, "The")
  AddGadgetItem(#ComboTest, -1, "quick")
  AddGadgetItem(#ComboTest, -1, "brown")
  AddGadgetItem(#ComboTest, -1, "fox")
  AddGadgetItem(#ComboTest, -1, "jumped")
  AddGadgetItem(#ComboTest, -1, "over")
  AddGadgetItem(#ComboTest, -1, "the")
  AddGadgetItem(#ComboTest, -1, "two")
  AddGadgetItem(#ComboTest, -1, "lazy")
  AddGadgetItem(#ComboTest, -1, "dogs")
  ;}
  ;
  Repeat
    ;
    EventID.l = WaitWindowEvent()
    ;
    If EventID = #PB_Event_CloseWindow  ; If the user has pressed on the close button
      ;
      DoQuit = #True
      ;
    ElseIf EventID = #PB_Event_Gadget
      ;
      If EventGadget() = #ButtonTest
        ;
        If EventType() = #PB_EventType_LeftClick
          ;
          fd_LineGadget(#WindowMain, #Line02, 0, 120, 250, 80, 23526)
          ;
          fd_RemoveGadget(#Line01)
          ;
          fd_CircleGadget(#WindowMain, #Circle01, 100, 100, 50, 0)
          ;
          fd_ResizeGadget(#LineDiv01, 0, 0, fd_GadgetWidth(#LineDiv01), 25)
          fd_ResizeGadget(#LineDiv02, 0, 0, fd_GadgetWidth(#LineDiv02), 30)
          fd_ResizeGadget(#LineDiv03, 0, 0, fd_GadgetWidth(#LineDiv03), 35)
          ;
        EndIf
        ;
      ElseIf EventGadget() = #Button01
        ;
        If EventType() = #PB_EventType_LeftClick
          ;
          fd_ResizeGadget(#Circle01, 0, 0, 20, 0)
          ;
        EndIf
        ;
      ElseIf EventGadget() = #Button02
        ;
        If EventType() = #PB_EventType_LeftClick
          ;
          fd_ResizeGadget(#Line02, 0, 0, fd_GadgetWidth(#Line02), -10)
          ;
        EndIf
        ;
      ElseIf EventGadget() = #Button03
        ;
        If EventType() = #PB_EventType_LeftClick
          ;
          fd_RemoveWindow(#WindowMain)
          ;
        EndIf
        ;
      ElseIf EventGadget() = #Button05
        ;
        If EventType() = #PB_EventType_LeftClick
          ;
          fd_ResizeGadget(#Box01, GadgetX(#Button05) - 20, GadgetY(#Button05) - 20, GadgetWidth(#Button05) + 40, GadgetHeight(#Button05) + 40)
          ;
        EndIf
        ;
      EndIf
      ;
    EndIf
    ;
  Until DoQuit = #True
  
EndIf
fd_Destroy()
End
And here's the code to draw shape "gadgets". I call it "FormDraw.pb" for my example so you will need to save it with that name to work for my example.

Code: Select all

;- Coded by Xombie 12/21/2005
;
;- Enumeration
Enumeration
  #fd_Line
  #fd_Rectangle
  #fd_Box
  #fd_Circle
EndEnumeration
;- Structures
Structure s_fdShapes
  ;
  Gadget.l
  ; The equivalent of the Purebasic Gadget Identifier.
  Window.l
  ; The Purebasic Window Identifier.
  Type.b
  ; The type of drawing.
  X.l
  Y.l
  X2.l
  Y2.l
  ;
  Color.l
  ;
EndStructure
Structure s_fdForm
  ;
  Window.l
  CallBack.l
  Shapes.l
  ; Pointer to s_fdGadgets array.
  Size.l
  ;
  Count.l
  ;
EndStructure
Structure s_fdMain
  ;
  Form.l
  ; Pointer to s_fdForm array.
  Size.l
  ;
  Count.l
  ;
EndStructure
;- Global Variables
Global _fDraw.s_fdMain
; The main structure to hold information about the drawn shapes.
;- Callbacks
Procedure.l fd_HandleEvents(HandleWindow.l, Message.l, wParam.l, lParam.l)
  ;
  CallBack.l
  ;
  OldWindow.l
  ;
  
  ;
  HoldRect.RECT
  ;
  *HoldForm.s_fdForm
  ;
  *HoldShapes.s_fdShapes
  ;
  HandleClip.l
  ;
  HandleOut.l
  ;
  ; If Message = #WM_ERASEBKGND : Debug "!" : EndIf
  ;
  If Message = #WM_PAINT
    ;
    If _fDraw\Form
      ;
      GetUpdateRect_(HandleWindow, @HoldRect, #False)
      ; Retrieve the area being redrawn.
      *Position = _fDraw\Form
      While *Position - _fDraw\Form < _fDraw\Size
        ;
        *HoldForm = PeekL(*Position)
        ;
        If HandleWindow = WindowID(*HoldForm\Window)
          ;
          ;                    UseWindow()
          HandleOut = StartDrawing(WindowOutput(*HoldForm\Window))
          ;
          HandleClip = CreateRectRgn_(HoldRect\Left, HoldRect\Top, HoldRect\Right, HoldRect\Bottom) : SelectClipRgn_(HandleOut, HandleClip)
          ; Create a clipping area based on the area redrawn.  If a window is only partially clipped, it will not redraw
          ; the whole window.  Instead, it will redraw the part that was clipped.  If half of a circle was clipped and
          ; we did not create a clipping region, this would cause the whole circle to be redrawn and it would appear
          ; on top of other controls.  This ensures that the drawn shapes are beneath actual controls.
          If *HoldForm\Shapes
            ;
            *Position = *HoldForm\Shapes
            While *Position - *HoldForm\Shapes < *HoldForm\Size
              ;
              *HoldShapes = PeekL(*Position)
              ;
              If *HoldShapes\Type = #fd_Line
                ;
                LineXY(*HoldShapes\X, *HoldShapes\Y, *HoldShapes\X2, *HoldShapes\Y2, *HoldShapes\Color)
                ;
              ElseIf *HoldShapes\Type = #fd_Circle
                ;
                Circle(*HoldShapes\X, *HoldShapes\Y, *HoldShapes\X2, *HoldShapes\Color)
                ;
              ElseIf *HoldShapes\Type = #fd_Box
                ;
                Box(*HoldShapes\X, *HoldShapes\Y, *HoldShapes\X2, *HoldShapes\Y2, *HoldShapes\Color)
                ;
              EndIf
              ;
              *Position + 4
              ;
            Wend
            ;
          EndIf
          ;
          StopDrawing()
          ;
          Break
          ;
        EndIf
        ;
        *Position + 4
        ;
      Wend
      ;
      SelectClipRgn_(HandleOut, 0) : DeleteObject_(HandleClip)
      ; Remove the clipping region.
    EndIf
    ;
  Else
    ;
    *Position = _fDraw\Form
    While *Position - _fDraw\Form < _fDraw\Size
      ;
      *HoldForm = PeekL(*Position)
      ;
      If HandleWindow = WindowID(*HoldForm\Window) : Break : EndIf
      ;
      *Position + 4
      ;
    Wend
    ;
  EndIf
  ;
  CallBack = CallWindowProc_(*HoldForm\CallBack, HandleWindow, Message, wParam, lParam)
  ;
  ProcedureReturn CallBack
  ;
EndProcedure
;- Array Procedures
Procedure.l _fd_AddForm(Window.l)
  ;
  NewArray.l
  ;
  
  ;
  *HoldForm.s_fdForm
  ;
  If _fDraw\Form
    ;
    *Position = _fDraw\Form
    While *Position - _fDraw\Form < _fDraw\Size
      ;
      *HoldForm = PeekL(*Position)
      ;
      If *HoldForm\Window = Window : ProcedureReturn *HoldForm : EndIf
      ; The window already exists.
      *Position + 4
      ;
    Wend
    ;
    NewArray = AllocateMemory(_fDraw\Size + 4)
    ;
    CopyMemory(_fDraw\Form, NewArray, _fDraw\Size)
    ;
    *HoldForm = AllocateMemory(SizeOf(s_fdForm))
    ;
    *HoldForm\Window = Window
    ;
    *HoldForm\CallBack = SetWindowLong_(WindowID(Window), #GWL_WNDPROC, @fd_HandleEvents())
    ; Set a callback for the window to handle redrawing the shapes.
    *HoldForm\Shapes = 0
    ; The drawn gadgets array is empty.
    *HoldForm\Size = 0 : *HoldForm\Count = 0
    ; No drawn gadgets added yet.
    PokeL(NewArray + _fDraw\Size, *HoldForm)
    ;
    FreeMemory(_fDraw\Form) : _fDraw\Form = NewArray
    ; Reassign the form array to the new array.
  Else
    ; No forms exist yet.
    _fDraw\Form = AllocateMemory(4)
    ;
    *HoldForm = AllocateMemory(SizeOf(s_fdForm))
    ;
    *HoldForm\Window = Window
    ;
    *HoldForm\CallBack = SetWindowLong_(WindowID(Window), #GWL_WNDPROC, @fd_HandleEvents())
    ; Set a callback for the window to handle redrawing the shapes.
    *HoldForm\Shapes = 0
    ; The drawn gadgets array is empty.
    *HoldForm\Size = 0 : *HoldForm\Count = 0
    ; No drawn gadgets added yet.
    PokeL(_fDraw\Form, *HoldForm)
    ;
  EndIf
  ;
  _fDraw\Size + 4 : _fDraw\Count + 1
  ; Increment the form count.
  ProcedureReturn *HoldForm
  ;
EndProcedure
Procedure.l _fd_AddShape(Window.l, Gadget.l, Type.b, X.l, Y.l, X2.l, Y2.l, Color.l)
  ;
  NewArray.l
  ;
  
  ;
  
  ;
  *HoldForm.s_fdForm
  ;
  *HoldShapes.s_fdShapes
  ;
  *HoldForm = _fd_AddForm(Window)
  ; Add the window to the array or return the existing window information.
  If *HoldForm\Shapes
    ;
    *Position = *HoldForm\Shapes
    While *Position - *HoldForm\Shapes < *HoldForm\Size
      ;
      *HoldShapes = PeekL(*Position)
      ;
      If *HoldShapes\Gadget = Gadget
        ; The control already exists.
        If *HoldShapes\Type <> Type
          ;
          MessageRequester("Error!", "Cannot change a shape type!  Please remove this shape and add a new one to continue.")
          ;
          ProcedureReturn 0
          ;
        Else
          ;
          *HoldShapes\X = X
          *HoldShapes\Y = Y
          *HoldShapes\X2 = X2
          *HoldShapes\Y2 = Y2
          *HoldShapes\Color = Color
          ;
          ;- Do Redraw here.  Maybe calculate a rectangle and redraw just that rectangle?
          ;
          ProcedureReturn *HoldShapes
          ; Exit the procedure.
        EndIf
        ;
      EndIf
      ;
      *Position + 4
      ;
    Wend
    ;
    NewArray = AllocateMemory(*HoldForm\Size + 4)
    ;
    CopyMemory(*HoldForm\Shapes, NewArray, *HoldForm\Size)
    ;
    *HoldShapes = AllocateMemory(SizeOf(s_fdShapes))
    ;
    *HoldShapes\Gadget = Gadget
    *HoldShapes\Type = Type
    *HoldShapes\X = X
    *HoldShapes\Y = Y
    *HoldShapes\X2 = X2
    *HoldShapes\Y2 = Y2
    *HoldShapes\Color = Color
    ;
    PokeL(NewArray + *HoldForm\Size, *HoldShapes)
    ;
    FreeMemory(*HoldForm\Shapes) : *HoldForm\Shapes = NewArray
    ;
    *HoldForm\Size + 4 : *HoldForm\Count + 4
    ; Increment the shape count and size.
  Else
    ; No shapes exist in the array.
    *HoldForm\Shapes = AllocateMemory(4)
    ;
    *HoldShapes = AllocateMemory(SizeOf(s_fdShapes))
    ;
    *HoldShapes\Gadget = Gadget
    *HoldShapes\Type = Type
    *HoldShapes\X = X
    *HoldShapes\Y = Y
    *HoldShapes\X2 = X2
    *HoldShapes\Y2 = Y2
    *HoldShapes\Color = Color
    ;
    PokeL(*HoldForm\Shapes, *HoldShapes)
    ;
    *HoldForm\Count = 1 : *HoldForm\Size = 4
    ;
  EndIf
  ;
  ProcedureReturn *HoldShapes
  ;
EndProcedure
Procedure.l _fd_GetShape(Gadget.l, *ParentForm.s_fdForm)
  ;
  
  ;
  *HoldForm.s_fdForm
  ;
  *HoldShapes.s_fdShapes
  ;
  If _fDraw\Form
    ;
    *Position = _fDraw\Form
    While *Position - _fDraw\Form < _fDraw\Size
      ;
      *HoldForm = PeekL(*Position)
      ;
      If *HoldForm\Shapes
        ;
        *PositionSub = *HoldForm\Shapes
        While *PositionSub - *HoldForm\Shapes < *HoldForm\Size
          ;
          *HoldShapes = PeekL(*PositionSub)
          ;
          If *HoldShapes\Gadget = Gadget
            ;
            If *ParentForm <> -1 : *ParentForm = *HoldForm : EndIf
            ;
            ProcedureReturn *HoldShapes
            ;
          EndIf
          ;
          *PositionSub + 4
          ;
        Wend
        ;
      EndIf
      ;
      *Position + 4
      ;
    Wend
    ;
  EndIf
  ;
  ProcedureReturn 0
  ;
EndProcedure
;- Main Procedures
Procedure.l fd_GadgetX(Gadget.l)
  ;
  *HoldShapes.s_fdShapes
  ;
  *HoldShapes = _fd_GetShape(Gadget, -1)
  ;
  If *HoldShapes
    ;
    If *HoldShapes\Type = #fd_Line
      ;
      ProcedureReturn *HoldShapes\X
      ;
    ElseIf *HoldShapes\Type = #fd_Circle
      ;
      ProcedureReturn *HoldShapes\X - *HoldShapes\X2
      ; The center X value minus the radius should give the left right?
    ElseIf *HoldShapes\Type = #fd_Box
      ;
      ProcedureReturn *HoldShapes\X
      ;
    EndIf
    ;
  EndIf
  ;
  ProcedureReturn 0
  ;
EndProcedure
Procedure.l fd_GadgetY(Gadget.l)
  ;
  *HoldShapes.s_fdShapes
  ;
  *HoldShapes = _fd_GetShape(Gadget, -1)
  ;
  If *HoldShapes
    ;
    If *HoldShapes\Type = #fd_Line
      ;
      If *HoldShapes\Y2 <= *HoldShapes\Y : ProcedureReturn *HoldShapes\Y2 : Else : ProcedureReturn *HoldShapes\Y : EndIf
      ;
    ElseIf *HoldShapes\Type = #fd_Circle
      ;
      ProcedureReturn *HoldShapes\Y - *HoldShapes\X2
      ; The center Y value minus the radius should give the top right?
    ElseIf *HoldShapes\Type = #fd_Box
      ;
      ProcedureReturn *HoldShapes\Y
      ;
    EndIf
    ;
  EndIf
  ;
  ProcedureReturn 0
  ;
EndProcedure
Procedure.l fd_GadgetWidth(Gadget.l)
  ;
  *HoldShapes.s_fdShapes
  ;
  *HoldShapes = _fd_GetShape(Gadget, -1)
  ;
  If *HoldShapes
    ;
    If *HoldShapes\Type = #fd_Line
      ;
      ProcedureReturn Abs(*HoldShapes\X2 - *HoldShapes\X)
      ; Add one to account for the thickness of the line.
    ElseIf *HoldShapes\Type = #fd_Circle
      ;
      ProcedureReturn *HoldShapes\X2 * 2
      ;
    ElseIf *HoldShapes\Type = #fd_Box
      ;
      ProcedureReturn *HoldShapes\X2
      ;
    EndIf
    ;
  EndIf
  ;
  ProcedureReturn 0
  ;
EndProcedure
Procedure.l fd_GadgetHeight(Gadget.l)
  ;
  *HoldShapes.s_fdShapes
  ;
  *HoldShapes = _fd_GetShape(Gadget, -1)
  ;
  If *HoldShapes
    ;
    If *HoldShapes\Type = #fd_Line
      ;
      ProcedureReturn Abs(*HoldShapes\Y2 - *HoldShapes\X)
      ; Add one to account for the thickness of the line.
    ElseIf *HoldShapes\Type = #fd_Circle
      ;
      ProcedureReturn *HoldShapes\X2 * 2
      ;
    ElseIf *HoldShapes\Type = #fd_Box
      ;
      ProcedureReturn *HoldShapes\Y2
      ;
    EndIf
    ;
  EndIf
  ;
  ProcedureReturn 0
  ;
EndProcedure
Procedure.l fd_ResizeGadget(Gadget.l, X.l, Y.l, Width.l, Height.l)
  ;
  HoldForm.s_fdForm
  ;
  *HoldShapes.s_fdShapes
  ;
  *HoldShapes = _fd_GetShape(Gadget, @HoldForm)
  ;
  If *HoldShapes
    ;
    If *HoldShapes\Type = #fd_Line
      ;
      If X <> 0 : *HoldShapes\X = X : EndIf
      If Y <> 0 : *HoldShapes\Y = Y : EndIf
      *HoldShapes\X2 = *HoldShapes\X + Width
      *HoldShapes\Y2 = *HoldShapes\Y + Height
      ; Not sure how to account for "no change" since -1 can't be used.  For example, Y2 could be less than Y.
    ElseIf *HoldShapes\Type = #fd_Circle
      ;
      If X <> 0 : *HoldShapes\X = X : EndIf
      If Y <> 0 : *HoldShapes\Y = Y : EndIf
      If Width <> 0 : *HoldShapes\X2 = Int(Width / 2) : EndIf
      ;
    ElseIf *HoldShapes\Type = #fd_Box
      ;
      If X <> 0 : *HoldShapes\X = X : EndIf
      If Y <> 0 : *HoldShapes\Y = Y : EndIf
      If Width <> 0 : *HoldShapes\X2 = Width : EndIf
      If Height <> 0 : *HoldShapes\Y2 = Height : EndIf
      ;
    EndIf
    ;
  EndIf
  ;
  RedrawWindow_(WindowID(HoldForm\Window), 0, 0, #RDW_ERASE | #RDW_INVALIDATE | #RDW_ERASENOW)
  ;
EndProcedure
Procedure.l fd_LineGadget(Window.l, Gadget.l, X.l, Y.l, X2.l, Y2.l, Color.l)
  ; Window is the PureBasic identifier for the window receiving the line.
  *HoldShapes.s_fdShapes
  ;
  *HoldShapes = _fd_AddShape(Window, Gadget, #fd_Line, X, Y, X2, Y2, Color)
  ;
  ;        UseWindow()
  StartDrawing(WindowOutput(Window))
  LineXY(X, Y, X2, Y2, Color)
  StopDrawing()
  ;
EndProcedure
Procedure.l fd_CircleGadget(Window.l, Gadget.l, X.l, Y.l, Radius.l, Color.l)
  ; Window is the PureBasic identifier for the window receiving the line.
  *HoldShapes.s_fdShapes
  ;
  *HoldShapes = _fd_AddShape(Window, Gadget, #fd_Circle, X, Y, Radius, 0, Color)
  ;
  ;        UseWindow()
  StartDrawing(WindowOutput(Window))
  Circle(X, Y, Radius, Color)
  StopDrawing()
  ;
EndProcedure
Procedure.l fd_BoxGadget(Window.l, Gadget.l, X.l, Y.l, Width.l, Height.l, Color.l)
  ; Window is the PureBasic identifier for the window receiving the line.
  *HoldShapes.s_fdShapes
  ;
  *HoldShapes = _fd_AddShape(Window, Gadget, #fd_Box, X, Y, Width, Height, Color)
  ;
  ;        UseWindow()
  StartDrawing(WindowOutput(Window))
  Box(X, Y, Width, Height)
  StopDrawing()
  ;
EndProcedure
Procedure fd_RemoveWindow(Window.l)
  ; Remove all drawn gadgets from a window.
  CaughtForm.b
  ;
  NewArray.l
  ;
  
  ;
  
  ;
  *HoldForm.s_fdForm
  ;
  *HoldShapes.s_fdShapes
  ;
  *Position = _fDraw\Form
  While *Position - _fDraw\Form < _fDraw\Size
    ;
    *HoldForm = PeekL(*Position)
    ;
    If *HoldForm\Window = Window
      ;
      SetWindowLong_(WindowID(Window), #GWL_WNDPROC, *HoldForm\CallBack)
      ;
      CaughtForm = #True
      ;
      Break
      ;
    EndIf
    ;
    *Position + 4
    ;
  Wend
  ;
  If CaughtForm
    ;
    *PositionSub = *HoldForm\Shapes
    While *PositionSub - *HoldForm\Shapes < *HoldForm\Size
      ;
      FreeMemory(PeekL(*PositionSub))
      ;
      *PositionSub + 4
      ;
    Wend
    ;
    FreeMemory(*HoldForm\Shapes)
    ;
    If _fDraw\Count = 1
      ; This is the only window in the array.
      FreeMemory(_fDraw\Form) : _fDraw\Form = 0
      ;
      _fDraw\Count = 0 : _fDraw\Size = 0
      ;
    Else
      ;
      NewArray = AllocateMemory(_fDraw\Size - 4)
      ;
      *NewPosition = NewArray
      ;
      *Position = _fDraw\Form
      While *Position - _fDraw\Form < _fDraw\Size
        ;
        If PeekL(*Position) <> *HoldForm
          ;
          PokeL(*NewPosition, PeekL(*Position))
          ;
          *NewPosition + 4
          ;
        EndIf
        ;
        *Position + 4
        ;
      Wend
      ;
      FreeMemory(*HoldForm)
      ;
      FreeMemory(_fDraw\Form) : _fDraw\Form = NewArray
      ;
      _fDraw\Size - 4 : _fDraw\Count - 1
      ; Decrement the size and count of the forms to show the removed window.
    EndIf
    ;
    RedrawWindow_(WindowID(Window), 0, 0, #RDW_ERASE | #RDW_INVALIDATE | #RDW_ERASENOW)
    ;
  EndIf
  ;
EndProcedure
Procedure fd_Destroy()
  ;
  
  ;
  
  ;
  *HoldForm.s_fdForm
  ;
  *HoldShapes.s_fdShapes
  ;
  *Position = _fDraw\Form
  While *Position - _fDraw\Form < _fDraw\Size
    ;
    *HoldForm = PeekL(*Position)
    ;
    *PositionSub = *HoldForm\Shapes
    While *PositionSub - *HoldForm\Shapes < *HoldForm\Size
      ;
      FreeMemory(PeekL(*PositionSub))
      ;
      *PositionSub + 4
      ;
    Wend
    ;
    FreeMemory(*HoldForm\Shapes)
    ;
    SetWindowLong_(WindowID(*HoldForm\Window), #GWL_WNDPROC, *HoldForm\CallBack)
    RedrawWindow_(WindowID(*HoldForm\Window), 0, 0, #RDW_ERASE | #RDW_INVALIDATE | #RDW_ERASENOW)
    ;
    FreeMemory(*HoldForm)
    ;
    *Position + 4
    ;
  Wend
  ;
  FreeMemory(_fDraw\Form) : _fDraw\Form = 0
  ;
  _fDraw\Size = 0 : _fDraw\Count = 0
  ;
EndProcedure
Procedure fd_RemoveGadget(Gadget.l)
  ;
  ExistsGadget.l
  ;
  NewArray.l
  ;
  
  ;
  
  ;
  *HoldForm.s_fdForm
  ;
  *HoldShapes.s_fdShapes
  ;
  *Position = _fDraw\Form
  While *Position - _fDraw\Form < _fDraw\Size
    ;
    *HoldForm = PeekL(*Position)
    ;
    If *HoldForm\Count
      ;
      *PositionSub = *HoldForm\Shapes
      While *PositionSub - *HoldForm\Shapes < *HoldForm\Size
        ;
        *HoldShapes = PeekL(*PositionSub)
        ;
        If *HoldShapes\Gadget = Gadget
          ;
          ExistsGadget = #True
          ;
          Break 2
          ;
        EndIf
        ;
        *PositionSub + 4
        ;
      Wend
      ;
    EndIf
    ;
    *Position + 4
    ;
  Wend
  ;
  If ExistsGadget
    ;
    If *HoldForm\Count = 1
      ; There is only one shape in the array.
      fd_RemoveWindow(*HoldForm\Window)
      ; Remove the window and it's shapes from the arrays.
    Else
      ; More than one shape in the array.
      NewArray = AllocateMemory(*HoldForm\Size - 4)
      ;
      *NewPosition = NewArray
      ;
      *Position = *HoldForm\Shapes
      While *Position - *HoldForm\Shapes < *HoldForm\Size
        ;
        If PeekL(*Position) <> *HoldShapes
          ;
          PokeL(*NewPosition, PeekL(*Position))
          ;
          *NewPosition + 4
          ;
        EndIf
        ;
        *Position + 4
        ;
      Wend
      ;
      FreeMemory(*HoldShapes)
      ;
      FreeMemory(*HoldForm\Shapes) : *HoldForm\Shapes = NewArray
      ;
      *HoldForm\Count - 1 : *HoldForm\Size - 4
      ;
      RedrawWindow_(WindowID(*HoldForm\Window), 0, 0, #RDW_ERASE | #RDW_INVALIDATE | #RDW_ERASENOW)
      ;
    EndIf
    ;
  EndIf
  ;
EndProcedure
And there you have it. I haven't tested it extensively so I'm kind of worried about partial clipping and redrawing. I'm no graphics expert ^_^; I imagine it would be pretty easy to upgrade this to include snazzy drawing effects via some api or otherwise but I won't be doing that any time soon since all I really need was plain black lines ^_^
rsts
Addict
Addict
Posts: 2736
Joined: Wed Aug 24, 2005 8:39 am
Location: Southwest OH - USA

Post by rsts »

Wow. You're a coding machine. You just keep churning it out.

It's becoming rather redundant, but thanks for your many many contributions.

cheers
Post Reply