PureBasic Forum
https://www.purebasic.fr/english/

Problem with sheet Alert
https://www.purebasic.fr/english/viewtopic.php?f=19&t=74595
Page 1 of 1

Author:  Wolfram [ Tue Feb 11, 2020 11:52 am ]
Post subject:  Problem with sheet Alert

I use a sheet modal Alert, but the menu events are still fired.
How can i make it work like a normal Alert which blocks all events?

Code:
; NSBlock module by Wilbert
; last update July 17, 2015

DeclareModule NSBlock
 
  Structure NSBlock
    *isa
    flags.l
    reserved.l
    *invoke
    *descriptor
  EndStructure
 
  Structure NSBlockWithPtr
    *block.NSBlock
    _block.NSBlock
  EndStructure
 
  Declare InitNSBlockWithPtr(*NSBlockWithPtr.NSBlockWithPtr, *Invoke, IsGlobal = #True)
 
EndDeclareModule

Module NSBlock
 
  Global.i NSConcreteGlobalBlock, NSConcreteStackBlock, DyLib
 
  DyLib = OpenLibrary(#PB_Any, "libSystem.dylib")
  If DyLib
    NSConcreteGlobalBlock = GetFunction(DyLib, "_NSConcreteGlobalBlock")
    NSConcreteStackBlock = GetFunction(DyLib, "_NSConcreteStackBlock")   
    CloseLibrary(DyLib)
  EndIf
 
  If Not NSConcreteGlobalBlock
    MessageRequester("Error", "Unable to access _NSConcreteGlobalBlock symbol")
    End
  EndIf
 
  DataSection
    NSBlockDescriptor:
    Data.i 0, SizeOf(NSBlock), 0, 0
  EndDataSection
 
  Procedure InitNSBlockWithPtr(*NSBlockWithPtr.NSBlockWithPtr, *Invoke, IsGlobal = #True)
    *NSBlockWithPtr\block = @*NSBlockWithPtr\_block
    With *NSBlockWithPtr\_block
      If IsGlobal
        \isa = NSConcreteGlobalBlock
        \flags = $30000000
      Else
        \isa = NSConcreteStackBlock
        \flags = $20000000
      EndIf
      \invoke = *Invoke
      \descriptor = ?NSBlockDescriptor
    EndWith
  EndProcedure
 
EndModule

; *** End of NSBlock module ***


UseModule NSBlock

#NSCriticalAlertStyle = 2
#NSInformationalAlertStyle = 1
#NSWarningAlertStyle = 0

Enumeration NSAlertButton
  #firstButton =1000
  #secondButton
EndEnumeration


#NSCommandKeyMask    = 1 << 20

Global MyBlockWithPtr.NSBlockWithPtr


;//Custom Icon for Alert
Global myIcon = CreateImage(#PB_Any, 64, 64, 32, $FFF26A0B)

Global mainWindow, button


ProcedureC ModalSheetCallback(*Block.NSBlock, returnCode)
 


  Select returnCode
    Case #firstButton
      Debug "OK"
     
    Case #secondButton
      Debug "Not OK"
     
  EndSelect

EndProcedure


InitNSBlockWithPtr(@MyBlockWithPtr, @ModalSheetCallback())



Procedure sheetAlert(message.s = "", informativeText.s= "", hasAccessory = #NO, icon = #Null)
 
 
    NSAlert = CocoaMessage(0,CocoaMessage(0, 0, "NSAlert alloc"), "init")
   
    CocoaMessage(0, NSAlert, "setMessageText:$", @message)
    CocoaMessage(0, NSAlert, "setInformativeText:$", @informativeText)
   
   
    defaultButton =CocoaMessage(0, NSAlert, "addButtonWithTitle:$", @"OK")
   
    noButton =CocoaMessage(0, NSAlert, "addButtonWithTitle:$", @"not OK")
    CocoaMessage(0, noButton, "setKeyEquivalent:$", @"n")
    CocoaMessage(0, noButton, "setKeyEquivalentModifierMask:", #NSCommandKeyMask)
   
   
    CocoaMessage(0, NSAlert, "setAlertStyle:", #NSInformationalAlertStyle)
   
    If icon
      CocoaMessage(0, NSAlert, "setIcon:", ImageID(icon))
    EndIf
   

   
    If hasAccessory
      strGadget = StringGadget(#PB_Any, 20, 68, 327, 20, "...you answare")
     
      strGadgetID = GadgetID(strGadget)
      CocoaMessage(0, NSAlert, "setAccessoryView:", strGadgetID)
     
     
      CocoaMessage(0, strGadgetID, "currentEditor")
     
      ;//Set defaultButton action while StringGadget has focus
      CocoaMessage(0, strGadgetID, "setTarget:", defaultButton)
      CocoaMessage(0, strGadgetID, "setAction:", sel_registerName_("performClick:"))
     
      CocoaMessage(0, NSAlert, "layout")
     
      CocoaMessage(0, strGadgetID, "becomeFirstResponder")

     
    EndIf
   
    CocoaMessage(0, NSAlert, "beginSheetModalForWindow:", WindowID(mainWindow), "completionHandler:@", @MyBlockWithPtr)

EndProcedure


Procedure mainWindowEvents(event)
 
  Select event
    Case #PB_Event_CloseWindow
      ProcedureReturn #False
     
    Case #PB_Event_Menu
      Debug "Menu is triggert"
      Select EventMenu()
         
         
      EndSelect
     
    Case #PB_Event_Gadget
      Select EventGadget()
        Case button
          sheetAlert("My Alert", "Global warming", #YES, myIcon)
         
        Case strGadget
          If EventType() = #PB_EventType_Change
            Debug GetGadgetText(strGadget)
          EndIf
         
      EndSelect
  EndSelect
 
  ProcedureReturn #True
EndProcedure




mainWindow = OpenWindow(#PB_Any, 0, 0, 400, 120, "MAIN WINDOW", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
button = ButtonGadget(#PB_Any, 150, 30, 90, 25, "show Alert")

If CreateMenu(0, WindowID(mainWindow))
  MenuTitle("TestMenu")
  MenuItem(0, "Open..."   +#TAB$+"Cmd+O")
EndIf


Repeat
  event = WaitWindowEvent()
Until mainWindowEvents(event) = #False

Author:  Wolfram [ Wed Feb 12, 2020 6:25 pm ]
Post subject:  Re: Problem with sheet Alert

I put a loop with WaitWindowEvent() inside the sheetRequester().
Normale you should use only one event loop, but in this case it seams to be ok.

Can someone verify it?
Code:
; NSBlock module by Wilbert
; last update July 17, 2015

DeclareModule NSBlock
  #waitForRequest = 0
  Global sheetResult
 
  Structure NSBlock
    *isa
    flags.l
    reserved.l
    *invoke
    *descriptor
  EndStructure
 
  Structure NSBlockWithPtr
    *block.NSBlock
    _block.NSBlock
  EndStructure
 
  Declare InitNSBlockWithPtr(*NSBlockWithPtr.NSBlockWithPtr, *Invoke, IsGlobal = #True)
 
EndDeclareModule


Module NSBlock
 
  Global.i NSConcreteGlobalBlock, NSConcreteStackBlock
  Define DyLib
 
  DyLib = OpenLibrary(#PB_Any, "libSystem.dylib")
  If DyLib
    NSConcreteGlobalBlock = GetFunction(DyLib, "_NSConcreteGlobalBlock")
    NSConcreteStackBlock = GetFunction(DyLib, "_NSConcreteStackBlock")   
    CloseLibrary(DyLib)
  EndIf
 
  If Not NSConcreteGlobalBlock
    MessageRequester("Error", "Unable to access _NSConcreteGlobalBlock symbol")
    End
  EndIf
 
  DataSection
    NSBlockDescriptor:
    Data.i 0, SizeOf(NSBlock), 0, 0
  EndDataSection
 
  Procedure InitNSBlockWithPtr(*NSBlockWithPtr.NSBlockWithPtr, *Invoke, IsGlobal = #True)
    *NSBlockWithPtr\block = @*NSBlockWithPtr\_block
    With *NSBlockWithPtr\_block
      If IsGlobal
        \isa = NSConcreteGlobalBlock
        \flags = $30000000
      Else
        \isa = NSConcreteStackBlock
        \flags = $20000000
      EndIf
      \invoke = *Invoke
      \descriptor = ?NSBlockDescriptor
    EndWith
  EndProcedure
 
EndModule

; *** End of NSBlock module ***


UseModule NSBlock

#NSCriticalAlertStyle = 2
#NSInformationalAlertStyle = 1
#NSWarningAlertStyle = 0

Enumeration NSAlertButton
  #firstButton =1000
  #secondButton
  #thirdButton
EndEnumeration


#NSCommandKeyMask    = 1 << 20

Global MyBlockWithPtr.NSBlockWithPtr


Global mainWindow, button


ProcedureC sheetChannleCallback(*Block.NSBlock, returnCode)
 
  NSBlock::sheetResult = returnCode
EndProcedure


InitNSBlockWithPtr(@MyBlockWithPtr, @sheetChannleCallback())


Procedure sheetRequester(message.s = "", informativeText.s= "")
 
  Protected NSAlert
  Protected defaultButton, buttonNo, buttonElse
  sheetResult = #waitForRequest
 
  NSAlert = CocoaMessage(0, CocoaMessage(0, 0, "NSAlert alloc"), "init")
  CocoaMessage(0, NSAlert, "setMessageText:$", @message)
  CocoaMessage(0, NSAlert, "setInformativeText:$", @informativeText)
 
 
  defaultButton =CocoaMessage(0, NSAlert, "addButtonWithTitle:$", @"Yes")
 
 
  buttonNo =CocoaMessage(0, NSAlert, "addButtonWithTitle:$", @"No")
  Protected frame.CGPoint
  CocoaMessage(@frame, buttonNo, "frame", 0)
  frame\x -28
  CocoaMessage(0, buttonNo, "setFrame:@", @frame)
  CocoaMessage(0, buttonNo, "setKeyEquivalent:$", @"n")
 
 
 
  buttonElse =CocoaMessage(0, NSAlert, "addButtonWithTitle:$", @"Else")
  CocoaMessage(0, buttonElse, "setKeyEquivalent:$", @"e")
 
 
  CocoaMessage(0, NSAlert, "setAlertStyle:", #NSInformationalAlertStyle)
 
 
  CocoaMessage(0, NSAlert, "layout")
 
 
  CocoaMessage(0, NSAlert, "beginSheetModalForWindow:", WindowID(mainWindow), "completionHandler:@", @MyBlockWithPtr)
 
 
  Repeat
    WaitWindowEvent()
  Until sheetResult <> #waitForRequest
 
  ProcedureReturn sheetResult
EndProcedure


Procedure mainWindowEvents(event)
 
  Select event
    Case #PB_Event_CloseWindow
      ProcedureReturn #False
     
    Case #PB_Event_Menu
      Debug "Menu is triggert"
      Select EventMenu()
             
      EndSelect
     
    Case #PB_Event_Gadget
      Select EventGadget()
        Case button
          result = sheetChanaleRequester("Massage", "Please make your choice...")
          Select result
            Case #firstButton
              Debug "Yes"
            Case #secondButton
              Debug "No"
            Case #thirdButton
              Debug "Else"
          EndSelect
         
      EndSelect
  EndSelect
 
  ProcedureReturn #True
EndProcedure



mainWindow = OpenWindow(#PB_Any, 0, 0, 400, 120, "MAIN WINDOW", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
button = ButtonGadget(#PB_Any, 150, 30, 90, 25, "show Alert")

If CreateMenu(0, WindowID(mainWindow))
  MenuTitle("TestMenu")
  MenuItem(0, "Open..."   +#TAB$+"Cmd+O")
EndIf


Repeat
  event = WaitWindowEvent()
Until mainWindowEvents(event) = #False

Author:  wilbert [ Wed Feb 12, 2020 8:06 pm ]
Post subject:  Re: Problem with sheet Alert

Wolfram wrote:
I use a sheet modal Alert, but the menu events are still fired.
How can i make it work like a normal Alert which blocks all events?

I think it has to do with sheet modal.
If you use "runModal" instead, menu events are ignored but that way the alert box is not attached to the window.

Page 1 of 1 All times are UTC + 1 hour
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/