Page 1 of 1

Scintilla + PanelGadget

Posted: Fri Apr 28, 2023 2:26 am
by AZJIO
Which is better of the two options?

This one uses multiple documents in one Scintilla instance
http://purebasic.mybb.ru/viewtopic.php?id=1005#p9970

Code: Select all

EnableExplicit

#Win = 0
#Sci = 0
#Pn = 1

Global PnTabHeight
Define Text$, *Text, CountTabs, *SciDoc, Event, i

; возвращает рандомный текст
Procedure.s _Get_Random_Text()
	Protected i, Rnd, Text$
	For i = 0 To 300
; 		Rnd = Random(90, 65)
		Rnd = Random(122, 97)
		Text$ + Chr( Rnd )
; 		If Rnd < 67: Text$ + #CRLF$ : EndIf
		If Rnd < 99: Text$ + #CRLF$ : EndIf
	Next
	ProcedureReturn Text$
EndProcedure

; событие клика по кнопке
Procedure _Event_Click_Tab()
	Protected index = GetGadgetState(#Pn) ; получаем кнопку
	Protected *SciDoc = GetGadgetItemData(#Pn, index) ; получаем записанный указатель на документ
; 	Debug index
; 	Debug *SciDoc
	ScintillaSendMessage(#Sci, #SCI_SETDOCPOINTER, 0, *SciDoc ) ; устанавливаемся на документ
EndProcedure


Procedure SizeWindowHandler()
	Protected w = WindowWidth(#Win)
	ResizeGadget(#Pn, #PB_Ignore, #PB_Ignore, w, #PB_Ignore)
	ResizeGadget(#Sci, #PB_Ignore, #PB_Ignore, w - 3, WindowHeight(#Win) - PnTabHeight)
EndProcedure

;- GUI
If OpenWindow(#Win, 0, 0, 700, 500, "Scintilla-Tab", #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_ScreenCentered | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget )

	If Not InitScintilla() : MessageRequester("", "Не удалось инициализировать компонент Scintilla" ) : End : EndIf
	; создаём один Scintilla гаджет
	ScintillaGadget(#Sci, 2, 28, WindowWidth(#Win) - 3, WindowHeight(#Win) - 27, 0 )
	ScintillaSendMessage(#Sci, #SCI_STYLESETFORE, 0, $aaaaaa ) ; покрасим основной текст
	ScintillaSendMessage(#Sci, #SCI_STYLESETBACK, 0, $3f3f3f ) ; покрасим основной текст
	ScintillaSendMessage(#Sci, #SCI_STYLESETBACK, #STYLE_DEFAULT, $3f3f3f)    ; цвет фона
	ScintillaSendMessage(#Sci, #SCI_STYLESETFORE, #STYLE_DEFAULT, $aaaaaa) ; цвет текста
	ScintillaSendMessage(#Sci, #SCI_STYLESETSIZE, #STYLE_DEFAULT, 12) ; размер шрифта
; 	ScintillaSendMessage(#Sci, #SCI_SETSCROLLWIDTHTRACKING, 1, 1)	; Добавляет прокрутку по ширине текущих строк
	ScintillaSendMessage(#Sci, #SCI_SETMARGINWIDTHN, 1, 0)   ; Устанавливает ширину поля 1 (номеров строк)
	PanelGadget(#Pn, 0, 0, 700, 28)

	CountTabs = 8 ; сколько будет табов

	For i = 0 To CountTabs - 1
		AddGadgetItem(#Pn, i, "Tab" + Str(i + 1))

		; Пишем текст в текущий выбранный документ
		Text$ = _Get_Random_Text()
		*Text = UTF8(Text$)
		ScintillaSendMessage(#Sci, #SCI_APPENDTEXT, Len(Text$), *Text)
		FreeMemory(*Text)

		*SciDoc = ScintillaSendMessage(#Sci, #SCI_GETDOCPOINTER ) ; получаем дескриптор текущего документа
		ScintillaSendMessage(#Sci, #SCI_ADDREFDOCUMENT, 0, *SciDoc )  ; создаём следующий документ
		ScintillaSendMessage(#Sci, #SCI_SETDOCPOINTER, 0, 0 )    ; устанавливаемся на новый документ
		SetGadgetItemData(#Pn, i, *SciDoc) ; привязываем документ к кнопке
	Next
	
	CloseGadgetList()
	BindGadgetEvent(#Pn, @_Event_Click_Tab(), #PB_All)
	BindEvent(#PB_Event_SizeWindow, @SizeWindowHandler())

	; показываем документ, связанный с последней кнопкой
	ScintillaSendMessage(#Sci, #SCI_SETDOCPOINTER, 0, GetGadgetItemData(#Pn, i - 1))
	SetGadgetState(#Pn, i - 1)
	
; 	Устанавливаем размер панели по высоте вкладок
	PnTabHeight = GetGadgetAttribute(#Pn, #PB_Panel_TabHeight)
; 	Debug PnTabHeight
	ResizeGadget(#Pn, #PB_Ignore, #PB_Ignore, #PB_Ignore, PnTabHeight)
	ResizeGadget(#Sci, #PB_Ignore, PnTabHeight, #PB_Ignore, WindowHeight(#Win) - PnTabHeight)
	

	Repeat
		Event = WaitWindowEvent()
	Until Event = #PB_Event_CloseWindow

EndIf
This creates multiple instances of Scintilla

Code: Select all

EnableExplicit

#Win = 0
#Pn = 0

Global CurSci, CountTabs, PnTabHeight
Define Text$, *Text, i

If Not InitScintilla()
	End
EndIf

; возвращает рандомный текст
Procedure.s _Get_Random_Text()
	Protected i, Rnd, Text$
	For i = 0 To 300
; 		Rnd = Random(90, 65)
		Rnd = Random(122, 97)
		Text$ + Chr( Rnd )
; 		If Rnd < 67: Text$ + #CRLF$ : EndIf
		If Rnd < 99: Text$ + #CRLF$ : EndIf
	Next
	ProcedureReturn Text$
EndProcedure

; событие клика по кнопке
Procedure _Event_Click_Tab()
	Protected index = GetGadgetState(#Pn) ; получаем кнопку
	If index + 1 = CurSci
		ProcedureReturn
	EndIf
	HideGadget(CurSci, #True)
	CurSci = index + 1
; 	Debug CurSci
; 	CurSci = GetGadgetItemData(#Pn, index) ; получаем записанный указатель на документ
; 	Debug CurSci
	HideGadget(CurSci, #False)
EndProcedure


Procedure SizeWindowHandler()
	Protected i, w = WindowWidth(#Win)
	ResizeGadget(#Pn, #PB_Ignore, #PB_Ignore, w, #PB_Ignore)
	For i = 1 To CountTabs
		ResizeGadget(i, #PB_Ignore, #PB_Ignore, w - 3, WindowHeight(#Win) - PnTabHeight)
	Next
EndProcedure

;- GUI
If OpenWindow(#Win, 0, 0, 700, 500, "Scintilla-Tab", #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_ScreenCentered | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget )
	PanelGadget(#Pn, 0, 0, 700, 28)
	CountTabs = 8 ; сколько будет табов
	For i = 0 To CountTabs - 1
		AddGadgetItem(#Pn, i, "Tab " +  Str(i))
	Next
	CloseGadgetList()
	For i = 1 To CountTabs
		ScintillaGadget(i, 0, 29, 700 - 4, 500 - 29, 0)
		HideGadget(i, #True)
		ScintillaSendMessage(i, #SCI_STYLESETFORE, 0, $aaaaaa ) ; покрасим основной текст
		ScintillaSendMessage(i, #SCI_STYLESETBACK, 0, $3f3f3f ) ; покрасим основной текст
		ScintillaSendMessage(i, #SCI_STYLESETBACK, #STYLE_DEFAULT, $3f3f3f)    ; цвет фона
		ScintillaSendMessage(i, #SCI_STYLESETFORE, #STYLE_DEFAULT, $aaaaaa) ; цвет текста
		ScintillaSendMessage(i, #SCI_STYLESETSIZE, #STYLE_DEFAULT, 12) ; размер шрифта
	; 	ScintillaSendMessage(i, #SCI_SETSCROLLWIDTHTRACKING, 1, 1)	; Добавляет прокрутку по ширине текущих строк
		ScintillaSendMessage(i, #SCI_SETMARGINWIDTHN, 1, 0)   ; Устанавливает ширину поля 1 (номеров строк)
		SetGadgetItemData(#Pn, i - 1, i) ; привязываем документ к кнопке
		
		; Пишем текст в текущий выбранный документ
		Text$ = _Get_Random_Text()
		*Text = UTF8(Text$)
		ScintillaSendMessage(i, #SCI_SETTEXT, Len(Text$), *Text)
		FreeMemory(*Text)
	Next
	BindGadgetEvent(#Pn, @_Event_Click_Tab(), #PB_All)
	BindEvent(#PB_Event_SizeWindow, @SizeWindowHandler())
	
	CurSci = i - 1
; 	Debug CurSci
	SetGadgetState(#Pn, CurSci - 1)
	HideGadget(CurSci, #False)
	
	
; 	Устанавливаем размер панели по высоте вкладок
	PnTabHeight = GetGadgetAttribute(#Pn, #PB_Panel_TabHeight)
; 	Debug PnTabHeight
	ResizeGadget(#Pn, #PB_Ignore, #PB_Ignore, #PB_Ignore, PnTabHeight)
	For i = 1 To CountTabs
		ResizeGadget(i, #PB_Ignore, PnTabHeight, #PB_Ignore, WindowHeight(#Win) - PnTabHeight)
	Next
; 	SizeWindowHandler()
	
	
	Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf
Without HideGadget + #True/#False

Code: Select all

EnableExplicit

#Win = 0
#Pn = 0

Global CurSci, CountTabs, PnTabHeight
Define Text$, *Text, i, j

If Not InitScintilla()
	End
EndIf

; возвращает рандомный текст
Procedure.s _Get_Random_Text()
	Protected i, Rnd, Text$
	For i = 0 To 300
; 		Rnd = Random(90, 65)
		Rnd = Random(122, 97)
		Text$ + Chr( Rnd )
; 		If Rnd < 67: Text$ + #CRLF$ : EndIf
		If Rnd < 99: Text$ + #CRLF$ : EndIf
	Next
	ProcedureReturn Text$
EndProcedure


Procedure SizeWindowHandler()
	Protected i, w = WindowWidth(#Win)
	Protected h = WindowHeight(#Win)
	ResizeGadget(#Pn, #PB_Ignore, #PB_Ignore, w, h)
	For i = 1 To CountTabs
		ResizeGadget(i, #PB_Ignore, #PB_Ignore, w - 3, h - PnTabHeight)
	Next
EndProcedure

;- GUI
If OpenWindow(#Win, 0, 0, 700, 500, "Scintilla-Tab", #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_ScreenCentered | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget )
	PanelGadget(#Pn, 0, 0, 700, 500)
	CountTabs = 8 ; сколько будет табов
	For i = 0 To CountTabs - 1
		AddGadgetItem(#Pn, i, "Tab " +  Str(i))
		j = i+1
		ScintillaGadget(j, 0, 0, 700 - 4, 500 - 29, 0)
; 		HideGadget(i+1, #True)
		ScintillaSendMessage(j, #SCI_STYLESETFORE, 0, $aaaaaa ) ; покрасим основной текст
		ScintillaSendMessage(j, #SCI_STYLESETBACK, 0, $3f3f3f ) ; покрасим основной текст
		ScintillaSendMessage(j, #SCI_STYLESETBACK, #STYLE_DEFAULT, $3f3f3f)    ; цвет фона
		ScintillaSendMessage(j, #SCI_STYLESETFORE, #STYLE_DEFAULT, $aaaaaa) ; цвет текста
		ScintillaSendMessage(j, #SCI_STYLESETSIZE, #STYLE_DEFAULT, 12) ; размер шрифта
	; 	ScintillaSendMessage(j, #SCI_SETSCROLLWIDTHTRACKING, 1, 1)	; Добавляет прокрутку по ширине текущих строк
		ScintillaSendMessage(j, #SCI_SETMARGINWIDTHN, 1, 0)   ; Устанавливает ширину поля 1 (номеров строк)
		
		; Пишем текст в текущий выбранный документ
		Text$ = _Get_Random_Text()
		*Text = UTF8(Text$)
		ScintillaSendMessage(j, #SCI_SETTEXT, Len(Text$), *Text)
		FreeMemory(*Text)
	Next
	CloseGadgetList()
	For i = 1 To CountTabs
	Next
; 	BindGadgetEvent(#Pn, @_Event_Click_Tab(), #PB_All)
	BindEvent(#PB_Event_SizeWindow, @SizeWindowHandler())

	Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf
Maybe there is a better option? Because I don't like HideGadget + #True/#False. If you create Scintilla on the PanelGadget surface, then the gadget blinks even more when switching tabs.

Re: Scintilla + PanelGadget

Posted: Fri Apr 28, 2023 1:19 pm
by blueb
Very nice AZJIO.

For what it's worth, I found the first version had less flickering on my system.

Win 11 Pro, Pure 6.02b2 x64

Re: Scintilla + PanelGadget

Posted: Thu May 04, 2023 10:58 am
by AZJIO
Too bad I can't bind a double click or context menu to a tab. I wanted to double-click to close the tab, and add some operations with the document to the tab menu. I can do with WinAPI but can't do cross platform.

Re: Scintilla + PanelGadget

Posted: Thu May 04, 2023 12:08 pm
by spikey
Have you seen TabBarGadget - Tabs like in a browser?

In your first example you're not actually using the PanelGadget as a container - so there's no particular reason to use a panel at all. Use a canvas which will give you better drawing and interactivity facilities and draw your own exactly how you want it.