A module to manage the tabulation

Applications, Games, Tools, User libs and useful stuff coded in PureBasic
Mesa
Enthusiast
Enthusiast
Posts: 349
Joined: Fri Feb 24, 2012 10:19 am

A module to manage the tabulation

Post by Mesa »

[Edit] Add PB Internal Structure Gadget MacOS by mk-soft

Code: Select all

;- TOP

;.-------------------------------------------------------------------------------------------------
;|
;|  Title            : Module TabKey
;|  Version          : v1.0
;|  Author					 : Mesa
;|  Copyright        : 
;|                     
;|  PureBasic        : 5.70+ 6.0+
;|  
;|  Operating System : Windows (XP to W11+), Linux ?, MacOS ?
;|  Processor        : x86, x64
;|
;|  API							 : Yes api used: Windows, MacOS and Linux
;|
;|-------------------------------------------------------------------------------------------------
;|
;|  Description      : Module to use the tabulation key with all gadgets
;|
;|  Forum Topic      : https://www.purebasic.fr/french/viewtopic.php?t=18938
;|                     https://www.purebasic.fr/english/viewtopic.php?t=81278
;|  Website          : 
;|
;|  Documentation    : 
;|
;|	Date 						 : 03/2023
;|
;|  Misc.						 : Several procedures system from mk-soft: https://www.purebasic.fr/english/viewtopic.php?f=12&t=72980 
;|										 Several procedures from Thorsten1867: MetaModule.pbi 
;|										 
;|
;.-------------------------------------------------------------------------------------------------


;.-------------------------------------------------------------------------------------------------
;|
;|  How to  use 		 : 1) Add or include the module
;|  			           : 2) Add "UseModule TabKey" or use TabKey:: prefix
;|  				         : 3)	Choice 1: Add once "UseTabKey()" to manage all gadgets in all windows
;| 												Choice 2: Add "UseTabKey(WinID)" to manage all gadgets in the specified window 
;|												Choice 3: Add "AddTabKeyGadget(GadgetID)" to manage gadgets one by one																																																																...
;|                     
;|                   : RemoveTabKeyGadget(GadgetID.i, RestoreInternalTab.i=#False)
;|									 : -> RestoreInternalTab.i=#False: Remove a gadget of the list
;|										 -> RestoreInternalTab.i=#True : The gadget restore its own tab (editorgadget,...)
;|
;.-------------------------------------------------------------------------------------------------


;.-------------------------------------------------------------------------------------------------
;|
;|  Procedures
;|  								 UseTabKey(WindowID.i=#PB_Default): Automatic management
;|									 AddTabKeyGadget(GadgetID.i, Flags.i=#False, WindowID.i=#PB_Default): Manual management
;|									 AddTabKeyWindow(WindowID.i): Manual management
;|									 RemoveTabKeyGadget(GadgetID.i, RestoreInternalTab.i=#False): Remove
;|  								 DebugMe(): Debug
;|
;.-------------------------------------------------------------------------------------------------



;.-------------------------------------------------------------------------------------------------
;|
;|  License Mesa.
;|  The license Mesa is, do what you like but make the World better, easier and enjoyable.
;|
;|
;|
;| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
;| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
;| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
;| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
;| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
;| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
;| SOFTWARE.
;| 
;.-------------------------------------------------------------------------------------------------



CompilerIf #PB_Compiler_IsMainFile
	EnableExplicit
CompilerEndIf


;- ----------------------------------------------------------------------------

;-   DeclareModule
;- ..................

DeclareModule TabKey
	
	;- Constantes
	#Enable_TabulationKey = #True
	
	EnumerationBinary Option
		#InternalTabKey ;=1
	EndEnumeration
	
	
	; Menu Events
	#Event_TabKey      = 64000
	#Event_ShiftTabKey = 63999
	
	;- Public Procedures
	Declare.i AddTabKeyGadget(GadgetID.i, Flags.i=#False, WindowID.i=#PB_Default)
	Declare.i AddTabKeyWindow(WindowID.i)
	Declare.i UseTabKey(WindowID.i=#PB_Default)
	Declare.i RemoveTabKeyGadget(GadgetID.i, RestoreInternalTab.i=#False)
	; 	Declare.i DebugMe()
	
EndDeclareModule
;- ----------------------------------------------------------------------------


;-   Module
;- ..................

;Mesa, mk-soft and Thorsten1867
Module TabKey
	
	EnableExplicit  
	
	;-  Structures
	Structure TabKey_Gadget_Structure        
		Window.i
		Flags.i
	EndStructure 
	
	Structure TabKey_Window_Structure 								
		List Gadget.i()
	EndStructure 
	
	Structure TabKey_Structure              
		Menu.i
		Map Window.TabKey_Window_Structure()
		Map Gadget.TabKey_Gadget_Structure()
	EndStructure 
	
	;- Global
	Global TabKey.TabKey_Structure
	
	
	;-   Private Procedures
	CompilerIf #PB_Compiler_OS = #PB_OS_Windows
		Import ""
			PB_Object_EnumerateStart(PB_Objects)
			PB_Object_EnumerateNext(PB_Objects, *ID.Integer)
			PB_Object_EnumerateAbort(PB_Objects)
			PB_Window_Objects
			PB_Gadget_Objects
		EndImport
	CompilerElse
		ImportC ""
			PB_Object_EnumerateStart(PB_Objects)
			PB_Object_EnumerateNext(PB_Objects, *ID.Integer)
			PB_Object_EnumerateAbort(PB_Objects)
			PB_Window_Objects.i
			PB_Gadget_Objects.i	
		EndImport
	CompilerEndIf
	
  CompilerIf #PB_Compiler_OS = #PB_OS_MacOS
    ; PB Internal Structure Gadget MacOS
    Structure sdkGadget
      *gadget
      *container
      *vt
      UserData.i
      Window.i
      Type.i
      Flags.i
    EndStructure
  CompilerEndIf

	Procedure WindowPB(WindowID) 
		Protected result, window
		
		result = -1
		PB_Object_EnumerateStart(PB_Window_Objects)
		While PB_Object_EnumerateNext(PB_Window_Objects, @window)
			If WindowID = WindowID(window)
				result = window
				Break
			EndIf
		Wend
		PB_Object_EnumerateAbort(PB_Window_Objects)
		
		ProcedureReturn result
	EndProcedure
	
	Procedure GetParentWindowID(Gadget)
		Protected WindowID
		
		If IsGadget(Gadget)
			CompilerSelect #PB_Compiler_OS
					
				CompilerCase #PB_OS_MacOS
					Protected *Gadget.sdkGadget = IsGadget(Gadget)
					WindowID = WindowID(*Gadget\Window)
				CompilerCase #PB_OS_Linux
					WindowID = gtk_widget_get_toplevel_(GadgetID(Gadget))
				CompilerCase #PB_OS_Windows           
					WindowID = GetAncestor_(GadgetID(Gadget), #GA_ROOT)
					
			CompilerEndSelect
		EndIf
		
		ProcedureReturn WindowID
	EndProcedure
	
	Procedure GetWindowID(Gadget)
		ProcedureReturn WindowPB(GetParentWindowID(Gadget))	
	EndProcedure
	
	Procedure GetWindowList(List Windows()) 
		Protected object
		
		ClearList(Windows())
		PB_Object_EnumerateStart(PB_Window_Objects)
		While PB_Object_EnumerateNext(PB_Window_Objects, @object)
			AddElement(Windows())
			Windows() = object
		Wend
		
		ProcedureReturn ListSize(Windows())
	EndProcedure
	
	Procedure GetGadgetList(List Gadgets(), WindowID=0)
		Protected object
		
		ClearList(Gadgets())
		PB_Object_EnumerateStart(PB_Gadget_Objects)
		
		If WindowID = 0
			While PB_Object_EnumerateNext(PB_Gadget_Objects, @object)
				AddElement(Gadgets())
				Gadgets() = object
			Wend
		Else 
			While PB_Object_EnumerateNext(PB_Gadget_Objects, @object)
				If GetParentWindowID(object) = WindowID
					AddElement(Gadgets())
					Gadgets() = object
				EndIf
			Wend
		EndIf
		
		ProcedureReturn ListSize(Gadgets())
	EndProcedure
	
		
	CompilerIf #Enable_TabulationKey
		
		Procedure Event_Tab()
			Protected Window
			
			Window = GetActiveWindow()
			
			If IsWindow(Window)
				If FindMapElement(TabKey\Window(), Str(Window))
					If NextElement(TabKey\Window()\Gadget())
						If IsGadget(TabKey\Window()\Gadget()) 	
							SetActiveGadget(TabKey\Window()\Gadget()) 	
						EndIf
					Else
						FirstElement(TabKey\Window()\Gadget())
						If IsGadget(TabKey\Window()\Gadget()) 
							SetActiveGadget(TabKey\Window()\Gadget()) 
						EndIf
					EndIf
				EndIf
				
			EndIf
			
		EndProcedure
		
		Procedure Event_ShiftTab()
			Protected Window
			
			Window = GetActiveWindow()
			
			If IsWindow(Window)
				
				If FindMapElement(TabKey\Window(), Str(Window))
					If PreviousElement(TabKey\Window()\Gadget())
						If IsGadget(TabKey\Window()\Gadget()) : SetActiveGadget(TabKey\Window()\Gadget()) : EndIf
					Else
						LastElement(TabKey\Window()\Gadget())
						If IsGadget(TabKey\Window()\Gadget()) : SetActiveGadget(TabKey\Window()\Gadget()) : EndIf
					EndIf
				EndIf
				
			EndIf
			
		EndProcedure
		
		Procedure Event_Focus()
			Protected GadgetID = EventGadget()
			
			If FindMapElement(TabKey\Gadget(), Str(GadgetID))
				
				If TabKey\Gadget()\Flags & #InternalTabKey
				
					If IsMenu(TabKey\Menu)
						UnbindMenuEvent(TabKey\Menu, #Event_TabKey,       @Event_Tab())
						UnbindMenuEvent(TabKey\Menu, #Event_ShiftTabKey,  @Event_ShiftTab())
					EndIf 
					
					If IsWindow(TabKey\Gadget()\Window)
						RemoveKeyboardShortcut(TabKey\Gadget()\Window, #PB_Shortcut_Tab)
						RemoveKeyboardShortcut(TabKey\Gadget()\Window, #PB_Shortcut_Shift|#PB_Shortcut_Tab)
					EndIf
					
				EndIf
				
			EndIf
			
		EndProcedure
		
		Procedure Event_LostFocus()
			Protected GadgetID = EventGadget()
			
			If FindMapElement(TabKey\Gadget(), Str(GadgetID))
				
				If TabKey\Gadget()\Flags & #InternalTabKey
					
					If IsWindow(TabKey\Gadget()\Window)
						AddKeyboardShortcut(TabKey\Gadget()\Window, #PB_Shortcut_Tab, #Event_TabKey)
						AddKeyboardShortcut(TabKey\Gadget()\Window, #PB_Shortcut_Shift|#PB_Shortcut_Tab, #Event_ShiftTabKey)
					EndIf
					
					If IsMenu(TabKey\Menu)
						BindMenuEvent(TabKey\Menu, #Event_TabKey,      @Event_Tab())
						BindMenuEvent(TabKey\Menu, #Event_ShiftTabKey, @Event_ShiftTab())
					EndIf
					
				EndIf
				
			EndIf
			
		EndProcedure
		
	CompilerEndIf  
	
	
	
	;- Public Procedures
		Procedure.i AddTabKeyGadget(GadgetID.i, Flags.i=#False, WindowID.i=#PB_Default)
		; Flags: #InternalTabKey - ex. editor gadget will use the tab inside the gadget.
			
			
		If AddMapElement(TabKey\Gadget(), Str(GadgetID))
			
			If WindowID = #PB_Default : WindowID = GetWindowID(GadgetID) : EndIf
			
			If FindMapElement(TabKey\Window(), Str(WindowID)) = #False
				AddTabKeyWindow(WindowID)
			EndIf  
			
			TabKey\Gadget()\Window = WindowID
			TabKey\Gadget()\Flags  = Flags
			
			If AddElement(TabKey\Window(Str(WindowID))\Gadget())
				TabKey\Window(Str(WindowID))\Gadget() = GadgetID
			EndIf
			
			CompilerIf #Enable_TabulationKey
				If IsGadget(GadgetID)
					BindGadgetEvent(GadgetID, @Event_Focus(),     #PB_EventType_Focus)
					BindGadgetEvent(GadgetID, @Event_LostFocus(), #PB_EventType_LostFocus)
				EndIf
			CompilerEndIf
			
			ProcedureReturn #True
		EndIf
		
		ProcedureReturn #False
	EndProcedure
	
	Procedure.i AddTabKeyWindow(WindowID.i)
		
		If IsWindow(WindowID)
			
			If FindMapElement(TabKey\Window(), Str(WindowID))
				
				CompilerIf #Enable_TabulationKey
				
					TabKey\Menu = CreateMenu(#PB_Any, WindowID(WindowID))
					If IsMenu(TabKey\Menu)
						
						RemoveKeyboardShortcut(WindowID, #PB_Shortcut_Tab)
						RemoveKeyboardShortcut(WindowID, #PB_Shortcut_Shift|#PB_Shortcut_Tab)
						
						AddKeyboardShortcut(WindowID, #PB_Shortcut_Tab, #Event_TabKey)
						AddKeyboardShortcut(WindowID, #PB_Shortcut_Shift|#PB_Shortcut_Tab, #Event_ShiftTabKey)
						
						BindMenuEvent(TabKey\Menu, #Event_TabKey,       @Event_Tab())
						BindMenuEvent(TabKey\Menu, #Event_ShiftTabKey,  @Event_ShiftTab())
						
					EndIf	
					
				CompilerEndIf
				
				ProcedureReturn #True
				
			ElseIf AddMapElement(TabKey\Window(), Str(WindowID))
				
				CompilerIf #Enable_TabulationKey
					
					TabKey\Menu = CreateMenu(#PB_Any, WindowID(WindowID))
					If IsMenu(TabKey\Menu)
						
						RemoveKeyboardShortcut(WindowID, #PB_Shortcut_Tab)
						RemoveKeyboardShortcut(WindowID, #PB_Shortcut_Shift|#PB_Shortcut_Tab)
						
						AddKeyboardShortcut(WindowID, #PB_Shortcut_Tab, #Event_TabKey)
						AddKeyboardShortcut(WindowID, #PB_Shortcut_Shift|#PB_Shortcut_Tab, #Event_ShiftTabKey)
						
						BindMenuEvent(TabKey\Menu, #Event_TabKey,       @Event_Tab())
						BindMenuEvent(TabKey\Menu, #Event_ShiftTabKey,  @Event_ShiftTab())
						
					EndIf
					
				CompilerEndIf
				
				ProcedureReturn #True
			EndIf
			
		EndIf
		
		ProcedureReturn #False
	EndProcedure
	
	Procedure.i RemoveTabKeyGadget(GadgetID.i, RestoreInternalTab.i=#False)
		Protected WindowID = GetWindowID(GadgetID)
		
		If FindMapElement(TabKey\Gadget(), Str(GadgetID))
			
			If RestoreInternalTab.i=#False
				ForEach TabKey\Window(Str(WindowID))\Gadget()
					If TabKey\Window(Str(WindowID))\Gadget()=GadgetID
						Break
					EndIf
				Next
				
				DeleteElement(TabKey\Window(Str(WindowID))\Gadget(), 1) 
				DeleteMapElement(TabKey\Gadget(), Str(GadgetID))
				LastElement(TabKey\Window(Str(WindowID))\Gadget())
				
			Else
				TabKey\Gadget()\Flags = #InternalTabKey	
			EndIf
		EndIf
		
	EndProcedure
	
	Procedure UseTabKey(WindowID.i=#PB_Default)
		Protected CountGadget, i
		NewList Windows()
		NewList Gadgets()
		
		If WindowID=#PB_Default
			GetWindowList(Windows())
			ForEach Windows()
				CountGadget= GetGadgetList(Gadgets(), WindowID(Windows()))
				If CountGadget>0
					ForEach Gadgets()	
						AddTabKeyGadget(Gadgets(),#False,Windows())
					Next
				EndIf
			Next
		Else
			CountGadget= GetGadgetList(Gadgets(), WindowID(WindowID))
			If CountGadget>0
				ForEach Gadgets()
					AddTabKeyGadget(Gadgets(),#False,WindowID)
				Next
			EndIf
		EndIf
		
	EndProcedure
	
; 	Procedure DebugMe()
; 		Debug TabKey\Window(Str(1))\Gadget()
; 	EndProcedure
	
EndModule
;- ----------------------------------------------------------------------------



;- Main

CompilerIf #PB_Compiler_IsMainFile
	
	Enumeration Windows
		#Window = 1 
		#Window2
	EndEnumeration
	
	Enumeration Gadgets 
		
		#Button = 1
		#image
		#Combo
		#editor
		#String
		
		
		#Button2
		#image2
		#Combo2
		#editor2
		#String2
		
	EndEnumeration
	
	
	
	
	If OpenWindow(#Window, 50, 200, 310, 360, "TAB Module1", #PB_Window_SystemMenu|#PB_Window_SizeGadget)
		
		ButtonGadget(#Button,   10,  15,  80, 24, "Button", #PB_Button_Toggle) 
		ImageGadget(#image,  110, 15,  80, 24, 0,#PB_Image_Border ) 
		ComboBoxGadget(#Combo, 210, 15, 90, 24)
		AddGadgetItem(#Combo, -1, "Test")
		SetGadgetState(#Combo, 0)
		EditorGadget(#editor,10,60,290,100)
		StringGadget(#String,10,200,290,30,"")
		
		OpenWindow(#Window2, 400, 200, 310, 360, "TAB Module2", #PB_Window_SystemMenu|#PB_Window_SizeGadget)
		
		ButtonGadget(#Button2,   10,  15,  80, 24, "Button", #PB_Button_Toggle) 
		ImageGadget(#image2,  110, 15,  80, 24, 0,#PB_Image_Border ) 
		ComboBoxGadget(#Combo2, 210, 15, 90, 24)
		AddGadgetItem(#Combo2, -1, "Test")
		SetGadgetState(#Combo2, 0)
		EditorGadget(#editor2,10,60,290,100)
		StringGadget(#String2,10,200,290,30,"")
		
		;-TabKey Management
		UseModule TabKey
		
		;Choice 1: Full automatic
		UseTabKey()
		
		;Choice 2: Automatic only for one or more specified windows
		;   				UseTabKey(#Window)
		
		;Choice 3: Handle gadgets manually
		; 					AddTabKeyGadget(#Button)
		; 					AddTabKeyGadget(#image) 
		; 					AddTabKeyGadget(#Combo)
		; 					AddTabKeyGadget(#editor);,#InternalTabKey
		; 					AddTabKeyGadget(#String)
		
		
		RemoveTabKeyGadget(#editor2, #True);editor gadget uses the tab inside the gadget.
		
		SetActiveWindow(#Window)
		
		
		Define Event
		Repeat
			Event = WaitWindowEvent()
			Select Event
				Case #PB_Event_Gadget
					Select EventGadget()
						Case #Button, #Combo To #String
							Debug "ok"
						Case #image
							;Some gadgets have no focus event
							Debug "ok ?"
							
						Case #Combo
							
					EndSelect
			EndSelect        
		Until Event = #PB_Event_CloseWindow
		
		CloseWindow(#Window)
	EndIf
	
CompilerEndIf
Mesa.
Last edited by Mesa on Thu Apr 06, 2023 5:52 pm, edited 1 time in total.
User avatar
mk-soft
Always Here
Always Here
Posts: 5409
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: A module to manage the tabulation

Post by mk-soft »

:wink:

Forgot macOS structure ...

Code: Select all

  CompilerIf #PB_Compiler_OS = #PB_OS_MacOS
    ; PB Internal Structure Gadget MacOS
    Structure sdkGadget
      *gadget
      *container
      *vt
      UserData.i
      Window.i
      Type.i
      Flags.i
    EndStructure
  CompilerEndIf
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
jharris
New User
New User
Posts: 2
Joined: Tue May 24, 2016 3:44 am
Location: North Central Arkansas

Re: A module to manage the tabulation

Post by jharris »

Thanks to both of you for this module!

It works beautifully on my M1 MacBook. It saved me a lot of stress creating my own.
User avatar
Piero
Enthusiast
Enthusiast
Posts: 346
Joined: Sat Apr 29, 2023 6:04 pm
Location: Italy

Re: A module to manage the tabulation

Post by Piero »

Huh?
What's that?
It's not very clear, and I just played with regexps, so I'm like:

Code: Select all

"^?!=[^;].*:?Fred$"
I'll take a look tomorrow

Edit:
Oh, I see now; It's to manage what happens when you press TAB!
Wasn't very clear for noobs like me :x

Edit2:
Maybe it's cuz I'm Italian, but the ORIGINAL "manage tabulations" seemed to be more something like a file with TABS to process
Post Reply