Page 1 of 1

Automatic resizing of gadgets

Posted: Tue Aug 09, 2016 10:05 am
by pf shadoko
Hello,

I wrapped the functions relating to gadgets to enable them automatically resize when you resize the window
(There is not all gadgets, but you'll see it's very easy to add more)
it also works in SB

Code: Select all

EnableExplicit

;############################################################################################################################
;                             Automatic resizing of gadgets - pf shadoko - 2016
;
;   operation:
;   Instructions: OpenWindow, ButtonGadget, TextGadget, ..., CloseGadgetList
;   must be used With the suffix 'R'
;   2 additional parameters: rx And ry match the type of resizing:
;   rx / ry = 0: no change
;   rx / ry = 1: modification of the x / y position
;   rx / ry = 2: changing the width / height
;   rx / ry = 3: proportional positioning
;  (Rx / ry = 4: proportional positioning one side)
;  (Rx / ry = 5: proportional positioning of the other side)
;############################################################################################################################

Structure GadgetInfo
  g.i             ;gadgetID
  Map Glist.s()   ;list of contained gadgets  (for containers)
  x.w:  y.w       ;position of origin
  dx.w: dy.w      ;dimension of origin
  rx.b : ry.b     ;type of resize
EndStructure

Global Dim GadgetCont.s(256), GadgetConti
Global NewMap GadgetList.GadgetInfo()

Procedure Redimensioner(c, nx, ny, ndx, ndy, t.s="G")
  Protected.w ox1,oy1, ox2,oy2, x1,y1, x2,y2
  Protected gi.GadgetInfo, o.GadgetInfo,  adx,ady,  r.f,d.w 
  Macro RedimensionerD(t, v1, V2, oV1, oV2, adV, ndV)
    d = ndV - adV
    r = ndV / adV
    Select t
      Case 0: v1 = oV1:       V2 = oV2
      Case 1: v1 = oV1 + d:   V2 = oV2 + d
      Case 2: v1 = oV1:       V2 = oV2 + d
      Case 3: v1 = oV1 * r:   V2 = oV2 * r
      Case 4: v1 = oV1:       V2 = oV2 * r
      Case 5: v1 = oV1 * r:   V2 = oV2 + d
    EndSelect
  EndMacro
  gi=GadgetList(t+Str(c))
  adx = gi\dx
  ady = gi\dy
  ForEach gi\Glist():o=GadgetList(gi\Glist())
       If (o\rx Or o\ry)
           ox1 = o\x: ox2 = ox1 + o\dx: RedimensionerD (o\rx, x1, x2, ox1, ox2, adx, ndx)
           oy1 = o\y: oy2 = oy1 + o\dy: RedimensionerD (o\ry, y1, y2, oy1, oy2, ady, ndy)
           Redimensioner (o\g, x1, y1, x2 - x1, y2 - y1)
       EndIf
  Next
  If t="G":ResizeGadget(c,nx, ny, ndx, ndy):EndIf
EndProcedure

Procedure GadgetInfo(na,n,x.w,y.w,dx.w,dy.w,rx.b,ry.b,iscontainer=0)
  Protected gi.GadgetInfo, tg.s
  With gi
    If n=-1:\g=na:Else:\g=n:EndIf
    \x=x: \dx=dx: \rx=rx
    \y=y: \dy=dy: \ry=ry
    If iscontainer=-1
      tg="W"+Str(\g):GadgetConti=0 
    Else
      tg="G"+Str(\g):GadgetList(GadgetCont(GadgetConti))\Glist(tg)=tg
    EndIf
    GadgetList(tg)=gi
    If iscontainer:GadgetConti+1:GadgetCont(GadgetConti)=tg :EndIf
    ProcedureReturn \g
  EndWith
EndProcedure

;--------------------------------- gadgets
Procedure ButtonGadgetR(n,x,y,dx,dy,txt.s,f=0,rx=0,ry=0)
  Protected na=ButtonGadget(n,x,y,dx,dy,txt,f)
  ProcedureReturn GadgetInfo(na,n,x,y,dx,dy,rx,ry)
EndProcedure

Procedure TextGadgetR(n,x,y,dx,dy,txt.s,f=0,rx=0,ry=0)
  Protected na=TextGadget(n,x,y,dx,dy,txt,f)
  ProcedureReturn GadgetInfo(na,n,x,y,dx,dy,rx,ry)
EndProcedure

Procedure CheckBoxGadgetR(n,x,y,dx,dy,txt.s,f=0,rx=0,ry=0)
  Protected na=CheckBoxGadget(n,x,y,dx,dy,txt,f)
  ProcedureReturn GadgetInfo(na,n,x,y,dx,dy,rx,ry)
EndProcedure

Procedure StringGadgetR(n,x,y,dx,dy,txt.s,f=0,rx=0,ry=0)
  Protected na=StringGadget(n,x,y,dx,dy,txt,f)
  ProcedureReturn GadgetInfo(na,n,x,y,dx,dy,rx,ry)
EndProcedure

Procedure EditorGadgetR(n,x,y,dx,dy,f=0,rx=0,ry=0)
  Protected na=EditorGadget(n,x,y,dx,dy,f)
  ProcedureReturn GadgetInfo(na,n,x,y,dx,dy,rx,ry)
EndProcedure

Procedure ButtonImageGadgetR(n,x,y,dx,dy,imageID,f=0,rx=0,ry=0)
  Protected na=ButtonImageGadget(n,x,y,dx,dy,imageID,f)
  ProcedureReturn GadgetInfo(na,n,x,y,dx,dy,rx,ry)
EndProcedure

;--------------------------------- containers
Procedure ContainerGadgetR(n,x,y,dx,dy,f=0,rx=0,ry=0)
  Protected na=ContainerGadget(n,x,y,dx,dy,f)
  ProcedureReturn GadgetInfo(na,n,x,y,dx,dy,rx,ry,1)
EndProcedure

Procedure PanelGadgetR(n,x,y,dx,dy,rx=0,ry=0)
  Protected na=PanelGadget(n,x,y,dx,dy)
  ProcedureReturn GadgetInfo(na,n,x,y,dx,dy,rx,ry,1)
EndProcedure

Procedure ScrollAreaGadgetR(n,x,y,dx,dy,scrolldx,scrolldy,scrollstep,f=0,rx=0,ry=0)
  Protected na=ScrollAreaGadget(n,x,y,dx,dy,scrolldx,scrolldy,scrollstep,f)
  ProcedureReturn GadgetInfo(na,n,x,y,dx,dy,rx,ry,1)
EndProcedure

;--------------------------------- window
Procedure WindowResizeEvent()
  Protected n=EventWindow()
  Redimensioner(n,0,0,WindowWidth(n), WindowHeight(n),"W")
EndProcedure

Procedure OpenWindowR(n,x,y,dx,dy,txt.s,f=#PB_Window_SystemMenu,pid=0)
  Protected na=OpenWindow(n,x,y,dx,dy,txt,f,pid)
  Protected nw=GadgetInfo(na,n,x,y,dx,dy,2,2,-1)
  BindEvent(#PB_Event_SizeWindow,@WindowResizeEvent(), nw)
  ProcedureReturn nw
EndProcedure

;---------------------------------
Procedure CloseGadgetListR() 
  CloseGadgetList()
  GadgetConti-1
EndProcedure

;############################################################################################################################
;                                                 Exemple
;############################################################################################################################


CreateImage(0,200,60):StartDrawing(ImageOutput(0)):Define i:For i=0 To 200:Circle(100,30,200-i,(i+50)*$010101):Next:StopDrawing()

OpenWindowR(0, 0, 0, 512, 200, "Resize gadget",#PB_Window_ScreenCentered | #PB_Window_SizeGadget) 


  TextGadgetR(1, 10,  10, 200, 50, "Resize the window, the gadgets will be automatically resized",#PB_Text_Center)
  ButtonImageGadgetR(3, 10, 70, 200, 60, ImageID(0),0,0,0)
    EditorGadgetR(2, 10,  140, 200, 20, 0,0,2):SetGadgetText(2,"Editor")
    ButtonGadgetR(4, 10, 170, 490, 20, "Button / toggle", #PB_Button_Toggle,2,1)
   TextGadgetr(5,220,10,190,20,"Text",#PB_Text_Center,2,0):SetGadgetColor(5, #PB_Gadget_BackColor, $00FFFF)
   ContainerGadgetR(6, 220, 30, 190, 100,#PB_Container_Single,2,2):SetGadgetColor(6, #PB_Gadget_BackColor, $cccccc) 
     EditorGadgetR(7, 10,  10, 170, 50, 0,2,2):SetGadgetText(7,"Editor")
     ButtonGadgetR(8, 10, 70, 80, 20, "Button",0,4,1) 
     ButtonGadgetR(9, 100, 70, 80, 20, "Button",0,5,1) 
   CloseGadgetListR() 
   StringGadgetR(10, 220,  140, 190, 20, "String",0,2,1)
   ButtonGadgetR(11, 420,  10, 80, 80, "Bouton",0,1,2)
   CheckBoxGadgetR(12, 420,  90, 200, 20, "CheckBox",0,1,1)
   CheckBoxGadgetR(13, 420,  110, 200, 20, "CheckBox",0,1,1)
   CheckBoxGadgetR(14, 420,  130, 200, 20, "CheckBox",0,1,1)
   CheckBoxGadgetR(15, 420,  150, 200, 20, "CheckBox",0,1,1)

Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow

Re: Automatic resizing of gadgets

Posted: Tue Aug 09, 2016 4:02 pm
by Lunasole
Thanks for posting, useful stuff and seems to work nice ^^
I'm going to post similar code to automate program UI localization (easily switch between languages on fly), but didn't make it clear enough yet

Btw you can directly replace PB library functions this way, to keep original syntax tip in IDE:

Code: Select all

Macro ButtonGadget(id, x, y, w, h, txt, flags = 0)
	Debug txt
	; and call original ButtonGadget + do other code
EndMacro

ButtonGadget(1, 2, 3, 4, 5, "test") ; the syntax tip here is like original ButtonGadget, but your macro is used instead

Re: Automatic resizing of gadgets

Posted: Tue Aug 09, 2016 6:38 pm
by mestnyi

Code: Select all

EnableExplicit

DeclareModule RS
  ;############################################################################################################################
  ;                             Automatic resizing of gadgets - pf shadoko - 2016
  ;
  ;   operation:
  ;   Instructions: OpenWindow, ButtonGadget, TextGadget, ..., CloseGadgetList
  ;   must be used With the suffix 'R'
  ;   2 additional parameters: rx And ry match the type of resizing:
  ;   rx / ry = 0: no change
  ;   rx / ry = 1: modification of the x / y center
  ;   rx / ry = 2: modification of the x / y position
  ;   rx / ry = 3: changing the width / height
  ;   rx / ry = 4: proportional positioning one side
  ;   rx / ry = 5: proportional positioning of the other side
  ;   rx / ry = 6: proportional positioning
  ;
  ;  http://forums.purebasic.com/english/viewtopic.php?f = 12&t = 66353
  ;############################################################################################################################

  Declare Register(n, rx.b, ry.b)
  Declare Resize(_n_, _x_, _y_, _width_, _height_, _type_.s = "G")
EndDeclareModule

Module RS
  Structure _s_resize
    g.i                 ; gadgetID
    
    x.w     : y.w       ; position of origin
    width.w : height.w  ; dimension of origin
    
    rx.b : ry.b         ; type of resize
    Map Glist.s()       ; list of contained gadgets (for containers)
  EndStructure
  
  Global NewMap RS._s_resize()
  
  Procedure Resize(_n_, _x_, _y_, _width_, _height_, _type_.s = "G")
    Macro ResizeD(_type_, v1, ov1, v2, ov2, adv, ndv)
      d = ndv - adv 
      Select _type_
        Case 0  : v1 = ov1                               : v2 = ov2
        Case 1  : v1 = ov1 + d/2                         : v2 = ov2 + d/2   ; center (right & bottom)
        Case 2  : v1 = ov1 + d                           : v2 = ov2 + d     ; right & bottom
        Case 3  : v1 = ov1                               : v2 = ov2 + d     ; full (right & bottom)
        Case 4  : v1 = ov1                               : v2 = ov2 * ndv / (adv + (ov2-adv/2)*2) : v2 + (ov2-adv/2)
        Case 5  : v1 = ov1 * ndv / adv                   : v2 = ov2 * ndv / adv
        Case 6  : v1 = ov1 * ndv / (adv + (ov1-adv/2)*2) : v2 = ov2 + d                           : v1 + (ov1-adv/2)
      EndSelect
    EndMacro
    
    Protected.w x1,y1, x2,y2, d
    Protected p._s_resize = RS(_type_ + Str(_n_))
    
    With RS(p\Glist())
      ForEach p\Glist()
        ; If (\rx Or \ry)
        ResizeD (\rx, x1, \x, x2, (\x+\width), p\width, _width_)
        ResizeD (\ry, y1, \y, y2, (\y+\height), p\height, _height_)
        
        Resize (\g, x1, y1, x2 - x1, y2 - y1)
        ; EndIf
      Next
    EndWith
    
    If _type_ = "G"
      ResizeGadget(_n_, _x_, _y_, _width_, _height_)
    EndIf
  EndProcedure
  
  Procedure Register(n, rx.b, ry.b)
    Protected p._s_resize, tg.s, window = GetActiveWindow()
    Static Parent.S
    
    With p
      \g = n
      \rx = rx
      \ry = ry
      
      tg = "W" + Str(window)
      
      If Not FindMapElement(RS(), tg)
        If IsWindow(window)
          \x = WindowX(window)
          \y = WindowY(window)
          \width = WindowWidth(window)
          \height = WindowHeight(window)
          
          Parent.S = tg
          RS(tg) = p
        EndIf
      EndIf
      
      If IsGadget(\g) 
        tg = "G" + Str(\g)
        RS(Parent.S)\Glist(tg) = tg
        
        \x = GadgetX(\g)
        \y = GadgetY(\g)
        \width = GadgetWidth(\g)
        \height = GadgetHeight(\g)
        
        Select GadgetType(\g) 
          Case #PB_GadgetType_Panel,
               #PB_GadgetType_Canvas,
               #PB_GadgetType_Container,
               #PB_GadgetType_ScrollArea
            Parent.S = tg
        EndSelect
        
        RS(tg) = p
      EndIf
      
      
      ProcedureReturn \g
    EndWith
  EndProcedure
EndModule

;-
;- EXAMPLE
;-
Procedure WindowResizeEvent()
  Protected n = EventWindow()
  RS::Resize(n, 0,0,WindowWidth(n), WindowHeight(n),"W")
EndProcedure

Procedure example_0()
  OpenWindow(0, 0, 0, 190, 200, "Resize gadget", #PB_Window_ScreenCentered | #PB_Window_SizeGadget) 
  BindEvent(#PB_Event_SizeWindow, @WindowResizeEvent(), 0)
  
  ButtonGadget(2, 55, 5, 80, 20, "center")    ; center
  ButtonGadget(3, 55, 25, 80, 20, "right")    ; right
  ButtonGadget(4, 55, 45, 80, 20, "stretch")  ; stretch
  
  ButtonGadget(5, 55, 65, 80, 20, ">>|<<")    ; proportional
  
  ButtonGadget(8, 10, 90, 80, 20, ">>|", #PB_Button_Right) ; proportional
  ButtonGadget(9, 100, 90, 80, 20, "|<<", #PB_Button_Left) ; proportional
  
  RS::Register(2,1,4) ; center
  RS::Register(3,2,1) ; right
  RS::Register(4,3,6) ; stretch
  
  RS::Register(5,5,2) ; proportional
  
  RS::Register(8,4,2) ; proportional right
  RS::Register(9,6,2) ; proportional left
EndProcedure

Procedure example_1()
  Define i
  CreateImage(0,200,60) 
  StartDrawing(ImageOutput(0))
  For i=0 To 200
    Circle(100, 30, 200-i, (i+50)*$010101)
  Next
  StopDrawing()
  
  OpenWindow(1, 0, 0, 512, 200, "Resize gadget",#PB_Window_ScreenCentered | #PB_Window_SizeGadget) 
  BindEvent(#PB_Event_SizeWindow, @WindowResizeEvent(), 1)
  
  TextGadget(1, 10,  10, 200, 50, "Resize the window, the gadgets will be automatically resized", #PB_Text_Center)
  ButtonImageGadget(3, 10, 70, 200, 60, ImageID(0))
  EditorGadget(2, 10,  140, 200, 20) : SetGadgetText(2,"Editor")
  ButtonGadget(4, 10, 170, 490, 20, "Button / toggle", #PB_Button_Toggle)
  TextGadget(5,220,10,190,20,"Text", #PB_Text_Center) : SetGadgetColor(5, #PB_Gadget_BackColor, $00FFFF)
  ContainerGadget(6, 220, 30, 190, 100, #PB_Container_Single) : SetGadgetColor(6, #PB_Gadget_BackColor, $cccccc) 
  EditorGadget(7, 10,  10, 170, 50) : SetGadgetText(7,"Editor")
  ButtonGadget(8, 10, 70, 80, 20, "Button") 
  ButtonGadget(9, 100, 70, 80, 20, "Button") 
  CloseGadgetList() 
  StringGadget(10, 220,  140, 190, 20, "String")
  ButtonGadget(11, 420,  10, 80, 80, "Bouton")
  CheckBoxGadget(12, 420,  90, 200, 20, "CheckBox")
  CheckBoxGadget(13, 420,  110, 200, 20, "CheckBox")
  CheckBoxGadget(14, 420,  130, 200, 20, "CheckBox")
  CheckBoxGadget(15, 420,  150, 200, 20, "CheckBox")
  
  RS::Register(2,0,3)
  RS::Register(4,3,2)
  RS::Register(5,3,0)
  RS::Register(6,3,3)
  RS::Register(7,3,3)
  RS::Register(8,4,2)
  RS::Register(9,6,2)
  RS::Register(10,3,2)
  RS::Register(11,2,3)
  RS::Register(12,2,2)
  RS::Register(13,2,2)
  RS::Register(14,2,2)
  RS::Register(15,2,2)
EndProcedure

example_0()

Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow

Re: Automatic resizing of gadgets

Posted: Wed Aug 10, 2016 2:44 pm
by ebs
Thanks to pf shadoko for the original idea and to mestnyi for his simplification.
Here's my small change; no actual code change, just some constants to make it easier to see the type of resizing being used.

Add this enumeration to at the top of the code:

Code: Select all

Enumeration Redimensioner
  #RDM_NOCHANGE
  #RDM_XYPOS
  #RDM_WIDTHHEIGHT
  #RDM_PROPPOS
  #RDM_PROPONESIDE
  #RDM_PROPOTHERSIDE
EndEnumeration
and then set the resizing properties for the gadgets like this:

Code: Select all

GadgetInfo(2, #RDM_NOCHANGE, #RDM_WIDTHHEIGHT)
GadgetInfo(4, #RDM_WIDTHHEIGHT, #RDM_XYPOS)
GadgetInfo(5, #RDM_WIDTHHEIGHT, #RDM_NOCHANGE)
GadgetInfo(6, #RDM_WIDTHHEIGHT, #RDM_WIDTHHEIGHT)
GadgetInfo(7, #RDM_WIDTHHEIGHT, #RDM_WIDTHHEIGHT)
GadgetInfo(8, #RDM_PROPONESIDE, #RDM_XYPOS)
GadgetInfo(9, #RDM_PROPOTHERSIDE, #RDM_XYPOS)
GadgetInfo(10, #RDM_WIDTHHEIGHT, #RDM_XYPOS)
GadgetInfo(11, #RDM_XYPOS, #RDM_WIDTHHEIGHT)
GadgetInfo(12, #RDM_XYPOS, #RDM_XYPOS)
GadgetInfo(13, #RDM_XYPOS, #RDM_XYPOS)
GadgetInfo(14, #RDM_XYPOS, #RDM_XYPOS)
GadgetInfo(15, #RDM_XYPOS, #RDM_XYPOS)

Re: Automatic resizing of gadgets

Posted: Wed Aug 10, 2016 3:36 pm
by mestnyi
Here is what you need?

Code: Select all

Global Dim GadgetCont.s(256), GadgetConti
When works like this, you can explain or comment on your code? It is not the usual realization that you have amazing work is not bad. :)

Code: Select all

Procedure GadgetInfo(n,rx.b,ry.b)
  Static Parent.S
  Protected gi.GadgetInfo, tg.s
  
  With gi
    \g=n
    \rx=rx
    \ry=ry
    
    If IsGadget(\g) : tg="G"+Str(\g)
      GadgetList(Parent.S)\Glist(tg)=tg
      
      \x = GadgetX(\g)
      \y = GadgetY(\g)
      \dx = GadgetWidth(\g)
      \dy = GadgetHeight(\g)
      
      Select GadgetType(\g) 
        Case #PB_GadgetType_Panel,
             #PB_GadgetType_Container,
             #PB_GadgetType_ScrollArea
          Parent.S = tg
      EndSelect
      
    Else : tg="W"+Str(\g)
      \x = WindowX(\g)
      \y = WindowY(\g)
      \dx = WindowWidth(\g)
      \dy = WindowHeight(\g)
      Parent.S = tg
      
    EndIf
    
    GadgetList(tg)=gi
    
    ProcedureReturn \g
  EndWith
EndProcedure


Re: Automatic resizing of gadgets

Posted: Wed Aug 10, 2016 4:02 pm
by Lunasole
@mestnyi, thank for your variant, nicely done (and ebs thank for enum improvement too ^^)