WebGadget frame load delegate [PB x86 / Carbon]

Mac OSX specific forum
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3942
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

WebGadget frame load delegate [PB x86 / Carbon]

Post by wilbert »

Example of creating a delegate class at runtime to monitor loading [PB x86 / Carbon]

Code: Select all

EnableExplicit

; *** import the required C functions ***

ImportC ""
  
  HIWebViewGetWebView(inView)
  
  oClassAddMethod(class, selector, imp, types.p-ascii) As "_class_addMethod"
  oClass(name.p-ascii) As "_objc_lookUpClass"
  oCreateClass(superclass, name.p-ascii, extraBytes = 0) As "_objc_allocateClassPair"
  oInstance(class, extraBytes = 0) As "_class_createInstance"
  CocoaMessageSend(receiver, selector, arg1 = #Null, arg2 = #Null, arg3 = #Null) As "_objc_msgSend"
  oRegisterClass(class) As "_objc_registerClassPair"
  oSel(name.p-ascii) As "_sel_registerName"
  
EndImport

; *** selectors that are used a lot ***

Global SEL_provisionalDataSource = oSel("provisionalDataSource")
Global SEL_dataSource = oSel("dataSource")
Global SEL_request = oSel("request")
Global SEL_URL = oSel("URL")
Global SEL_absoluteString = oSel("absoluteString")
Global SEL_length = oSel("length")
Global SEL_getCharacters_range_ = oSel("getCharacters:range:")
Global SEL_stopLoading = oSel("stopLoading")

; *** functions to get frame url ***

Procedure.s StringFromNSString(nsstring)
  Protected len = CocoaMessageSend(nsstring, SEL_length)
  Protected *mem = malloc_(len << 1); allocate 16 byte aligned uninitialized memory
  CocoaMessageSend(nsstring, SEL_getCharacters_range_, *mem, 0, len)
  Protected result.s = PeekS(*mem, len, #PB_Unicode)
  free_(*mem)
  ProcedureReturn result
EndProcedure

Procedure.s GetFrameURL(frame, provisional = #False)
  Protected source
  If provisional
    source = CocoaMessageSend(frame, SEL_provisionalDataSource)
  Else
    source = CocoaMessageSend(frame, SEL_dataSource)
  EndIf
  Protected urlString = CocoaMessageSend(CocoaMessageSend(CocoaMessageSend(source, SEL_request), SEL_URL), SEL_absoluteString)
  ProcedureReturn StringFromNSString(urlString)
EndProcedure

; *** the functions for our delegate class ***

ProcedureC DidStartProvisionalLoad(obj, sel, webview, frame); load starts
  Protected frameUrl.s = GetFrameURL(frame, #True)
  Debug "Load : " + frameUrl
  If frameUrl = "http://www.purebasic.com/news.php"
    CocoaMessageSend(frame, SEL_stopLoading)
    MessageRequester("", "No news today!")
  EndIf
EndProcedure

ProcedureC ServerRedirect(obj, sel, webview, frame); server redirect
  Debug "Redirect : " + GetFrameURL(frame, #True)
EndProcedure

ProcedureC LoadComplete(obj, sel, webview, frame); load complete
  Debug "Finished loading : " + GetFrameURL(frame)
EndProcedure

ProcedureC Anchor(obj, sel, webview, frame); anchor within page
  Debug "Anchor : " + GetFrameURL(frame)
EndProcedure

; *** create the delegate class and instance ***

Define FrameLoadDelegateClass = oCreateClass(oClass("NSObject"), "PB_FrameLoadDelegate"); PB_FrameLoadDelegate class extends NSObject
oClassAddMethod(FrameLoadDelegateClass, oSel("webView:didStartProvisionalLoadForFrame:"), @DidStartProvisionalLoad(), "v@:@@")
oClassAddMethod(FrameLoadDelegateClass, oSel("webView:didReceiveServerRedirectForProvisionalLoadForFrame:"), @ServerRedirect(), "v@:@@")
oClassAddMethod(FrameLoadDelegateClass, oSel("webView:didFinishLoadForFrame:"), @LoadComplete(), "v@:@@")
oClassAddMethod(FrameLoadDelegateClass, oSel("webView:didChangeLocationWithinPageForFrame:"), @Anchor(), "v@:@@")
oRegisterClass(FrameLoadDelegateClass)
Define FrameLoadDelegate = oInstance(FrameLoadDelegateClass)

; *** class and instance are created now ***


; test the frame load delegate

If OpenWindow(0, 0, 0, 600, 340, "WebPrint", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  
  ButtonGadget(0, 10, 10, 100, 20, "Load page")
  
  Define PBWebView = WebGadget(#PB_Any, 10, 50, 580, 280, "")
  Define WebView = HIWebViewGetWebView(GadgetID(PBWebView))
  CocoaMessageSend(WebView, oSel("setFrameLoadDelegate:"), FrameLoadDelegate)
  
  Repeat
    Define EventID = WaitWindowEvent()
    If EventID = #PB_Event_Gadget
      Select EventGadget()
          
        Case 0
          SetGadgetText(PBWebView, "http://www.purebasic.com")
          
      EndSelect
    EndIf      
  Until EventID = #PB_Event_CloseWindow
  
EndIf