Automatic resizing of gadgets

Share your advanced PureBasic knowledge/code with the community.
User avatar
pf shadoko
Enthusiast
Enthusiast
Posts: 386
Joined: Thu Jul 09, 2015 9:07 am

Automatic resizing of gadgets

Post 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
User avatar
Lunasole
Addict
Addict
Posts: 1091
Joined: Mon Oct 26, 2015 2:55 am
Location: UA
Contact:

Re: Automatic resizing of gadgets

Post 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
"W̷i̷s̷h̷i̷n̷g o̷n a s̷t̷a̷r"
mestnyi
Addict
Addict
Posts: 1098
Joined: Mon Nov 25, 2013 6:41 am

Re: Automatic resizing of gadgets

Post 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
Last edited by mestnyi on Sun Apr 19, 2020 10:17 pm, edited 1 time in total.
ebs
Enthusiast
Enthusiast
Posts: 561
Joined: Fri Apr 25, 2003 11:08 pm

Re: Automatic resizing of gadgets

Post 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)
mestnyi
Addict
Addict
Posts: 1098
Joined: Mon Nov 25, 2013 6:41 am

Re: Automatic resizing of gadgets

Post 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

User avatar
Lunasole
Addict
Addict
Posts: 1091
Joined: Mon Oct 26, 2015 2:55 am
Location: UA
Contact:

Re: Automatic resizing of gadgets

Post by Lunasole »

@mestnyi, thank for your variant, nicely done (and ebs thank for enum improvement too ^^)
"W̷i̷s̷h̷i̷n̷g o̷n a s̷t̷a̷r"
Post Reply