MapInfo Pro

 View Only

MapBasic Monday: Interacting with the Layer List

  • 1.  MapBasic Monday: Interacting with the Layer List

    Employee
    Posted 04-28-2025 03:03
    Edited by Peter Møller 04-28-2025 07:51

    Almost four months ago, I wrote an article about interacting with the Table List through MapBasic in response to a question from our English partner, CDR Group. In today's post, we will look at interacting with the Layer List.

    The process is very similar. On the Table Lists, you could only interact with the tables. With the Layer List, you can interact with maps and layers.

    Interacting with the Table List and the Layer List allows the user to select the table or layer on which she wants to act. This simplifies the process and skips the steps of showing a dialog where she has to select the table or layer from a long list of names.

    I'll show a couple of examples from the WindowHelper tool.

    You can find the full source code for the WindowHelper tool on GitHub.
    Happy #MapInfoMonday!

    Adding a Control to the Layer List Context Menu

    First, you need to add a menu item to one of the context menus of the Layer List. You have two context menus to choose from: One for the map elements and one for the layer elements.

    Here is an example of how you can add a menu item to the Map context menu using the RibbonLib from the MapBasic Common Libraries:

    	nCtrlIdx = RBNCntxtMenuAddMenuItem(MenuId_LcMapsShortcut, "exmapCntxtCloneMap", "Clone Map", "")
    	If nCtrlIdx > 0 Then
    		Call RBNControlSetToolTipIdx(nCtrlIdx, PRGIGetApplicationName(), "Clone this map"), "")
    		Call RBNControlSetIconsIdx(nCtrlIdx, CONTROL_SIZE_SMALL, MI_IMG_MAP_CLONEMAP_16, MI_IMG_MAP_CLONEMAP_32)
    		Call RBNControlSetLeftMarginIdx(nCtrlIdx, 0)
    		Call RBNControlSetCustomMBXHandlerIdx(nCtrlIdx, "MAPHCloneMapLC")
    	End If
    

    I start by adding the menu item using the function RBNCntxtMenuAddMenuItem. Notice that the function takes the ID of the context menu MenuId_LcMapsShortcut to add the menu item to. The function returns the ID of the new menu item, which I store in the variable nCtrlIdx.

    Then I can configure the look and behaviour of the menu item using additional procedures from the RibbonLib and the menu item ID.

    Similarly, I can add a menu item to the context menu of the layers.

    	nCtrlIdx = RBNCntxtMenuAddMenuItem(MenuId_LcLayersShortcut, "exlyrCntxtCntxtCloseTable", "Close table", "")
    	If nCtrlIdx > 0 Then
    		Call RBNControlSetToolTipIdx(nCtrlIdx, PRGIGetApplicationName(), "Close selected table", "")
    		Call RBNControlSetIconsIdx(nCtrlIdx, CONTROL_SIZE_SMALL, "", PATH_IMAGES & "Close Table 24x24.png")
    		Call RBNControlSetLeftMarginIdx(nCtrlIdx, 0)
    		Call RBNControlSetCustomMBXHandlerIdx(nCtrlIdx, "TABHCloseTableLC")
    	End If
    

    This is the same as for the context menu for the map elements. Here, I refer to the ID of the layer context menu instead: MenuId_LcLayersShortcut.

    Both examples add the menu item to the end of the context menus. You can also insert the menu item somewhere in the existing context menu if you prefer. This can be done using a different function: You can use the function RBNCntxtMenuInsertMenuItem to insert the menu item at a specific location, or you can use the function RBNCntxtMenuInsertMenuItemAfter to place the menu item after an existing named menu item.

    The Procedures Called from the Menu Items

    Now let's look at the procedures called from the menu item to understand how you can figure out what map or layer was selected by the user.

    Let's start with the procedure that clones the map.

    Sub MAPHCloneMapLC
    
    Dim	nMID As Integer
    
    OnError GoTo ErrorOccured
    
    	If NOT LayerControlInfo(LC_INFO_SEL_COUNT) = 1 Then
    		Note "Please select one map in the Layer List!"
    		Exit Sub
    	End If
    
    	nMID		= LayerControlSelectionInfo (1, LC_SEL_INFO_MAPWIN_ID)
    	If nMID = 0 Then
    		Note "Please select one map in the Layer List!"
    		Exit Sub
    	End If
    
    	Set Window nMID Front
    	Run Menu Command M_MAP_CLONE_MAPPER
    
    	Exit Sub
    '-------------------------
    ErrorOccured:
    	Call ERRCreate(Err(), Error$(), "MAPHCloneMapLC")
    	Call ERRShow()
    
    End Sub

    The procedure to close an existing map has been designed to only work with one map at a time.

    Therefore, I start by verifying that only one item has been selected in the Layer List using this function call: LayerControlInfo(LC_INFO_SEL_COUNT).  This will return the number of selected items in the Layer List.

    Next, I get the ID of the selected map.

    To clone the map, I set it as the active window and run the menu command for cloning maps: Run Menu Command M_MAP_CLONE_MAPPER

    The procedure allowing the user to close the table of the selected layers is a bit more complex.

    Sub TABHCloseTableLC
    
    Dim	nMID, arrMIDs(), nLayerID, arrLayerIDs(), nLayer, nTab As Integer,
    	sTab, arrTables(), sFile As String
    
    OnError GoTo ErrorOccured
    
    	If LayerControlInfo(LC_INFO_SEL_COUNT) = 0 Then
    		Note "Please select at least one layer in the Layer List!"
    		Exit Sub
    	End If
    
    	If LayerControlSelectionInfo (1, LC_SEL_INFO_TYPE) <> LC_SEL_INFO_TYPE_LAYER Then
    		Note "Please select at least one layer in the Layer List!"
    		Exit Sub
    	End If
    
    	'**Looping through the selected layers
    	For nLayer = 1 To LayerControlInfo(LC_INFO_SEL_COUNT)
    		nMID		= LayerControlSelectionInfo (nLayer, LC_SEL_INFO_MAPWIN_ID)
    		nLayerID	= LayerControlSelectionInfo (nLayer, LC_SEL_INFO_LAYER_ID)
    		If nLayerID > 0 Then
    			Do Case LayerInfo(nMID, nLayerID, LAYER_INFO_TYPE)
    				Case LAYER_INFO_TYPE_COSMETIC
    					'** do nothing
    				Case LAYER_INFO_TYPE_THEMATIC
    					Call ARRAYAddValueInteger(arrMIDs, nMID)
    					Call ARRAYAddValueInteger(arrLayerIDs, nLayerID)
    
    				Case Else
    					sTab 	= LayerInfo(nMID, nLayerID, LAYER_INFO_NAME)
    					Call ARRAYAddValueString(arrTables, sTab)
    			End Case
    		End If
    	Next
    
    	'**Removing Thematic Layers
    	For nLayer = Ubound(arrLayerIDs) To 1 Step -1
    		Remove Map
    			Window arrMIDs(nLayer)
    			Layer arrLayerIDs(nLayer)
    			Interactive
    	Next
    
    	'**Closing selected tables
    	For nTab = 1 To Ubound(arrTables)
    		Call TABClose(arrTables(nTab))
    	Next
    
    	Exit Sub
    '-------------------------
    ErrorOccured:
    	Call ERRCreate(Err(), Error$(), "TABHCloseTableLC")
    	Call ERRShow()
    
    End Sub 'TABHCloseTableLC

    First, I ensure the user has selected at least one element in the Layer List. Then I make sure that the first selected element is a layer.

    Now I can analyze what specific layers were selected.

    I loop over the selected layers and, depending on their type, I do one of two things:

    For normal layers, I capture and store the table name for the layer in an array called arrTables.

    For thematic layers, I capture and store the map ID and layer ID.

    It is important not to make any changes to the maps and layers until you have read the details about all the selected elements. Otherwise, the order will change and you will run into various issues with the IDs.

    Now it is time to close the selected tables. Again, I separate this into two:

    For thematic layers, I only remove the thematic layer from the map. I assume that if the user wants the actual table closed, she could have selected the base layer instead of the thematic layer.

    Also, notice that I loop over the thematic layers backwards. This is again to avoid messing with the layer order. When I remove a layer from a map window, the layers after the removed layer will be assigned new IDs. By removing the layers from the bottom, I do not mess with the IDs of the layers closer to the top.

    For any other layer types, I close the table for the selected layer. This will also remove the layer from this map and other maps as well.

    By the way, with a focus on user experience, the Precisely support website has undergone several updates over the past year.

    I encourage everyone to explore the latest website features, including AI-powered search capabilities and our redesigned product help pages: Product Help – Precisely Support

    Also note that when you use the search capability here in the Knowledge Community, the AI search will automatically also search other support websites and articles.

    If you are new to the customer portal, self-registration options are now available: Contact Support – Precisely Support



    ------------------------------
    Peter Horsbøll Møller
    Principal Presales Consultant | Distinguished Engineer
    Precisely | Trust in Data
    ------------------------------