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.
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
------------------------------