Page 1 of 1

setAutoresizingMask

Posted: Wed Nov 30, 2016 10:43 pm
by Airr
It's been a long time since I've visited this forum, amazing how far PB has come since my last visit!

One of the things I've always wanted to be able to do is auto-size/anchor Gadgets like Interface Builder allows one to do.

So I downloaded the latest Mac beta of PB last night, and started playing. Here's what I have:

Code: Select all

;
; ------------------------------------------------------------
;
;   Live Gadget Auto Resizing Demo
;
; ------------------------------------------------------------
;

;
; Open a window, and try resizing it...
;

Enumeration
  #Window
  #Entry
  #Button
  #Editor
  #Combo
EndEnumeration

Enumeration
  #akNone
  #akRight                        ; anchor to right side of Window, no resize
  #akWidth                        ; resize width of Gadget, based on width of Window
  #akLeft = 4                     ; anchor to left side of Window, no resize
  #akTop = 8                      ; anchor to top of Window, no resize
  #akHeight = 16                  ; resize height of Gadget, based on height of Window
  #akFull = #akWidth | #akHeight  ; resize width/height of Gadget, based on width/height of Window
EndEnumeration


Procedure Anchor (handle, value)
  Define tmp
  Select GadgetType(handle)
    Case  #PB_GadgetType_Editor
      ; EDITOR GADGET IS COMPOSED OF NSTEXTVIEW->NSCLIPVIEW->NSSCROLLVIEW HIERARCHY
      ; So we have to traverse the hierarchy to get the actual NSScrollView object
      tmp = CocoaMessage(0,CocoaMessage(0, GadgetID(handle),"superview"),"superview")
      
    Default
      tmp = GadgetID(handle)
  EndSelect
  
  CocoaMessage(0,tmp, "setAutoresizingMask:", value)  
EndProcedure

If OpenWindow(#Window, 100, 200, 800, 600, "Live Gadget Auto Resizing Demo", #PB_Window_ScreenCentered | #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget)
  
  ; Set minimum window size
  Define con.CGSize
  con\width = 800
  con\height = 622
  CocoaMessage(0,WindowID(#Window), "setMinSize:@", @con)
  
  Top = 16
  GadgetHeight = 24

  StringGadget(#Entry,  20, Top, 670, GadgetHeight, "Hello, World")
  ButtonGadget(#Button, 710, Top-2, 70, GadgetHeight+4, "Click")
  
  ComboBoxGadget(#Combo, 573, 50, 120, GadgetHeight)
  AddGadgetItem(#Combo, -1, "Apples")
  AddGadgetItem(#Combo, -1, "Oranges")
  AddGadgetItem(#Combo, -1, "Peaches")
  SetGadgetState(#Combo,1)
  
  EditorGadget(#Editor, 20, 90,670, 480)
  
  ; Set up auto-resizing by specifying how Gadget is to be anchored in Window
  Anchor(#Button,#akRight)
  Anchor(#Entry,#akWidth)
  Anchor(#Combo, #akRight)
  Anchor(#Editor, #akFull)

  Repeat
    Event = WaitWindowEvent()
  
    If Event = #PB_Event_CloseWindow
      Quit = 1
    EndIf

  Until Quit = 1
  
EndIf

End
What I like about this, is that the native Cocoa runtime is handling the resizing, so it's generally flicker-free.

I'd be interested in hearing what everyone thinks, and please excuse any sloppiness on my part.

AIR.

Re: setAutoresizingMask

Posted: Wed Nov 30, 2016 11:51 pm
by WilliamL
Interesting

How about an ImageGadget()?

Re: setAutoresizingMask

Posted: Thu Dec 01, 2016 1:05 am
by Airr
WilliamL wrote:How about an ImageGadget()?

Code: Select all

Procedure Anchor (handle, value)
  Define tmp
  Select GadgetType(handle)
    Case  #PB_GadgetType_Editor
      ; EDITOR GADGET IS COMPOSED OF NSTEXTVIEW->NSCLIPVIEW->NSSCROLLVIEW HIERARCHY
      ; So we have to traverse the hierarchy to get the actual NSScrollView object
      tmp = CocoaMessage(0,CocoaMessage(0, GadgetID(handle),"superview"),"superview")
      
    Case #PB_GadgetType_Image
      ; This will cause the image to scale proportionally
      ; To scale-to-fit, use "1"
      CocoaMessage(0,GadgetID(handle),"setImageScaling:",3)
      tmp = GadgetID(handle)   
      
    Default
      tmp = GadgetID(handle)
  EndSelect
  
  CocoaMessage(0,tmp, "setAutoresizingMask:", value)  
EndProcedure

Re: setAutoresizingMask

Posted: Thu Dec 01, 2016 1:22 am
by WilliamL
Works great! I like the use of the constants to define where the field goes and how small the code is.

Here is your code with some of additions:

Code: Select all

Enumeration
  #Window
  #Entry
  #Button
  #Editor
  #Combo
  #imagegadget
EndEnumeration

Enumeration
  #akNone
  #akRight                        ; anchor to right side of Window, no resize
  #akWidth                        ; resize width of Gadget, based on width of Window
  #akLeft = 4                     ; anchor to left side of Window, no resize
  #akTop = 8                      ; anchor to top of Window, no resize
  #akHeight = 16                  ; resize height of Gadget, based on height of Window
  #akFull = #akWidth | #akHeight  ; resize width/height of Gadget, based on width/height of Window
  #akBottom = #akTop|#akWidth     ; attached to bottom of window
EndEnumeration

Procedure Anchor (handle, value)
  Define tmp
  Select GadgetType(handle)
    Case  #PB_GadgetType_Editor,#PB_GadgetType_ListView, #PB_GadgetType_ListIcon, #PB_GadgetType_Tree
      ; EDITOR GADGET IS COMPOSED OF NSTEXTVIEW->NSCLIPVIEW->NSSCROLLVIEW HIERARCHY
      ; So we have to traverse the hierarchy to get the actual NSScrollView object
        tmp = CocoaMessage(0, GadgetID(handle),"enclosingScrollView")
    Case #PB_GadgetType_Image
      ; This will cause the image to scale proportionally
      ; To scale-to-fit, use "1"
      CocoaMessage(0,GadgetID(handle),"setImageScaling:",1)
      tmp = GadgetID(handle)  ;   Live Gadget Auto Resizing Demo
    Default
      tmp = GadgetID(handle)
  EndSelect
  
  CocoaMessage(0,tmp, "setAutoresizingMask:", value)  
EndProcedure

If OpenWindow(#Window, 100, 200, 800, 600, "Live Gadget Auto Resizing Demo", #PB_Window_ScreenCentered | #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget)
  ; Set minimum window size
  WindowBounds(#Window, 800, 622, #PB_Default, #PB_Default)
  
  Top = 16
  GadgetHeight = 24

  StringGadget(#Entry,  20, Top, 670, GadgetHeight, "Hello, World")
  ButtonGadget(#Button, 710, Top-2, 70, GadgetHeight+4, "Click")
  
  ComboBoxGadget(#Combo, 573, 50, 120, GadgetHeight)
  AddGadgetItem(#Combo, -1, "Apples")
  AddGadgetItem(#Combo, -1, "Oranges")
  AddGadgetItem(#Combo, -1, "Peaches")
  SetGadgetState(#Combo,1)
  
  ;EditorGadget(#Editor, 20, 90,670, 280)
  ListViewGadget(#Editor, 20, 90,670, 280)
  
  CreateImage(image_id,200,200)
  StartDrawing(ImageOutput(image_id))
  Box(0,0,100,100,0)
  StopDrawing()
  ImageGadget(#ImageGadget,20,380,670,200,ImageID(image_id))
  
  ; Set up auto-resizing by specifying how Gadget is to be anchored in Window
  Anchor(#Button,#akRight)
  Anchor(#Entry,#akWidth)
  Anchor(#Combo, #akRight)
  Anchor(#Editor, #akFull)
  ;Anchor(#ImageGadget, #akFull) ; works but top is over-laid by above
  Anchor(#ImageGadget,#akBottom) ; width only changes
  
  Repeat
    Event = WaitWindowEvent()
  
    If Event = #PB_Event_CloseWindow
      Quit = 1
    EndIf

  Until Quit = 1
EndIf

Re: setAutoresizingMask

Posted: Thu Dec 01, 2016 3:52 am
by Airr
Ok, in the Anchor proc, change the "3" to a "1" in the call to "setImageScaling"

Then change

Code: Select all

Anchor(#ImageGadget, #akFull)
to

Code: Select all

Anchor(#ImageGadget, #akTop|#akWidth)
I should note that "#akTop" anchors the widget proportionally to the top or the "Y" axis. So it will push the gadget towards the bottom as the window grows. I guess it might make more sense to define it as "#akBottom" so that it's more intuitive.

Re: setAutoresizingMask

Posted: Thu Dec 01, 2016 5:50 am
by Airr
I decided to give this a try with the PureBasic Gadget Demo source.

Since I couldn't attach files, I created a Gist instead

Give it a try and let me know what you think....

AIR

Re: setAutoresizingMask

Posted: Thu Dec 01, 2016 6:17 am
by wilbert
The common way to get the scroll view is like this

Code: Select all

  Select GadgetType(handle)
    Case  #PB_GadgetType_Editor
      tmp = CocoaMessage(0, GadgetID(handle),"enclosingScrollView")
    Default
      tmp = GadgetID(handle)
  EndSelect

Re: setAutoresizingMask

Posted: Thu Dec 01, 2016 6:28 am
by Airr
tmp = CocoaMessage(0, GadgetID(handle),"enclosingScrollView")
Thanks! Much cleaner!

AIR.

Re: setAutoresizingMask

Posted: Thu Dec 01, 2016 6:22 pm
by WilliamL
this appears to work with the ListViewGadget also...

Code: Select all

    Case  #PB_GadgetType_Editor,#PB_GadgetType_ListView
        tmp = CocoaMessage(0, GadgetID(handle),"enclosingScrollView")

Re: setAutoresizingMask

Posted: Thu Dec 01, 2016 8:23 pm
by Airr
Yes, updated the Gist last night with the following:

Code: Select all

    Case  #PB_GadgetType_Editor, #PB_GadgetType_ListView, #PB_GadgetType_ListIcon, #PB_GadgetType_Tree
      ; THE GADGETS ABOVE ARE COMPOSED OF PBGADGET->NSCLIPVIEW->NSSCROLLVIEW HIERARCHY
      ; So we have to retrieve the actual NSScrollView object to resize
      tmp = CocoaMessage(0, GadgetID(handle),"enclosingScrollView")

Re: setAutoresizingMask

Posted: Thu Dec 01, 2016 9:52 pm
by fsw
Cool stuff :!:

One thing:

This is not really needed:

Code: Select all

  ; Set minimum window size
  Define con.CGSize
  con\width = 800
  con\height = 622
  CocoaMessage(0,WindowID(#Window), "setMinSize:@", @con)
as there is the built-in WindowBounds() command:

Code: Select all

  ; Set minimum window size
  WindowBounds(#Window, 800, 622, #PB_Default, #PB_Default)
Keep up the good work :D

Re: setAutoresizingMask

Posted: Thu Dec 01, 2016 9:58 pm
by Airr
Thanks, will replace what I have with the built-in command.