The following procedure is used by the PureBasic IDE to adjust gadget sizes to fit the text they contain. This allows the IDE dialogs to look good with any font size and also allows translated text to fit even if it is longer than the default text.
Of course with this you need a more complex code to arrange/resize the gadgets, but as you can see below when this is done you can even change the font (or gadget content) on the fly and easily resize the gadgets to fit.
Code: Select all
;
; Calculates the size required to display a Gadget properly.
;
; Supported Gadgets:
; Button, Checkbox, Option, Text, String, ComboBox, Image
;
; Note:
; For Gadgets with variable content (String, ComboBox), only the returned height
; is useful, as the width will only be an absolute minimum value.
;
; The 'Flags' parameter gives gadget flags to include in the calculation.
; Currently only #PB_Text_Border makes a difference there.
;
CompilerIf Defined(Max, #PB_Procedure) = 0
Procedure Max(a, b)
If a > b
ProcedureReturn a
Else
ProcedureReturn b
EndIf
EndProcedure
CompilerEndIf
CompilerIf #PB_Compiler_OS = #PB_OS_Linux
Structure PB_Gadget
*Gadget.GtkWidget
*Container.GtkWidget
*VT
UserData.i
GadgetData.i[4]
EndStructure
CompilerEndIf
CompilerIf #PB_Compiler_OS = #PB_OS_MacOS
Structure OSX_Rect
top.w
left.w
bottom.w
right.w
EndStructure
#noErr = 0
CompilerEndIf
; Stores the result in *Width\l and *Height\l
;
Procedure GetRequiredSize(Gadget, *Width.LONG, *Height.LONG, Flags = 0)
CompilerSelect #PB_Compiler_OS
CompilerCase #PB_OS_Windows
DC = GetDC_(GadgetID(Gadget))
oldFont = SelectObject_(DC, GetGadgetFont(Gadget))
Size.SIZE
Select GadgetType(Gadget)
Case #PB_GadgetType_Text
Text$ = RemoveString(GetGadgetText(Gadget), Chr(10))
count = CountString(Text$, Chr(13)) + 1
empty = 0
maxheight = 0
For index = 1 To count
Line$ = StringField(Text$, index, Chr(13))
If Line$ = ""
empty + 1
Else
GetTextExtentPoint32_(DC, @Line$, Len(Line$), @LineSize.SIZE)
Size\cx = Max(Size\cx, LineSize\cx)
Size\cy + LineSize\cy
maxheight = Max(maxheight, LineSize\cy)
EndIf
Next index
Size\cy + empty * maxheight
If Flags & #PB_Text_Border
Size\cx + GetSystemMetrics_(#SM_CXEDGE) * 2
Size\cy + GetSystemMetrics_(#SM_CYEDGE) * 2
Else
Size\cx + 2
Size\cy + 2
EndIf
Case #PB_GadgetType_CheckBox, #PB_GadgetType_Option
Text$ = GetGadgetText(Gadget)
GetTextExtentPoint32_(DC, @Text$, Len(Text$), @Size.SIZE)
Size\cx + 20
Size\cy = Max(Size\cy+2, 20)
Case #PB_GadgetType_Button
Text$ = GetGadgetText(Gadget)
GetTextExtentPoint32_(DC, @Text$, Len(Text$), @Size.SIZE)
Size\cx + GetSystemMetrics_(#SM_CXEDGE)*2
Size\cy = Max(Size\cy+GetSystemMetrics_(#SM_CYEDGE)*2, 24)
Size\cx + 10
Case #PB_GadgetType_String
Text$ = GetGadgetText(Gadget) + "Hg"
GetTextExtentPoint32_(DC, @Text$, Len(Text$), @Size.SIZE)
Size\cx = GetSystemMetrics_(#SM_CXEDGE)*2
Size\cy = Max(Size\cy+GetSystemMetrics_(#SM_CXEDGE)*2, 20)
Case #PB_GadgetType_ComboBox
GetTextExtentPoint32_(DC, @"Hg", 2, @Size.SIZE)
Size\cy = Max(Size\cy + 8, 21)
Size\cx = Size\cy
Case #PB_GadgetType_Image
Size\cx = GadgetWidth(Gadget)
Size\cy = GadgetHeight(Gadget)
EndSelect
SelectObject_(DC, oldFont)
ReleaseDC_(GadgetID(Gadget), DC)
*Width\l = Size\cx
*Height\l = Size\cy
CompilerCase #PB_OS_Linux
*Gadget.PB_Gadget = IsGadget(Gadget)
If *Gadget And *Gadget\Container And GadgetType(Gadget) <> #PB_GadgetType_ComboBox
gtk_widget_size_request_(*Gadget\Container, @RealSize.GtkRequisition)
gtk_widget_set_size_request_(*Gadget\Container, -1, -1)
gtk_widget_size_request_(*Gadget\Container, @Size.GtkRequisition)
gtk_widget_set_size_request_(*Gadget\Container, RealSize\Width, RealSize\Height)
Else
gtk_widget_size_request_(GadgetID(Gadget), @RealSize.GtkRequisition)
gtk_widget_set_size_request_(GadgetID(Gadget), -1, -1)
gtk_widget_size_request_(GadgetID(Gadget), @Size.GtkRequisition)
gtk_widget_set_size_request_(GadgetID(Gadget), RealSize\Width, RealSize\Height)
EndIf
If GadgetType(Gadget) = #PB_GadgetType_ComboBox Or GadgetType(Gadget) = #PB_GadgetType_String
*Width\l = 20
Else
*Width\l = Size\Width
EndIf
*Height\l = Size\Height
CompilerCase #PB_OS_MacOS
Type = GadgetType(Gadget)
If Type = #PB_GadgetType_Image
*Width\l = GadgetWidth(Gadget)
*Height\l = GadgetHeight(Gadget)
ElseIf Type = #PB_GadgetType_Text
realwidth = GadgetWidth(Gadget)
*Width\l = 40
*Height\l = 20
ResizeGadget(Gadget, #PB_Ignore, #PB_Ignore, 1000, #PB_Ignore)
If GetBestControlRect_(GadgetID(Gadget), @Rect.OSX_Rect, @BaseLine.w) = #noErr
Height = Rect\bottom - Rect\top
If Height > 0
Min = 0
Max = 1000
While Max > Min+2
Mid = (Min + Max) / 2
ResizeGadget(Gadget, #PB_Ignore, #PB_Ignore, Mid, #PB_Ignore)
If GetBestControlRect_(GadgetID(Gadget), @Rect.OSX_Rect, @BaseLine.w) <> #noErr
ProcedureReturn
EndIf
If Rect\bottom - Rect\top > Height
Min = Mid
Else
Max = Mid
EndIf
Wend
*Width\l = Rect\right - Rect\left + 2
*Height\l = Max(Height, 20)
EndIf
EndIf
ResizeGadget(Gadget, #PB_Ignore, #PB_Ignore, realwidth, #PB_Ignore)
Else
If GetBestControlRect_(GadgetID(Gadget), @Rect.OSX_Rect, @BaseLine.w) = #noErr
*Width\l = Rect\right - Rect\left
*Height\l = Max(Rect\bottom - Rect\top, 20)
If Type = #PB_GadgetType_Button Or Type = #PB_GadgetType_String
*Height\l = Max(*Height\l, 24)
EndIf
Else
*Width\l = 40
*Height\l = 20
EndIf
If Type = #PB_GadgetType_String Or Type = #PB_GadgetType_ComboBox
*Width\l = 30
EndIf
EndIf
CompilerEndSelect
EndProcedure
; convinience wrappers if only one size is needed
;
Procedure GetRequiredWidth(Gadget, Flags = 0)
Protected Width.l, Height.l
GetRequiredSize(Gadget, @Width, @Height, Flags)
ProcedureReturn Width
EndProcedure
Procedure GetRequiredHeight(Gadget, Flags = 0)
Protected Width.l, Height.l
GetRequiredSize(Gadget, @Width, @Height, Flags)
ProcedureReturn Height
EndProcedure
Code: Select all
Enumeration
#Button_1
#Button_2
#Button_3
#Checkbox_1
#Checkbox_2
#Checkbox_3
#String
#ComboBox
#ChangeFont
EndEnumeration
Procedure Resize()
GetRequiredSize(#Button_1, @Button1Width.l, @Button1Height.l)
GetRequiredSize(#Button_2, @Button2Width.l, @Button2Height.l)
GetRequiredSize(#Button_3, @Button3Width.l, @Button3Height.l)
Height = Max(Button1Height, Max(Button2Height, Button3Height))
x = 10
y = 10
ResizeGadget(#Button_1, x, y, Button1Width, Height): x + Button1Width + 5
ResizeGadget(#Button_2, x, y, Button2Width, Height): x + Button2Width + 5
ResizeGadget(#Button_3, x, y, Button3Width, Height): x + Button3Width + 5
y + Height + 10
WindowWidth = x
GetRequiredSize(#Checkbox_1, @Check1Width.l, @Check1Height.l)
GetRequiredSize(#Checkbox_2, @Check2Width.l, @Check2Height.l)
GetRequiredSize(#Checkbox_3, @Check3Width.l, @Check3Height.l)
Width = Max(Check1Width, Max(Check2Width, Check3Width))
ResizeGadget(#Checkbox_1, 10, y, Width, Check1Height): y + Check1Height + 5
ResizeGadget(#Checkbox_2, 10, y, Width, Check2Height): y + Check2Height + 5
ResizeGadget(#Checkbox_3, 10, y, Width, Check3Height): y + Check3Height + 5
y + 5
WindowWidth = Max(WindowWidth, Width+20)
Height = GetRequiredHeight(#String)
ResizeGadget(#String, 10, y, WindowWidth-20, Height)
y + Height + 5
Height = GetRequiredHeight(#ComboBox)
ResizeGadget(#ComboBox, 10, y, WindowWidth-20, Height)
y + Height + 10
GetRequiredSize(#ChangeFont, @ButtonWidth.l, @ButtonHeight.l)
ResizeGadget(#ChangeFont, (WindowWidth-ButtonWidth)/2, y, ButtonWidth, ButtonHeight)
y + ButtonHeight + 10
ResizeWindow(0, #PB_Ignore, #PB_Ignore, WindowWidth, y)
EndProcedure
If OpenWindow(0, 100, 100, 0, 0, "Size test", #PB_Window_SystemMenu|#PB_Window_Invisible)
ButtonGadget(#Button_1, 0, 0, 0, 0, "Short")
ButtonGadget(#Button_2, 0, 0, 0, 0, "-- Longer --")
ButtonGadget(#Button_3, 0, 0, 0, 0, "------- Longest ------")
CheckBoxGadget(#Checkbox_1, 0, 0, 0, 0, "Hello world")
CheckBoxGadget(#Checkbox_2, 0, 0, 0, 0, "The quick brown fox jumped over the lazy dog.")
CheckBoxGadget(#Checkbox_3, 0, 0, 0, 0, "Whatever")
StringGadget(#String, 0, 0, 0, 0, "String")
ComboBoxGadget(#ComboBox, 0, 0, 0, 0)
AddGadgetItem(#ComboBox, 0, "ComboBox")
SetGadgetState(#ComboBox, 0)
ButtonGadget(#ChangeFont, 0, 0, 0, 0, "Change font")
Resize()
HideWindow(0, 0)
Repeat
Event = WaitWindowEvent()
If Event = #PB_Event_Gadget And EventGadget() = #ChangeFont
If FontRequester("Arial", 20, 0)
If LoadFont(0, SelectedFontName(), SelectedFontSize(), SelectedFontStyle())
For Gadget = #Button_1 To #ChangeFont
SetGadgetFont(Gadget, FontID(0))
Next Gadget
Resize()
EndIf
EndIf
EndIf
Until Event = #PB_Event_CloseWindow
EndIf