DeclareModule Settings Declare Open() EndDeclareModule Module Settings EnableExplicit #Win_W = 500 #Win_H = 290 #Panel_W = 140 #Row_H = 44 #Pad = 20 Global Color_Panel_Bg = RGB( 22, 22, 34) Global Color_Sel = RGB( 52, 52, 72) Global Color_Hover = RGB( 40, 40, 58) Global Color_Accent = RGB(100, 120, 255) Global Color_Content_Bg = RGB( 36, 36, 52) Global Color_Sep = RGB( 48, 48, 65) Global Color_Text = RGB(200, 200, 215) Global Color_Dim = RGB(110, 110, 135) Global PanelFont = LoadFont(#PB_Any, "sans-serif", 13) ; To add a section: add its name below, create its gadgets in Open(), And add a Case to _ShowSection() / _HideSection(). Enumeration #Section_Account ; #Section_Appearance ; #Section_About #Section_Count ; keep in last place EndEnumeration Global Dim _SectionNames.s(#Section_Count) ; State Global Window Global _PanelCanvas Global _CurrentSection Global _PanelHover = -1 ; Account section gadgets Global _LblCurrent, _InCurrent Global _LblNew, _InNew Global _LblConfirm, _InConfirm Global _BtnSave ; Private declarations Declare _DrawPanel() Declare _HideSection(Section) Declare _ShowSection(Section) Declare Handler_Close() Declare Handler_PanelCanvas() Declare Handler_Save() Declare _SaveCallback(Success, DataString.s) ; Public procedures Procedure Open() If IsWindow(Window) SetActiveWindow(Window) ProcedureReturn EndIf _SectionNames(#Section_Account) = "Account" Window = OpenWindow(#PB_Any, 200, 150, #Win_W, #Win_H, "Settings", #PB_Window_TitleBar | #PB_Window_SystemMenu) SetWindowColor(Window, Color_Content_Bg) _PanelCanvas = CanvasGadget(#PB_Any, 0, 0, #Panel_W, #Win_H) ; Account section gadgets Protected CX = #Panel_W + 1 + #Pad Protected CW = #Win_W - #Panel_W - 1 - #Pad * 2 Protected Y = 20 _LblCurrent = TextGadget (#PB_Any, CX, Y, CW, 18, "Current password") _InCurrent = StringGadget(#PB_Any, CX, Y + 22, CW, 26, "", #PB_String_Password) Y + 66 _LblNew = TextGadget (#PB_Any, CX, Y, CW, 18, "New password") _InNew = StringGadget(#PB_Any, CX, Y + 22, CW, 26, "", #PB_String_Password) Y + 66 _LblConfirm = TextGadget (#PB_Any, CX, Y, CW, 18, "Confirm new password") _InConfirm = StringGadget(#PB_Any, CX, Y + 22, CW, 26, "", #PB_String_Password) Y + 58 _BtnSave = ButtonGadget(#PB_Any, CX, Y, CW, 30, "Change password") ; Label colors SetGadgetColor(_LblCurrent, #PB_Gadget_FrontColor, Color_Text) SetGadgetColor(_LblNew, #PB_Gadget_FrontColor, Color_Text) SetGadgetColor(_LblConfirm, #PB_Gadget_FrontColor, Color_Text) SetGadgetColor(_LblCurrent, #PB_Gadget_BackColor, Color_Content_Bg) SetGadgetColor(_LblNew, #PB_Gadget_BackColor, Color_Content_Bg) SetGadgetColor(_LblConfirm, #PB_Gadget_BackColor, Color_Content_Bg) BindGadgetEvent(_BtnSave, @Handler_Save()) BindGadgetEvent(_PanelCanvas, @Handler_PanelCanvas()) BindEvent(#PB_Event_CloseWindow, @Handler_Close(), Window) Desktop::Register("Settings", Window, "⚙") _DrawPanel() EndProcedure ; Private procedures Procedure _DrawPanel() If Not IsGadget(_PanelCanvas) : ProcedureReturn : EndIf If Not StartDrawing(CanvasOutput(_PanelCanvas)) : ProcedureReturn : EndIf Protected W = OutputWidth() Protected H = OutputHeight() Protected i, Y, TH Box(0, 0, W, H, Color_Panel_Bg) Box(W - 1, 0, 1, H, Color_Sep) ; right-edge separator If IsFont(PanelFont) : DrawingFont(FontID(PanelFont)) : EndIf TH = TextHeight("A") For i = 0 To #Section_Count - 1 Y = i * #Row_H If i = _CurrentSection Box(0, Y, W - 1, #Row_H, Color_Sel) Box(0, Y, 3, #Row_H, Color_Accent) ElseIf i = _PanelHover Box(0, Y, W - 1, #Row_H, Color_Hover) EndIf DrawingMode(#PB_2DDrawing_Transparent) DrawText(14, Y + (#Row_H - TH) / 2, _SectionNames(i), Color_Text) Next StopDrawing() EndProcedure Procedure _HideSection(Section) Select Section Case #Section_Account HideGadget(_LblCurrent, #True) HideGadget(_InCurrent, #True) HideGadget(_LblNew, #True) HideGadget(_InNew, #True) HideGadget(_LblConfirm, #True) HideGadget(_InConfirm, #True) HideGadget(_BtnSave, #True) EndSelect EndProcedure Procedure _ShowSection(Section) _HideSection(_CurrentSection) _CurrentSection = Section Select Section Case #Section_Account HideGadget(_LblCurrent, #False) HideGadget(_InCurrent, #False) HideGadget(_LblNew, #False) HideGadget(_InNew, #False) HideGadget(_LblConfirm, #False) HideGadget(_InConfirm, #False) HideGadget(_BtnSave, #False) EndSelect _DrawPanel() EndProcedure ; Event handlers Procedure Handler_PanelCanvas() Protected EType = EventType() Protected MY = GetGadgetAttribute(_PanelCanvas, #PB_Canvas_MouseY) Protected Row = MY / #Row_H Select EType Case #PB_EventType_MouseMove If Row < #Section_Count And Row <> _PanelHover _PanelHover = Row _DrawPanel() EndIf Case #PB_EventType_MouseLeave _PanelHover = -1 _DrawPanel() Case #PB_EventType_LeftButtonUp If Row >= 0 And Row < #Section_Count And Row <> _CurrentSection _ShowSection(Row) EndIf EndSelect EndProcedure Procedure Handler_Save() Protected Current.s = GetGadgetText(_InCurrent) Protected New_.s = GetGadgetText(_InNew) Protected Confirm.s = GetGadgetText(_InConfirm) If Current = "" Or New_ = "" Or Confirm = "" Notify::Toast("Please fill in all fields.", Notify::#Warning) ProcedureReturn EndIf If New_ <> Confirm Notify::Toast("New passwords do not match.", Notify::#Warning) ProcedureReturn EndIf If Len(New_) < 8 Notify::Toast("Password must be at least 8 characters.", Notify::#Warning) ProcedureReturn EndIf DisableGadget(_BtnSave, #True) HTTPRequest(#PB_HTTP_Post, "/api/auth/password", "current_password=" + URLEncoder(Current, #PB_UTF8) + "&new_password=" + URLEncoder(New_, #PB_UTF8), @_SaveCallback()) EndProcedure Procedure _SaveCallback(Success, DataString.s) DisableGadget(_BtnSave, #False) If Not Success Notify::Toast("Connection error.", Notify::#Error) ProcedureReturn EndIf If ParseJSON(0, DataString) Protected Root = JSONValue(0) If GetJSONBoolean(GetJSONMember(Root, "success")) SetGadgetText(_InCurrent, "") SetGadgetText(_InNew, "") SetGadgetText(_InConfirm, "") Notify::Toast("Password changed successfully.", Notify::#Success) Else Notify::Toast(GetJSONString(GetJSONMember(Root, "error")), Notify::#Error) EndIf FreeJSON(0) Else Notify::Toast("Unexpected server response.", Notify::#Error) EndIf EndProcedure Procedure Handler_Close() UnbindGadgetEvent(_PanelCanvas, @Handler_PanelCanvas()) UnbindGadgetEvent(_BtnSave, @Handler_Save()) UnbindEvent(#PB_Event_CloseWindow, @Handler_Close(), Window) Desktop::Unregister(Window) Window = 0 EndProcedure EndModule ; IDE Options = SpiderBasic 3.10 (Windows - x86) ; CursorPosition = 10 ; Folding = Dw ; iOSAppOrientation = 0 ; AndroidAppCode = 0 ; AndroidAppOrientation = 0 ; EnableXP ; DPIAware ; CompileSourceDirectory