Module: Blockly

Share your advanced knowledge/code with the community.
User avatar
Peter
Posts: 1086
Joined: Mon Feb 24, 2014 10:17 pm
Location: 127.0.0.1:9080
Contact:

Module: Blockly

Post by Peter »

Hello,

here is a wrapper to use the JavaScript-Library Blockly from Google:

Image

Demo: http://spiderbytes.tuebben.de/demos/Blockly/

Download: http://spiderbytes.tuebben.de/downloads/blockly.zip

More informations: https://developers.google.com/blockly/

Have fun! ... Peter
tj1010
Posts: 201
Joined: Wed May 27, 2015 1:36 pm
Contact:

Re: Module: Blockly

Post by tj1010 »

Cool! Reminds me of Sketchy or whatever that educational programming thing MIT did years ago.
falsam
Posts: 280
Joined: Mon May 05, 2014 9:49 pm
Location: France
Contact:

Re: Module: Blockly

Post by falsam »

Hello Peter.

I am not a fan of code with blocks but congratulations and thank you for sharing. It is a beautiful result and easy to understand.

➽ Windows 11 - JDK 1.8 - SB 2.40 - Android 13
http://falsam.com

Sorry for my poor english
IdeasVacuum
Posts: 143
Joined: Tue Feb 25, 2014 1:27 pm

Re: Module: Blockly

Post by IdeasVacuum »

Hello Peter

There are a number of online IDEs based on Blockly, I am using MIT's App Inventor to create Android Apps - it's very good. I would like to build a program alongside it (separate but smart) that can scrape key names (the names of Blocks) and store them in a sorted list with a record of their location on the canvas. This would be very useful because once your blocks count is above a thousand, it is difficult to navigate. So a dynamic list like Pure Basics' Procedures List would be great.

The browsers can find block names and highlight them, but it's not good enough, especially when the highlight is lost as soon as you scroll, and of course you have to remember the name to look for. Programatically, the find can be based on block type names e.g. find 'Procedure', then collect the User's name for it, e.g. 'MyDataIn'. That I think I can tackle - but how to determine the location on the canvas and scroll the Browser to it on demand?
User avatar
Peter
Posts: 1086
Joined: Mon Feb 24, 2014 10:17 pm
Location: 127.0.0.1:9080
Contact:

Re: Module: Blockly

Post by Peter »

@IdeasVacuum: Sorry, but this is too abstract for me. Do you have a sample code or a screenshot that illustrates your concern?
IdeasVacuum
Posts: 143
Joined: Tue Feb 25, 2014 1:27 pm

Re: Module: Blockly

Post by IdeasVacuum »

Hi Peter - yup, a bit too wordy, a picture paints a thousand words:

Image

So I am collecting the title text from every main block, and listing them in the same way that PB lists Procedures. What I wish to do is click on a list item and take the User to the corresponding block.
User avatar
Peter
Posts: 1086
Joined: Mon Feb 24, 2014 10:17 pm
Location: 127.0.0.1:9080
Contact:

Re: Module: Blockly

Post by Peter »

First you have to go through all blocks to get the IDs of the ParentBlocks (parentBlock_==null). But I think you already know this because you have already determined the list of blocks.

If you have determined the ID of a ParentBlock you can center the complete block in the ViewPort.

That would look something like this:

Code: Select all

XIncludeFile "Blockly.sbi"

Enumeration
  #XmlToolbox
  #XmlWorkspace
  #Dialog
  #Xml
EndEnumeration

Runtime Enumeration
  #Window
  #Blockly
  #Splitter
  #ListView
EndEnumeration

Procedure SizeWindowEvent()
  ResizeGadget(#Splitter, 0, 0, WindowWidth(#Window), WindowHeight(#Window))
EndProcedure

Runtime Procedure OnListViewEvent()
  
  Protected SelectedID.s
  
  SelectedID = GetGadgetText(#ListView)
  
  Protected GID = GadgetID(#Blockly)
  
  ! var selector  = $(v_gid.div).find('.dijitContentPane');
  ! var workspace = selector.data("workspace");
  ! var block = workspace.getBlockById(v_selectedid);
  
  ! // https://github.com/google/blockly/issues/1013#issuecomment-290713644
  ! block.select(); // *block* is the block to scroll into view.
  ! var mWs = Blockly.mainWorkspace;
  ! var xy = block.getRelativeToSurfaceXY(); // Scroll the workspace so that the block's top left corner
  ! var m = mWs.getMetrics(); // is in the (0.2; 0.3) part of the viewport.
  ! mWs.scrollbar.set(	xy.x * mWs.scale - m.contentLeft - m.viewWidth  * 0.2, xy.y * mWs.scale - m.contentTop  - m.viewHeight * 0.3);  
    
EndProcedure

Procedure OnChange()
  
  Protected GID = GadgetID(#Blockly)
  
  ! var selector  = $(v_gid.div).find('.dijitContentPane');
  ! var workspace = selector.data("workspace");
  ! var allBlocks = workspace.getAllBlocks();
  
  Protected ID.s
  ClearGadgetItems(#ListView)
  
  ! for (var blockCounter = 0; blockCounter < allBlocks.length; blockCounter ++) {
  !   if (allBlocks[blockCounter].parentBlock_ == null) {
  !     v_id = allBlocks[blockCounter].id;
  AddGadgetItem(#ListView, -1, ID)
  !   }
  ! }
   
EndProcedure

Procedure Main()
  
  Protected XML.s
  
  XML = "<window id='#Window' name='Window' text='BlocklyDemo' minwidth='1000' minheight='600' flags='#PB_Window_ScreenCentered | #PB_Window_SystemMenu | #PB_Window_SizeGadget'>" +
        " <splitter id='#Splitter' flags='#PB_Splitter_Vertical'>" +
        "   <container id='#Blockly' />" +
        "   <vbox expand='item:2'>" +
        "     <text text='Block-IDs:' flags='#PB_Text_VerticalCenter' />" +
        "     <listview id='#ListView' onevent='OnListViewEvent()' />" +
        "   </vbox>" + 
        " </splitter>" +
        "</window>"
  
  
  If ParseXML(#Xml, XML) And XMLStatus(#Xml) = #PB_XML_Success
    
    If CreateDialog(#Dialog) And OpenXMLDialog(#Dialog, #Xml, "Window")
      
      ; setting splitter:
      
      SetGadgetState(#Splitter, 600)  
      
      ; setting blockly-container
      
      Blockly::BindGadget(#Blockly, ComposeXML(#XmlToolbox))
      Blockly::TextToWorkspace(#Blockly, ComposeXML(#XmlWorkspace))
      Blockly::Refresh(#Blockly)
      Blockly::ScrollCenter(#Blockly)
      Blockly::BindBlocklyEvent(#Blockly, @OnChange())
      
    Else  
      Debug "Dialog error: " + DialogError(#Dialog)
    EndIf
    
  Else
    Debug "XML error: " + XMLError(#Xml) + " (Line: " + XMLErrorLine(#Xml) + ")"
  EndIf
  
EndProcedure

Procedure Loading(Type, Filename.s, ObjectId)
  
  Static nbOfXml
  
  Select Type
      
    Case #PB_Loading_Xml
      
      nbOfXml + 1
      
      If nbOfXml = 2
        Blockly::Init(@Main())
      EndIf
      
  EndSelect
  
EndProcedure

Procedure LoadingError(Type, Filename.s)
  Debug "LoadingError: " + Filename
EndProcedure


BindEvent(#PB_Event_Loading, @Loading())
BindEvent(#PB_Event_LoadingError, @LoadingError())

LoadXML(#XmlToolbox,   "./resources/toolboxes/toolbox.xml")
LoadXML(#XmlWorkspace, "./resources/workspaces/workspace.xml")
(Place more ParentBlocks into the viewport and click on the listitems on the right to center them)
IdeasVacuum
Posts: 143
Joined: Tue Feb 25, 2014 1:27 pm

Re: Module: Blockly

Post by IdeasVacuum »

Phew - that's a fast and comprehensive response, thank you Peter. I was wondering if it could not be done with blockly API, I could do it via the DOM and find each elements scroll position, but a blockly approach is preferable. Thanks again!
Post Reply