217 lines
6.0 KiB
Plaintext
217 lines
6.0 KiB
Plaintext
DeclareModule TextEditor
|
|
Declare Open(FileID.s, Path.s)
|
|
EndDeclareModule
|
|
|
|
Module TextEditor
|
|
EnableExplicit
|
|
|
|
#MaxEditors = 16
|
|
#ToolbarHeight = 35
|
|
|
|
Global Dim _Windows.i(#MaxEditors)
|
|
Global Dim _Editors.i(#MaxEditors)
|
|
Global Dim _SaveBtns.i(#MaxEditors)
|
|
Global Dim _FileIDs.s(#MaxEditors)
|
|
Global Dim _Paths.s(#MaxEditors)
|
|
Global Dim _Dirty.i(#MaxEditors)
|
|
Global Dim _Saving.i(#MaxEditors)
|
|
Global _Count.i = 0
|
|
Global _Loading_Slot.i = -1
|
|
Global _ClosingSlot.i = -1 ; slot awaiting confirm-close callback
|
|
|
|
Declare _FindByWindow(Window.i)
|
|
Declare _FindByEditor(Editor.i)
|
|
Declare _SetDirty(Slot.i, Dirty.i)
|
|
Declare _Save(Slot.i)
|
|
Declare _Remove(Slot.i)
|
|
Declare _ConfirmCloseCallback(Result.i)
|
|
Declare _ReadCallback(Success.i, DataString.s)
|
|
Declare _SaveCallback(Success.i, DataString.s)
|
|
Declare Handler_Resize()
|
|
Declare Handler_Save()
|
|
Declare Handler_Change()
|
|
Declare Handler_Close()
|
|
|
|
Procedure Open(FileID.s, Path.s)
|
|
If _Count >= #MaxEditors
|
|
Notify::Toast("Too many editors open.", Notify::#Warning)
|
|
ProcedureReturn
|
|
EndIf
|
|
|
|
Protected Slot.i = _Count
|
|
Protected W.i = 600
|
|
Protected H.i = 400
|
|
Protected Win.i = OpenWindow(#PB_Any, 120 + Slot * 20, 60 + Slot * 20, W, H,
|
|
FS::GetFilePart(Path),
|
|
#PB_Window_TitleBar | #PB_Window_SizeGadget | #PB_Window_SystemMenu)
|
|
|
|
Protected SaveBtn.i = ButtonGadget(#PB_Any, 5, 3, 80, #ToolbarHeight - 6, "Save")
|
|
Protected Editor.i = EditorGadget(#PB_Any, 0, #ToolbarHeight, W, H - #ToolbarHeight)
|
|
|
|
_Windows(Slot) = Win
|
|
_Editors(Slot) = Editor
|
|
_SaveBtns(Slot) = SaveBtn
|
|
_FileIDs(Slot) = FileID
|
|
_Paths(Slot) = Path
|
|
_Dirty(Slot) = #False
|
|
_Count + 1
|
|
|
|
BindGadgetEvent(SaveBtn, @Handler_Save())
|
|
BindGadgetEvent(Editor, @Handler_Change())
|
|
BindEvent(#PB_Event_SizeWindow, @Handler_Resize(), Win)
|
|
BindEvent(#PB_Event_CloseWindow, @Handler_Close(), Win)
|
|
|
|
Desktop::Register(FS::GetFilePart(Path), Win, "📄")
|
|
|
|
_Loading_Slot = Slot
|
|
FS::Read_(FileID, Path, @_ReadCallback())
|
|
EndProcedure
|
|
|
|
; Private procedures
|
|
Procedure.i _FindByWindow(Window.i)
|
|
Protected i.i
|
|
For i = 0 To _Count - 1
|
|
If _Windows(i) = Window : ProcedureReturn i : EndIf
|
|
Next
|
|
ProcedureReturn -1
|
|
EndProcedure
|
|
|
|
Procedure.i _FindByEditor(Editor.i)
|
|
Protected i.i
|
|
For i = 0 To _Count - 1
|
|
If _Editors(i) = Editor : ProcedureReturn i : EndIf
|
|
Next
|
|
ProcedureReturn -1
|
|
EndProcedure
|
|
|
|
Procedure _SetDirty(Slot.i, Dirty.i)
|
|
_Dirty(Slot) = Dirty
|
|
Protected Title.s = FS::GetFilePart(_Paths(Slot))
|
|
If Dirty : Title = "* " + Title : EndIf
|
|
SetWindowTitle(_Windows(Slot), Title)
|
|
EndProcedure
|
|
|
|
Procedure _Save(Slot.i)
|
|
If Not IsWindow(_Windows(Slot)) : ProcedureReturn : EndIf
|
|
If _Saving(Slot) : ProcedureReturn : EndIf
|
|
Protected Content.s = GetGadgetText(_Editors(Slot))
|
|
_Saving(Slot) = #True
|
|
DisableGadget(_SaveBtns(Slot), #True)
|
|
FS::Write(_FileIDs(Slot), _Paths(Slot), Content, @_SaveCallback())
|
|
EndProcedure
|
|
|
|
Procedure _Remove(Slot.i)
|
|
UnbindGadgetEvent(_SaveBtns(Slot), @Handler_Save())
|
|
UnbindGadgetEvent(_Editors(Slot), @Handler_Change())
|
|
UnbindEvent(#PB_Event_SizeWindow, @Handler_Resize(), _Windows(Slot))
|
|
UnbindEvent(#PB_Event_CloseWindow, @Handler_Close(), _Windows(Slot))
|
|
Desktop::Unregister(_Windows(Slot))
|
|
|
|
Protected i.i
|
|
For i = Slot To _Count - 2
|
|
_Windows(i) = _Windows(i + 1)
|
|
_Editors(i) = _Editors(i + 1)
|
|
_SaveBtns(i) = _SaveBtns(i + 1)
|
|
_FileIDs(i) = _FileIDs(i + 1)
|
|
_Paths(i) = _Paths(i + 1)
|
|
_Dirty(i) = _Dirty(i + 1)
|
|
_Saving(i) = _Saving(i + 1)
|
|
Next
|
|
_Windows(_Count - 1) = 0
|
|
_Editors(_Count - 1) = 0
|
|
_SaveBtns(_Count - 1) = 0
|
|
_FileIDs(_Count - 1) = ""
|
|
_Paths(_Count - 1) = ""
|
|
_Dirty(_Count - 1) = #False
|
|
_Saving(_Count - 1) = #False
|
|
_Count - 1
|
|
|
|
If _Loading_Slot = Slot : _Loading_Slot = -1 : EndIf
|
|
If _ClosingSlot = Slot : _ClosingSlot = -1 : EndIf
|
|
EndProcedure
|
|
|
|
; Called by Notify::Confirm — Result=1 means discard and close, 0 means cancel.
|
|
Procedure _ConfirmCloseCallback(Result.i)
|
|
If Result And _ClosingSlot >= 0
|
|
_Remove(_ClosingSlot)
|
|
EndIf
|
|
_ClosingSlot = -1
|
|
EndProcedure
|
|
|
|
; Callbacks
|
|
Procedure _ReadCallback(Success.i, DataString.s)
|
|
If _Loading_Slot < 0 : ProcedureReturn : EndIf
|
|
Protected Slot.i = _Loading_Slot
|
|
_Loading_Slot = -1
|
|
If Not IsWindow(_Windows(Slot)) : ProcedureReturn : EndIf
|
|
If Success
|
|
SetGadgetText(_Editors(Slot), DataString)
|
|
_SetDirty(Slot, #False)
|
|
Else
|
|
SetGadgetText(_Editors(Slot), "")
|
|
_SetDirty(Slot, #True)
|
|
EndIf
|
|
EndProcedure
|
|
|
|
Procedure _SaveCallback(Success.i, DataString.s)
|
|
Protected i.i
|
|
For i = 0 To _Count - 1
|
|
If _Saving(i)
|
|
_Saving(i) = #False
|
|
DisableGadget(_SaveBtns(i), #False)
|
|
If Success
|
|
_SetDirty(i, #False)
|
|
Else
|
|
Notify::Toast("Save failed — " + FS::GetFilePart(_Paths(i)), Notify::#Error)
|
|
EndIf
|
|
Break
|
|
EndIf
|
|
Next
|
|
EndProcedure
|
|
|
|
; Event handlers
|
|
Procedure Handler_Resize()
|
|
Protected Win.i = EventWindow()
|
|
Protected Slot.i = _FindByWindow(Win)
|
|
If Slot < 0 : ProcedureReturn : EndIf
|
|
ResizeGadget(_Editors(Slot), 0, #ToolbarHeight,
|
|
WindowWidth(Win), WindowHeight(Win) - #ToolbarHeight)
|
|
EndProcedure
|
|
|
|
Procedure Handler_Save()
|
|
Protected Slot.i = _FindByWindow(EventWindow())
|
|
If Slot >= 0 : _Save(Slot) : EndIf
|
|
EndProcedure
|
|
|
|
Procedure Handler_Change()
|
|
Protected Slot.i = _FindByEditor(EventGadget())
|
|
If Slot >= 0 And Not _Dirty(Slot)
|
|
_SetDirty(Slot, #True)
|
|
EndIf
|
|
EndProcedure
|
|
|
|
Procedure Handler_Close()
|
|
Protected Win.i = EventWindow()
|
|
Protected Slot.i = _FindByWindow(Win)
|
|
If Slot < 0 : ProcedureReturn : EndIf
|
|
|
|
If _Dirty(Slot)
|
|
_ClosingSlot = Slot
|
|
Notify::Confirm("Unsaved changes",
|
|
"Close " + Chr(34) + FS::GetFilePart(_Paths(Slot)) + Chr(34) + " without saving?",
|
|
@_ConfirmCloseCallback())
|
|
Else
|
|
_Remove(Slot)
|
|
EndIf
|
|
EndProcedure
|
|
|
|
EndModule
|
|
; IDE Options = SpiderBasic 3.10 (Windows - x86)
|
|
; CursorPosition = 69
|
|
; Folding = DA5
|
|
; iOSAppOrientation = 0
|
|
; AndroidAppCode = 0
|
|
; AndroidAppOrientation = 0
|
|
; EnableXP
|
|
; DPIAware
|
|
; CompileSourceDirectory |