FCoreModule_Popup.vb¶
State before¶
The file existed but was an empty stub:
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
Activatorproperty of typeMyTabPage— 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
BeforePopuphandler that sets the menu caption and applies enable/disable rules based onInstance.LockUserSettingsandInstance.PublisherMode. - Has a
CloseUphandler that clearsActivator(avoids holding a stale reference between popups). - Has five
ItemClickhandlers — 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¶
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:
MyTabPage.ShowContextMenusetss_CoreModule_ContextMenuForm.Activator = Meimmediately before callingShowPopup.BeforePopupand the click handlers readActivatorto get the current core module.CloseUpclears it.
DefineContextMenu¶
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:
- 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. - 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." - Publisher mode.
Publish Module…requires bothPublisherMode = Trueand the unlock state. This matches the existing rule for the per-tab Publish action inFPulseTab_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:
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.