FCoreModule_Popup.vb¶
State before¶
The file existed but was an empty stub:
Public Class FCoreModule_Popup
End Class
The corresponding designer file (FCoreModule_Popup.Designer.vb) had a partial form with bar items already defined, but nothing was wiring it up — the form was never instantiated and the buttons had no click handlers. Some scaffolding existed in CCoreModule.vb (around lines 102–109) but was commented out.
State after¶
A full code-behind. The class:
- Exposes an Activator property of type MyTabPage — set by the caller (MyTabPage.ShowContextMenu) so the click handlers know which core module to operate on.
- Has a DefineContextMenu() method that explicitly wires the popup's items.
- Has a BeforePopup handler that sets the menu caption and applies enable/disable rules based on Instance.LockUserSettings and Instance.PublisherMode.
- Has a CloseUp handler that clears Activator (avoids holding a stale reference between popups).
- Has five ItemClick handlers — one per menu item.
Imports¶
Imports PulseDevTools.ReportingModules
Imports PulseDevTools.TabControl
Imports PulseDevTools.TabControl.MyTabPage
Same imports as FPulseTab_Popup.vb. The third import (a class import, not a namespace) brings the nested ePageType into scope.
Activator pattern¶
Public Property Activator As TabControl.MyTabPage
The fully-qualified TabControl.MyTabPage is intentional — Activator collides with System.Activator, so the property type must be unambiguous. FPulseTab_Popup uses the same pattern.
The flow is:
1. MyTabPage.ShowContextMenu sets s_CoreModule_ContextMenuForm.Activator = Me immediately before calling ShowPopup.
2. BeforePopup and the click handlers read Activator to get the current core module.
3. CloseUp clears it.
DefineContextMenu¶
FCoreModule_Popup.vb
Public Sub DefineContextMenu()
PopupMenu1.Manager = BarManager1
PopupMenu1.ShowCaption = True
PopupMenu1.ClearLinks()
PopupMenu1.AddItem(btnRefresh)
PopupMenu1.AddItem(btnResetToDefault).BeginGroup = True
PopupMenu1.AddItem(btnSaveAndShare)
PopupMenu1.AddItem(btnPublish)
PopupMenu1.AddItem(btnLoadFromFile)
End Sub
Mirrors the proven pattern in MyTabPage.DefinePopContextMenu. Called once on first creation by MyTabPage.ShowContextMenu. The BeginGroup = True on btnResetToDefault produces the visual separator after Refresh Module.
BeforePopup handler¶
Private Sub PopupMenu1_BeforePopup(...) Handles PopupMenu1.BeforePopup
Dim myPopup As DevExpress.XtraBars.PopupMenu = sender
If Activator Is Nothing OrElse Activator.m_CoreModule Is Nothing Then
Exit Sub
End If
myPopup.MenuCaption = "Module: " & Activator.m_CoreModule.ModuleInfo.ModuleCaption
For Each curItemLink As XtraBars.BarItemLink In myPopup.ItemLinks
If curItemLink.Item Is btnRefresh Then
curItemLink.Item.Enabled = True
Else
curItemLink.Item.Enabled = Not Instance.LockUserSettings
End If
Next
btnPublish.Enabled = Instance.PublisherMode AndAlso Not Instance.LockUserSettings
End Sub
Three responsibilities:
1. Menu caption. Shows Module: <name> at the top of the popup so users can confirm which module they're acting on. Useful when right-clicking quickly between modules.
2. Lock state. When Instance.LockUserSettings = True (a deployment-locked-down state), all state-mutating items are disabled. Refresh stays enabled — refreshing data isn't a "setting change."
3. Publisher mode. Publish Module… requires both PublisherMode = True and the unlock state. This matches the existing rule for the per-tab Publish action in FPulseTab_Popup.
Why no e.Cancel
The Activator Is Nothing branch deliberately does not set e.Cancel = True. If the popup is invoked with a stale state, showing a slightly-off menu is more diagnostic for users than swallowing the click silently. In normal flow this branch should never be reached — MyTabPage.ShowContextMenu always sets Activator before ShowPopup.
Click handlers¶
| Handler | Purpose | Cross-reference |
|---|---|---|
btnRefresh_ItemClick |
Refresh every tab in the module | Click Handlers — Refresh |
btnResetToDefault_ItemClick |
Reset module to default tab set | Reset Algorithm |
btnSaveAndShare_ItemClick |
Save module via CSaveAndShareFile |
Click Handlers — Save and Share |
btnPublish_ItemClick |
Publish to other users | Publish/Receive Loop |
btnLoadFromFile_ItemClick |
Load .pmod file |
Click Handlers — Load From File |
All handlers start with the same null-check:
If Activator Is Nothing OrElse Activator.m_CoreModule Is Nothing Then Exit Sub
This is defensive — under normal flow `Activator` is always set, but if the popup is somehow shown without an Activator, the click is a no-op rather than an NPE.