- Coded in PB 5.60+
- Supported OS: windows & linux
- TODO : option to add button
Code: Select all
DeclareModule StringButtonGadget
Enumeration
;custom Flags
#StringButton_Default=0
#StringButton_Numeric=#PB_String_Numeric
#StringButton_Password=#PB_String_Password
#StringButton_ReadOnly=#PB_String_ReadOnly
#StringButton_LowerCase=#PB_String_LowerCase
#StringButton_UpperCase=#PB_String_UpperCase
;custom Statuses
#StringButton_IsHighlighted=1
#StringButton_IsDragged=2
#StringButton_IsSnapped=4
;custom Attributes
#StringButton_CurrentFlags=2000
#StringButton_CurrentPadding
#StringButton_CurrentThickness
#StringButton_CurrentCornerRadius
#StringButton_CurrentTransparentColor
#StringButton_CurrentStatus
#StringButton_CurrentDrawingFunction
EndEnumeration
Global StringButtonTransparentColor.i
Declare.i StringButtonGadget(Gadget, x, y, Width, Height, Content$, Flags=0, Padding=1, Thickness=1, CornerRadius=0)
EndDeclareModule
Module StringButtonGadget
EnableExplicit
CompilerIf #PB_Compiler_OS=#PB_OS_Windows
;- PB SDK for Windows
Structure Gadget
Gadget.i
*vt.GadgetVT
UserData.i
OldCallback.i
Daten.i[4]
EndStructure
Structure GadgetVT
GadgetType.l
SizeOf.l
*GadgetCallback
*FreeGadget
*GetGadgetState
*SetGadgetState
*GetGadgetText
*SetGadgetText
*AddGadgetItem2
*AddGadgetItem3
*RemoveGadgetItem
*ClearGadgetItemList
*ResizeGadget
*CountGadgetItems
*GetGadgetItemState
*SetGadgetItemState
*GetGadgetItemText
*SetGadgetItemText
*OpenGadgetList2
*GadgetX
*GadgetY
*GadgetWidth
*GadgetHeight
*HideGadget
*AddGadgetColumn
*RemoveGadgetColumn
*GetGadgetAttribute
*SetGadgetAttribute
*GetGadgetItemAttribute2
*SetGadgetItemAttribute2
*SetGadgetColor
*GetGadgetColor
*SetGadgetItemColor2
*GetGadgetItemColor2
*SetGadgetItemData
*GetGadgetItemData
*GetRequiredSize
*SetActiveGadget
*GetGadgetFont
*SetGadgetFont
*SetGadgetItemImage
EndStructure
CompilerElseIf #PB_Compiler_OS=#PB_OS_Linux
;- PB SDK for Linux
Structure Gadget
Gadget.i
GadgetContainer.i
*vt.GadgetVT
UserData.i
Daten.i[4]
EndStructure
Structure GadgetVT
SizeOf.l
GadgetType.l
*ActivateGadget
*FreeGadget
*GetGadgetState
*SetGadgetState
*GetGadgetText
*SetGadgetText
*AddGadgetItem2
*AddGadgetItem3
*RemoveGadgetItem
*ClearGadgetItemList
*ResizeGadget
*CountGadgetItems
*GetGadgetItemState
*SetGadgetItemState
*GetGadgetItemText
*SetGadgetItemText
*SetGadgetFont
*OpenGadgetList2
*AddGadgetColumn
*GetGadgetAttribute
*SetGadgetAttribute
*GetGadgetItemAttribute2
*SetGadgetItemAttribute2
*RemoveGadgetColumn
*SetGadgetColor
*GetGadgetColor
*SetGadgetItemColor2
*GetGadgetItemColor2
*SetGadgetItemData
*GetGadgetItemData
*GetGadgetFont
*SetGadgetItemImage
*HideGadget ;Mac & Windows only
EndStructure
CompilerElseIf #PB_Compiler_OS=#PB_OS_MacOS
;- PB SDK for MacOs => TODO
CompilerEndIf
Structure CustomGadget
vt.GadgetVT
vtOld.GadgetVT ;old gadget VT
isCustom.b ;determines if customization is active
;custom properties
Gadget.i
Flags.i
StringGadget.i
Padding.i
Thickness.i
CornerRadius.i
x.i : y.i : w.i : h.i
BackColor.i
FrontColor.i
LineColor.i
GrayTextColor.i
WindowColor.i
TransparentColor.i
State.f
CurrentStatus.f
*DrawingFunction
EndStructure
Structure CustomContext
*DraggedGadget.CustomGadget
DragStartPos.i
EndStructure
Global CustomContext.CustomContext ;Custom global context
Global NewMap CustomGadget.CustomGadget() ;Custom gadget list
Declare.i NewCustomGadget(*this.Gadget)
Declare FreeCustomGadget(*this.Gadget)
Declare DrawCustomGadget(*this.Gadget)
Declare UseCustomGadget(*this.Gadget, *CustomGadget.CustomGadget)
Declare CustomGadgetEvents()
Declare ConvertToRGBA(Color, DefaultAlpha=255)
Procedure ResizeGadgetSmoothly(Gadget, x, y, w, h, SmoothMode=#True)
Protected *this.Gadget=GadgetID(Gadget)
If SmoothMode ;prevent flickering
CompilerIf #PB_Compiler_OS=#PB_OS_Windows
SendMessage_(*this, #WM_SETREDRAW, 0, 0)
CompilerEndIf
EndIf
ResizeGadget(Gadget, x, y, w, h)
If SmoothMode ;prevent flickering
CompilerIf #PB_Compiler_OS=#PB_OS_Windows
SendMessage_(*this, #WM_SETREDRAW, 1, 0)
InvalidateRect_(*this, 0, 0)
UpdateWindow_(*this)
CompilerEndIf
EndIf
EndProcedure
Procedure _ResizeGadget(*this.Gadget, x, y, w.w, h.w)
Protected *CustomGadget.CustomGadget=*this\vt
With *CustomGadget
If x=#PB_Ignore : x=\x : EndIf
If y=#PB_Ignore : y=\y : EndIf
If w=#PB_Ignore : w=\w : EndIf
If h=#PB_Ignore : h=\h : EndIf
\x=x : \y=y : \w=w : \h=h
;resize bar (resized original gadget)
UseCustomGadget(*this, 0)
ResizeGadget(\Gadget, \x, \y, \w, \h)
UseCustomGadget(*this, 1)
Protected spacingV=\Thickness + \Padding
Protected spacingH=\Thickness + \Padding + ((\CornerRadius -\Thickness) -\Padding) * Bool(\Padding<(\CornerRadius -\Thickness))
ResizeGadget(\StringGadget, spacingH, spacingV, \w-2*spacingH, \h-2*spacingV)
DrawCustomGadget(*this)
EndWith
EndProcedure
Procedure.i _GetGadgetColor(*this.Gadget, ColorType)
Protected *CustomGadget.CustomGadget=*this\vt, result
With *CustomGadget
Select ColorType
Case #PB_Gadget_BackColor : result=\BackColor
Case #PB_Gadget_FrontColor : result=\FrontColor
Case #PB_Gadget_LineColor : result=\LineColor
Case #PB_Gadget_GrayTextColor : result=\GrayTextColor
EndSelect
ProcedureReturn result
EndWith
EndProcedure
Procedure _SetGadgetColor(*this.Gadget, ColorType, Color)
Protected *CustomGadget.CustomGadget=*this\vt
With *CustomGadget
Select ColorType
Case #PB_Gadget_BackColor : \BackColor=Color : SetGadgetColor(\StringGadget, ColorType, Color) ;colorize CanvasGadget & StringGadget
Case #PB_Gadget_FrontColor : \FrontColor=Color : SetGadgetColor(\StringGadget, ColorType, Color) ;colorize CanvasGadget & StringGadget
Case #PB_Gadget_LineColor : \LineColor=Color
Case #PB_Gadget_GrayTextColor : \GrayTextColor=Color
EndSelect
DrawCustomGadget(*this)
EndWith
EndProcedure
Procedure.s _GetGadgetText(*this.Gadget)
Protected *CustomGadget.CustomGadget=*this\vt
With *CustomGadget
ProcedureReturn GetGadgetText(\StringGadget)
EndWith
EndProcedure
Procedure _SetGadgetText(*this.Gadget, Text$)
Protected *CustomGadget.CustomGadget=*this\vt
With *CustomGadget
SetGadgetText(\StringGadget, Text$)
EndWith
EndProcedure
Procedure _SetGadgetAttribute(*this.Gadget, Attribute, Value)
Protected *CustomGadget.CustomGadget=*this\vt
With *CustomGadget
Select Attribute
Case 0 To 1024
;Set original gadget attribute
UseCustomGadget(*this, 0)
SetGadgetAttribute(\Gadget, Attribute, Value)
UseCustomGadget(*this, 1)
Case #StringButton_CurrentFlags : \Flags=Value
Case #StringButton_CurrentThickness : \Thickness=Value
Case #StringButton_CurrentPadding : \Padding=Value
Case #StringButton_CurrentCornerRadius : \CornerRadius=Value
Case #StringButton_CurrentTransparentColor : \TransparentColor=ConvertToRGBA(Value)
Case #StringButton_CurrentDrawingFunction : \DrawingFunction=Value
EndSelect
_ResizeGadget(*this, #PB_Ignore, #PB_Ignore, #PB_Ignore, #PB_Ignore)
EndWith
EndProcedure
Procedure.i _GetGadgetAttribute(*this.Gadget, Attribute)
Protected *CustomGadget.CustomGadget=*this\vt, result
With *CustomGadget
Select Attribute
Case 0 To 1024
;Get original gadget attribute
UseCustomGadget(*this, 0)
result=GetGadgetAttribute(\Gadget, Attribute)
UseCustomGadget(*this, 1)
Case #StringButton_CurrentFlags : result=\Flags
Case #StringButton_CurrentStatus : result=\CurrentStatus
Case #StringButton_CurrentThickness : result=\Thickness
Case #StringButton_CurrentPadding : result=\Padding
Case #StringButton_CurrentCornerRadius : result=\CornerRadius
Case #StringButton_CurrentTransparentColor : result=\TransparentColor
Case #StringButton_CurrentDrawingFunction : result=\DrawingFunction
EndSelect
ProcedureReturn result
EndWith
EndProcedure
Procedure _FreeGadget(*this.Gadget)
Protected *CustomGadget.CustomGadget=*this\vt
With *CustomGadget
FreeCustomGadget(*this)
EndWith
EndProcedure
Procedure CustomGadgetEvents()
Protected t=EventType()
Protected g=EventGadget()
Protected *this.Gadget=IsGadget(g)
Protected *CustomGadget.CustomGadget=*this\vt
With *CustomGadget
EndWith
EndProcedure
Procedure UseCustomGadget(*this.Gadget, isCustom)
Protected *CustomGadget.CustomGadget=*this\vt
Protected vtOld.GadgetVT
If Bool(isCustom)<>*CustomGadget\isCustom
;swap custom gadgetVT and original gadgetVT
vtOld=*CustomGadget\vtOld
*CustomGadget\vtOld=*CustomGadget\vt
*CustomGadget\vt=vtOld
*CustomGadget\isCustom=Bool(isCustom)
EndIf
EndProcedure
Procedure.i ConvertToRGBA(ColorRGB, DefaultAlpha=255)
ProcedureReturn RGBA(Red(ColorRGB), Green(ColorRGB), Blue(ColorRGB), DefaultAlpha)
EndProcedure
Procedure DrawCornerBoxPath(x.d, y.d, Width.d, Height.d, CornerRadius.d, Color, Flags=#PB_Path_Default)
If CornerRadius<=0
;sharp corner
AddPathBox(x, y, Width, Height, Flags)
Else
;rounded corner
MovePathCursor(x + CornerRadius, y, Flags & #PB_Path_Relative)
AddPathEllipse(0, CornerRadius, CornerRadius, CornerRadius, 180, -90, #PB_Path_Relative)
AddPathLine(Width-CornerRadius*2, 0, #PB_Path_Relative)
AddPathEllipse(0, CornerRadius, CornerRadius, CornerRadius, -90, 0, #PB_Path_Connected | #PB_Path_Relative)
AddPathLine(0, Height-CornerRadius*2, #PB_Path_Relative)
AddPathEllipse(-CornerRadius, 0, CornerRadius, CornerRadius, 0, 90, #PB_Path_Connected | #PB_Path_Relative)
AddPathLine(CornerRadius*2-Width, 0, #PB_Path_Relative)
AddPathEllipse(0, -CornerRadius, CornerRadius, CornerRadius, 90, 180, #PB_Path_Connected | #PB_Path_Relative)
ClosePath()
EndIf
VectorSourceColor(Color)
FillPath()
EndProcedure
Procedure DrawCustomGadget(*this.Gadget)
Protected *CustomGadget.CustomGadget=*this\vt
With *CustomGadget
If \DrawingFunction
CallFunctionFast(\DrawingFunction, \Gadget)
ProcedureReturn
EndIf
StartVectorDrawing(CanvasVectorOutput(\Gadget))
VectorSourceColor(ConvertToRGBA(\TransparentColor))
FillVectorOutput()
If \Thickness<=0
;no border
DrawCornerBoxPath(0, 0, \w, \h, \CornerRadius, ConvertToRGBA(\BackColor))
Else
;smooth border
DrawCornerBoxPath(0, 0, \w, \h, \CornerRadius, ConvertToRGBA(\LineColor))
DrawCornerBoxPath(\Thickness, \Thickness, \w-2*\Thickness, \h-2*\Thickness, \CornerRadius -\Thickness, ConvertToRGBA(\BackColor))
EndIf
StopVectorDrawing()
EndWith
EndProcedure
Procedure FreeCustomGadget(*this.Gadget)
;find custom gadget data
Protected *CustomGadget.CustomGadget=FindMapElement(CustomGadget(), "ID-" + *this\Gadget)
With *CustomGadget
If *CustomGadget
;free original gadget
UseCustomGadget(*this, 0)
FreeGadget(\Gadget)
;delete custom gadget data
DeleteMapElement(CustomGadget())
EndIf
EndWith
EndProcedure
Procedure.i NewCustomGadget(*this.Gadget)
;create custom gadget data
Protected *CustomGadget.CustomGadget=AddMapElement(CustomGadget(), "ID-" + *this\Gadget)
If *CustomGadget
*CustomGadget\isCustom=1
CopyMemory(*this\vt, *CustomGadget\vtOld, SizeOf(GadgetVT))
CopyMemory(*this\vt, *CustomGadget\vt, SizeOf(GadgetVT))
With *CustomGadget\vt
;define mandatory custom method
\FreeGadget=@_FreeGadget()
;define other custom methods
\ResizeGadget=@_ResizeGadget()
\GetGadgetText=@_GetGadgetText()
\SetGadgetText=@_SetGadgetText()
\GetGadgetColor=@_GetGadgetColor()
\SetGadgetColor=@_SetGadgetColor()
\GetGadgetAttribute=@_GetGadgetAttribute()
\SetGadgetAttribute=@_SetGadgetAttribute()
EndWith
;apply custom gadgetVT
*this\vt=*CustomGadget
EndIf
ProcedureReturn *CustomGadget
EndProcedure
Procedure.i StringButtonGadget(Gadget, x, y, Width, Height, Content$, Flags=#StringButton_Default, Padding=1, Thickness=1, CornerRadius=0)
Protected result=CanvasGadget(Gadget, x, y, Width, Height, #PB_Canvas_Container)
If result=0 : ProcedureReturn #False : EndIf
If Gadget=#PB_Any : Gadget=result : EndIf
Protected *this.Gadget=IsGadget(Gadget)
Protected *CustomGadget.CustomGadget=NewCustomGadget(*this)
With *CustomGadget
;define custom properties
\x=x : \y=y : \w=Width : \h=Height
\Gadget=Gadget
\Flags=Flags
\Padding=Padding
\Thickness=Thickness
\CornerRadius=CornerRadius
Protected spacing=\Padding + \Thickness
\StringGadget=StringGadget(#PB_Any, spacing, spacing, Width-spacing*2, Height-spacing*2, Content$, Flags | #PB_String_BorderLess)
\BackColor=ConvertToRGBA(GetGadgetColor(\StringGadget, #PB_Gadget_BackColor))
\FrontColor=ConvertToRGBA(GetGadgetColor(\StringGadget, #PB_Gadget_FrontColor))
\LineColor=ConvertToRGBA(#Gray)
\TransparentColor=ConvertToRGBA(StringButtonTransparentColor)
CloseGadgetList()
SetGadgetAttribute(\Gadget, #PB_Canvas_Cursor, #PB_Cursor_IBeam)
;define custom events
BindGadgetEvent(Gadget, @CustomGadgetEvents())
EndWith
ProcedureReturn result
EndProcedure
EndModule
CompilerIf #PB_Compiler_IsMainFile
;********************
; EXAMPLE
;********************
UseModule StringButtonGadget
Runtime Enumeration
#xml : #dialog : #win
EndEnumeration
Procedure SetGadgetColors(Gadget, BackColor=0, FrontColor=0, LineColor=0, GrayTextColor=0)
SetGadgetColor(Gadget, #PB_Gadget_FrontColor, FrontColor)
SetGadgetColor(Gadget, #PB_Gadget_BackColor, BackColor)
SetGadgetColor(Gadget, #PB_Gadget_LineColor, LineColor)
SetGadgetColor(Gadget, #PB_Gadget_GrayTextColor, GrayTextColor)
EndProcedure
Procedure DrawingFunction(Gadget)
StartVectorDrawing(CanvasVectorOutput(Gadget))
Protected i, x, y, w=VectorOutputWidth(), h=VectorOutputHeight()
Protected Flags=GetGadgetAttribute(Gadget, #StringButton_CurrentFlags)
Protected Padding=GetGadgetAttribute(Gadget, #StringButton_CurrentPadding)
Protected Thickness=GetGadgetAttribute(Gadget, #StringButton_CurrentThickness)
Protected FrontColor=GetGadgetColor(Gadget, #PB_Gadget_FrontColor)
Protected BackColor=GetGadgetColor(Gadget, #PB_Gadget_BackColor)
Protected LineColor=GetGadgetColor(Gadget, #PB_Gadget_LineColor)
Protected GrayTextColor=GetGadgetColor(Gadget, #PB_Gadget_GrayTextColor)
Protected TransparentColor=GetGadgetAttribute(Gadget, #StringButton_CurrentTransparentColor)
StartVectorDrawing(CanvasVectorOutput(Gadget))
;VectorSourceColor(TransparentColor)
;FillVectorOutput()
;AddPathCurvyBox(Thickness / 2, Thickness / 2, w-Thickness, h-Thickness)
;VectorSourceColor(BackColor)
;FillPath(#PB_Path_Preserve)
;VectorSourceColor(LineColor)
;StrokePath(Thickness)
StopVectorDrawing()
EndProcedure
Define xml$="<window id='#win' name='splitter' text='StringButton Gadgets' width='322' height='235' " +
" flags='#PB_Window_ScreenCentered | #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget'>" +
" <vbox>" +
" <string id='0' />" +
" <string id='1' />" +
" <string id='2' />" +
" <string id='3' />" +
" <string id='4' />" +
" <string id='5' />" +
" <string id='6' />" +
" <string id='7' />" +
" </vbox>" +
"</window>"
If CatchXML(#xml, @xml$, StringByteLength(xml$), 0, #PB_Ascii) And XMLStatus(#xml)=#PB_XML_Success And CreateDialog(#dialog) And OpenXMLDialog(#dialog, #xml, "splitter")
StartDrawing(WindowOutput(#Win))
StringButtonGadget::StringButtonTransparentColor=Point(0, 0) ; Specify window color for transparency effect
StopDrawing()
StringButtonGadget(0, 8, 8, 306, 20, "Normal StringGadget...")
StringButtonGadget(1, 8, 8, 306, 20, "1234567", #StringButton_Numeric, 0, 3, 8)
SetGadgetColors(1, RGB(125, 158, 255), RGB(44, 251, 255), RGB(128, 66, 255), #Cyan)
StringButtonGadget(2, 8, 8, 306, 20, "Read-only", #StringButton_ReadOnly)
StringButtonGadget(3, 8, 8, 306, 20, "lowercase...", #StringButton_LowerCase)
StringButtonGadget(4, 8, 8, 306, 20, "uppercase...", #StringButton_UpperCase)
StringButtonGadget(5, 8, 8, 306, 20, "Borderless", #StringButton_Default, 2, 0)
StringButtonGadget(6, 8, 8, 306, 20, "")
DisableGadget(6, 1)
SetGadgetText(6, "Diabled")
StringButtonGadget(7, 8, 8, 306, 20, "Password", #StringButton_Password, 2)
SetGadgetAttribute(7, #StringButton_CurrentThickness, 2)
SetGadgetAttribute(7, #StringButton_CurrentCornerRadius, 3)
;SetGadgetAttribute(7, #StringButton_CurrentDrawingFunction, @DrawingFunction())
ResizeWindow(#win, #PB_Ignore, #PB_Ignore, #PB_Ignore, 236)
Repeat
e=WaitWindowEvent()
g=EventGadget()
t=EventType()
d=EventData()
win=EventWindow()
Debug "event=" + e + " win=" + win + " gadget=" + g + " EventType=" + t + " EventData=" + d
Until e=#PB_Event_CloseWindow
EndIf
CompilerEndIf