Event woes in custom dialogue

BlitzMax Forums/MaxGUI Module/Event woes in custom dialogue

Ghost Dancer(Posted 2010) [#1]
I have been trying to make a stand-alone dialog function that works much like the Confirm command but also has a text field to get data from the user.

This is the code for the function:



This works fine when the main program uses a simple event loop, for example:



However, if the main program uses event hooks to manage the events it hangs the program as in the following example:



I've been working on this for hours but I can't work out how to solve the problem. I have tried making the RequestInput use hooks as well but that didn't work either (I can post the code if it helps).

Any suggestions how to get this working?


degac(Posted 2010) [#2]
Hi,
Have you seen this?

On that base I made this 'about gadget' using proxygadgets, and it seems to work very well


Maybe you can find inspiration to resolve your implementation.

Cheers


JoshK(Posted 2010) [#3]
You can't make a nice neat self-contained function like that. You have to add an event hook, and detect when the button is closed.


Ghost Dancer(Posted 2010) [#4]
Thanks, I did do a search but somehow missed that one. The main thing I need to do that differs from those examples is to halt the main program flow whilst my dialog is running, as it is requesting user input partway through an operation (much like how RequestFile works), and the problem I'm getting is related to this.

I already tried a hooked version but it resulted in the same problem. Full code below:



The problem seems to be the Repeat/WaitSystem loop, but I need something like this to halt the main program flow until the dialog is closed.


Ghost Dancer(Posted 2010) [#5]
Any other suggestions to solve this? I really need it to behave like a Confirm dialog (or similar) so program flow only continues once the dialog is closed.


TAS(Posted 2012) [#6]
What about deleting the event hook at start and re-installing upon exit?


skn3(Posted 2012) [#7]
Create a window stack so when you open a window a new entry is added to the stack. All previous windows are disabled. When you close the dialogue, remove it from the stack and enable the top most window on stack.


This is ripped from my dialogue class so no idea how well it is working but hopefully it will help.

You will need the maxguiex module for some functions for bringing the window to the top n stuff.
https://github.com/skn3/maxguiex

you could probably remove the two lines
				BringWindowToTop(dialogue)
				FocusWindow(dialogue)

and then you wouldn't need maxguiex and find an alternative?

[bbcode]Import maxgui.drivers
Import maxgui.proxygadgets
Import skn3.maxguiex

Type Skn3Dialogue Extends TProxyGadget
Global hooked:Int
Global stack:TList = CreateList()
Global classes:TMap = CreateMap()

Field Window:TGadget

Field IsActive:Int = False
Field isOpen:Int = False
Field isModal:Int = True

Field hasOpened:Int = False

Field stackLink:TLink
Field stackActiveGadget:TGadget

'function api
Function OpenDialogue:Skn3Dialogue(dialogue:Skn3Dialogue,parent:Skn3Dialogue)
' --- open a dialogue spawned from this dialogue ---
If dialogue = Null Return Null

'open this dialogue
dialogue.Open()

'return it
Return dialogue
End Function

Function GetTopMostDialogue:Skn3Dialogue()
' --- return teh top most dialogue in the applet ---
Return Skn3Dialogue(stack.Last())
End Function

'hooks
Function EventHook:Object(id:Int,data:Object,context:Object)
Local event:TEvent = TEvent(data)

'check valid event
If event
'process all dialogues from top of dialogue stack to bottom
Local link:TLink = stack.LastLink()
Local dialogue:Skn3Dialogue

While link
'get dialogue
dialogue = Skn3Dialogue(link.value())

'see if the dialogue is handling the event
If dialogue.isOpen And dialogue.OnFilterEvent(event)
event = dialogue.OnEvent(event)
If event = Null Return Null
EndIf

'previous link
link = link.PrevLink()
Wend
EndIf

'return
Return event
EndFunction

'constructor/destructor
Method New()
If hooked = False
hooked = True
AddHook(EmitEventHook,Skn3Dialogue.EventHook,Null)
EndIf
End Method

'events
Method OnCreate:Skn3Dialogue() Abstract

Method OnFilterEvent:Int(event:TEvent)
Return True
End Method

Method OnEvent:TEvent(event:TEvent)
Select event.id
Case EVENT_WINDOWCLOSE
' --- window is closed ---
If event.source = Self
close()

'return event used
Return Null
End If
End Select

Return event
End Method

Method OnClose()
If Window FreeGadget(Window)
End Method

'api
Method OpenChildDialogue:Skn3Dialogue(dialogue:skn3Dialogue)
Return Skn3Dialogue.OpenDialogue(dialogue,Self)
End Method

Method Open()
' --- open the dialogue ---
If Window And isOpen = False
'flag this dialogue open
isOpen = True

Local link:TLink
Local dialogue:Skn3Dialogue

'for the top most dialogue remember the active gadget
dialogue = Skn3Dialogue(stack.Last())
If dialogue
'get active gadget
dialogue.stackActiveGadget = ActiveGadget()

'make sure the gadget is not the dialogue window
If dialogue.stackActiveGadget = dialogue.Window dialogue.stackActiveGadget = Null
EndIf

'lock all other dialogues if this new dialogue is modal!
If isModal
link = stack.FirstLink()
While link
'get dialogue
dialogue = Skn3Dialogue(link.value())

'disable dialogue
If dialogue.isModal DisableGadget(dialogue)

'next dialogue
link = link.NextLink()
Wend
EndIf

'add this dialogue to the stack if it is a modal
stackLink = stack.AddLast(Self)

'setup the dialogue window
If hasOpened = False ShowGadget(Window)

'reset first open flag
hasOpened = True
EndIf
End Method

Method close()
' --- close the dialogue and remove it from the stack ---
'ok indicated whether we are just closing or if we are returning
Local link:TLink
Local dialogue:Skn3Dialogue

'first activate the what will be new top most dialogue
link = stackLink.PrevLink()
If link
While link
dialogue = Skn3Dialogue(link.value())
if dialogue.isModal Exit
link = link.PrevLink()
dialogue = Null
Wend

If dialogue And dialogue.Window
'activate the dialogue window
EnableGadget(dialogue)
BringWindowToTop(dialogue)
FocusWindow(dialogue)

'activate a gadget if there was one
If dialogue.stackActiveGadget <> Null
ActivateGadget(dialogue.stackActiveGadget)
dialogue.stackActiveGadget = Null
EndIf
EndIf
EndIf

'now pop dead dialogues starting from this off the stack
link = stackLink
While link
'get dialogue
dialogue = Skn3Dialogue(link.value())

dialogue.OnClose()

'next link
link = link.NextLink()

'remove the dialogue from the stack
If dialogue.isModal
dialogue.stackLink.remove()
dialogue.stackLink = Null
EndIf
Wend

'return successful close
Return Null
End Method
End Type

Type Skn3DialogueParent Extends Skn3Dialogue
Field button:TGadget

Method OnCreate:Skn3Dialogue()
Window = CreateWindow("parent window",50,50,300,300,Null,WINDOW_TITLEBAR)
SetProxy(Window)

button = CreateButton("press",5,5,Window.ClientWidth()-10,Window.ClientHeight()-10,Window)

Return Self
End Method

Method OnFilterEvent:Int(event:TEvent)
Return event.source = button
End Method

Method OnEvent:TEvent(event:TEvent)
Select event.id
Case EVENT_GADGETACTION
Select event.source
Case button
OpenChildDialogue(New Skn3DialogueChild.OnCreate())
Return Null
End Select
End Select

Return Super.OnEvent(event)
End Method
End Type

Type Skn3DialogueChild Extends Skn3Dialogue
Method OnCreate:Skn3Dialogue()
Window = CreateWindow("child window",50,50,150,150,Null,WINDOW_TOOL | WINDOW_TITLEBAR)
SetProxy(Window)

Return Self
End Method
End Type

Local parentDialogue:Skn3Dialogue = New Skn3DialogueParent.OnCreate()
parentDialogue.Open()

Repeat
WaitEvent()
Forever[/bbcode]

Last edited 2012

Last edited 2012

Last edited 2012