Skip to content

Commit

Permalink
Window menu: a list of open images is now displayed...
Browse files Browse the repository at this point in the history
...at the bottom of the Window menu.  This basically duplicates the functionality of the "image tabstrip" PD provides, but for users who disable the tabstrip, they will still have a way to "jump" to any open image.

This also mirrors similar functionality in Photoshop and GIMP.

Thank you to G Busch for the suggestion!
  • Loading branch information
tannerhelland committed Aug 26, 2021
1 parent a145c20 commit 009721d
Show file tree
Hide file tree
Showing 6 changed files with 192 additions and 36 deletions.
13 changes: 7 additions & 6 deletions Classes/pdRecentFiles.cls
Original file line number Diff line number Diff line change
Expand Up @@ -229,9 +229,9 @@ Friend Sub UpdateUI_NonEmptyList()
End If

'Ensure the special menus at the bottom of the Recent Files list are available
FormMain.MnuRecentSepBar1.Visible = True
FormMain.MnuLoadAllMRU.Visible = True
FormMain.MnuClearMRU.Visible = True
For i = 0 To FormMain.MnuRecentFiles.Count - 1
FormMain.MnuRecentFiles(i).Visible = True
Next i

'Update any relevant thumbnail icons. (TODO: ensure this isn't being called from multiple places.)
IconsAndCursors.ResetMenuIcons
Expand All @@ -255,9 +255,10 @@ Friend Sub UpdateUI_EmptyList()
End If

FormMain.MnuRecDocs(0).Enabled = False
FormMain.MnuRecentSepBar1.Visible = False
FormMain.MnuClearMRU.Visible = False
FormMain.MnuLoadAllMRU.Visible = False

For i = 0 To FormMain.MnuRecentFiles.Count - 1
FormMain.MnuRecentFiles(i).Visible = False
Next i

'All icons in this menu need to be manually reset after the list is cleared; the ResetMenuIcons function
' will also call the Menus.UpdateSpecialMenu_RecentFiles() function to set all captions properly.
Expand Down
78 changes: 56 additions & 22 deletions Forms/MainWindow.frm
Original file line number Diff line number Diff line change
Expand Up @@ -65,14 +65,17 @@ Begin VB.Form FormMain
Enabled = 0 'False
Index = 0
End
Begin VB.Menu MnuRecentSepBar1
Begin VB.Menu MnuRecentFiles
Caption = "-"
Index = 0
End
Begin VB.Menu MnuLoadAllMRU
Begin VB.Menu MnuRecentFiles
Caption = "Open all recent images"
Index = 1
End
Begin VB.Menu MnuClearMRU
Begin VB.Menu MnuRecentFiles
Caption = "Clear recent image list"
Index = 2
End
End
Begin VB.Menu MnuFile
Expand Down Expand Up @@ -1762,6 +1765,17 @@ Begin VB.Form FormMain
Caption = "Previous image"
Index = 8
End
Begin VB.Menu MnuWindow
Caption = "-"
Index = 9
Visible = 0 'False
End
Begin VB.Menu MnuWindowOpen
Caption = "empty"
Enabled = 0 'False
Index = 0
Visible = 0 'False
End
End
Begin VB.Menu MnuHelpTop
Caption = "Help"
Expand Down Expand Up @@ -2088,6 +2102,33 @@ Private Sub MnuMacroCreate_Click(Index As Integer)
End Select
End Sub

Private Sub MnuRecentFiles_Click(Index As Integer)

Select Case Index

Case 0
'separator

'Load all MRU files
Case 1
Dim listOfFiles As pdStringStack
Set listOfFiles = New pdStringStack

Dim i As Long
For i = 0 To g_RecentFiles.GetNumOfItems() - 1
listOfFiles.AddString g_RecentFiles.GetFullPath(i)
Next i

Loading.LoadMultipleImageFiles listOfFiles, True

'Clear MRU
Case 2
g_RecentFiles.ClearList

End Select

End Sub

Private Sub MnuRender_Click(Index As Integer)
Select Case Index
Case 0
Expand Down Expand Up @@ -2724,6 +2765,18 @@ Private Sub MnuView_Click(Index As Integer)
End Select
End Sub

Private Sub MnuWindowOpen_Click(Index As Integer)

'Open the current document corresponding to the index in the menu
Dim listOfOpenImages As pdStack
PDImages.GetListOfActiveImageIDs listOfOpenImages

If (Index < listOfOpenImages.GetNumOfInts) Then
If PDImages.IsImageActive(listOfOpenImages.GetInt(Index)) Then CanvasManager.ActivatePDImage listOfOpenImages.GetInt(Index), "window menu"
End If

End Sub

Private Sub MnuWindowToolbox_Click(Index As Integer)

'Because this is a checkbox-based menu, we handle its commands specially
Expand Down Expand Up @@ -3355,10 +3408,6 @@ Private Sub MnuBlur_Click(Index As Integer)
End Select
End Sub

Private Sub MnuClearMRU_Click()
g_RecentFiles.ClearList
End Sub

'All Color sub-menu entries are handled here.
Private Sub MnuColor_Click(Index As Integer)
Select Case Index
Expand Down Expand Up @@ -3723,21 +3772,6 @@ Private Sub MnuLighting_Click(Index As Integer)
End Select
End Sub

'Load all images in the current "Recent Files" menu
Private Sub MnuLoadAllMRU_Click()

Dim listOfFiles As pdStringStack
Set listOfFiles = New pdStringStack

Dim i As Long
For i = 0 To g_RecentFiles.GetNumOfItems() - 1
listOfFiles.AddString g_RecentFiles.GetFullPath(i)
Next i

Loading.LoadMultipleImageFiles listOfFiles, True

End Sub

'All metadata sub-menu options are handled here
Private Sub MnuMetadata_Click(Index As Integer)
Select Case Index
Expand Down
8 changes: 7 additions & 1 deletion Modules/Interface.bas
Original file line number Diff line number Diff line change
Expand Up @@ -535,7 +535,10 @@ Private Sub SetUIMode_NoImages()
'With all menus reset to their default values, we can now redraw all associated menu icons.
' (IMPORTANT: this function must be called whenever menu captions change, because icons are associated by caption.)
IconsAndCursors.ResetMenuIcons


'Ensure the Windows menu does not list any open images.
Menus.UpdateSpecialMenu_WindowsOpen

'If no images are currently open, but images were previously opened during this session, release any memory associated
' with those images. This helps minimize PD's memory usage at idle.
If (PDImages.GetNumSessionImages >= 1) Then PDImages.ReleaseAllPDImageResources
Expand Down Expand Up @@ -2034,6 +2037,9 @@ Public Sub NotifyNewActiveImage(Optional ByVal newImageIndex As Long = -1)
'A newly activated image requires a whole swath of UI changes. Ask SyncInterfaceToCurrentImage to handle this for us.
Interface.SyncInterfaceToCurrentImage

'Ensure the list of open windows (on the main form > Window menu) is up-to-date
Menus.UpdateSpecialMenu_WindowsOpen

End Sub

'This function should only be used if the entire tabstrip needs to be redrawn due to some massive display-related change
Expand Down
126 changes: 120 additions & 6 deletions Modules/Menus.bas
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ Attribute VB_Name = "Menus"
'
'***************************************************************************


Option Explicit

Private Type PD_MenuEntry
Expand Down Expand Up @@ -922,6 +921,7 @@ Public Sub UpdateAgainstCurrentTheme(Optional ByVal redrawMenuBar As Boolean = T
' (e.g. the "Languages" menu), while others must be handled here.
Menus.UpdateSpecialMenu_RecentFiles
Menus.UpdateSpecialMenu_RecentMacros
Menus.UpdateSpecialMenu_WindowsOpen

If redrawMenuBar Then DrawMenuBar FormMain.hWnd

Expand Down Expand Up @@ -3319,15 +3319,129 @@ Public Sub UpdateSpecialMenu_Language(ByVal numOfLanguages As Long, ByRef availa

End Sub

'The main form's Window menu displays a list of open images. This list must be updated whenever...
' 1) An image is loaded
' 2) An image is unloaded
' 3) A different image is "activated" (e.g. selected for editing)
' 4) The current image is saved to a different filename
Public Sub UpdateSpecialMenu_WindowsOpen()

Dim i As Long

'Quick branch for "no open images" state (it's much easier to handle)
If (PDImages.GetNumOpenImages > 0) Then

'Images are potentially stored non-sequentially. Retrieve a list of active image IDs from the
' central image manager.
Dim listOfOpenImages As pdStack
PDImages.GetListOfActiveImageIDs listOfOpenImages

'Ensure the correct number of menus are available. (This may involve freeing existing menus
' when an image is closed, or adding new menus when an image is opened.)

'This limit is effectively arbitrary, but useability of this menu is kind of pointless
' past a certain point. (Windows may have its own menu count limit as well, idk; I deliberately
' prefer to stay well beneath that amount.)
Const MAX_NUM_MENU_ENTRIES As Long = 64

Dim numImagesAllowed As Long
numImagesAllowed = PDMath.Min2Int(MAX_NUM_MENU_ENTRIES, listOfOpenImages.GetNumOfInts)

If (FormMain.MnuWindowOpen.Count > numImagesAllowed) Then
For i = FormMain.MnuWindowOpen.Count - 1 To numImagesAllowed - 1 Step -1
If (i <> 0) Then Unload FormMain.MnuWindowOpen(i)
Next i
End If

Dim curMenuCount As Long
curMenuCount = FormMain.MnuWindowOpen.Count
If (curMenuCount < numImagesAllowed) Then
For i = curMenuCount To numImagesAllowed - 1
Load FormMain.MnuWindowOpen(i)
Next i
End If

'The correct number of menu entries are now available.

'To ensure offsets retrieved from API menu calls are valid, we need to ensure the separator bar
' above the open window section is visible *before* interacting with items beneath it.
' (FYI: individual menus start at index 10 (9 is the separator bar above the first open image entry))
Const MENU_OFFSET As Long = 10
FormMain.MnuWindow(MENU_OFFSET - 1).Visible = True

'We now need to set all menu captions to match the filename of each open image. (As part of setting
' the correct names, we'll also set visible/enabled/checked state.)

'Menu bar itself
Dim hMenu As Long
hMenu = GetMenu(FormMain.hWnd)

'Window menu
hMenu = GetSubMenu(hMenu, 9&)

'Prepare a MenuItemInfo struct
Dim tmpMii As Win32_MenuItemInfoW
tmpMii.cbSize = LenB(tmpMii)
tmpMii.fMask = MIIM_STRING

'Note that we have to use WAPI to do this, because filenames may have Unicode chars.
For i = 0 To numImagesAllowed - 1

'Use VB to set the rest of the parameters; this will also trigger a DrawMenuBar call
With FormMain.MnuWindowOpen(i)
.Visible = True
.Enabled = True
.Checked = (listOfOpenImages.GetInt(i) = PDImages.GetActiveImageID)
End With

'Retrieve the caption (which should be the location on-disk, unless the image hasn't been saved
' in which case the loader will have assigned the image a "suggested" filename)
Dim tmpCaption As String
If PDImages.GetImageByID(listOfOpenImages.GetInt(i)).ImgStorage.DoesKeyExist("CurrentLocationOnDisk") Then
tmpCaption = Files.FileGetName(PDImages.GetImageByID(listOfOpenImages.GetInt(i)).ImgStorage.GetEntry_String("CurrentLocationOnDisk"), False)
End If

If (LenB(tmpCaption) = 0) Then
tmpCaption = Files.FileGetName(PDImages.GetImageByID(listOfOpenImages.GetInt(i)).ImgStorage.GetEntry_String("OriginalFileName"), False)
End If


Debug.Print "caption?", tmpCaption, hMenu, MENU_OFFSET + i
'Assign the caption via WAPI to preserve Unicode chars
tmpMii.dwTypeData = StrPtr(tmpCaption)
Debug.Print SetMenuItemInfoW(hMenu, MENU_OFFSET + i, 1&, tmpMii), "SetMenuItemInfoW"
Debug.Print Err.LastDllError

Next i

'Use the API to trigger a state change for any new captions
DrawMenuBar FormMain.hWnd

'No open images. Unload all menu items and hide the separator bar at the top of this section.
Else

If (FormMain.MnuWindowOpen.Count > 1) Then
For i = 1 To FormMain.MnuWindowOpen.Count - 1
Unload FormMain.MnuWindowOpen(i)
Next i
End If

'Hide the final instance and the separator bar above it
FormMain.MnuWindow(9).Visible = False
FormMain.MnuWindowOpen(0).Visible = False

End If

End Sub

'Whenever the "File > Open Recent" menu is modified, we need to modify our internal list of recent file items.
' (We manually track this menu so we can handle translations correctly for the items at the bottom of the menu,
' e.g. "Load all" and "Clear list", as well as menu captions for recent files with Unicode filenames.)
Public Sub UpdateSpecialMenu_RecentFiles()

'Whenever the "File > Open Recent" menu is modified, we need to modify our internal list of recent file items.
' (We manually track this menu so we can handle translations correctly for the items at the bottom of the menu,
' e.g. "Load all" and "Clear list".)

'Start by retrieving a handle to the menu in question
If (Not g_RecentFiles Is Nothing) Then

Dim hMenu As Long
hMenu = GetMenu(FormMain.hWnd)
hMenu = GetSubMenu(hMenu, 0&)
Expand Down
1 change: 1 addition & 0 deletions Modules/Saving.bas
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ Public Function PhotoDemon_SaveImage(ByRef srcImage As pdImage, ByVal dstPath As
g_RecentFiles.AddFileToList dstPath, srcImage
Interface.SyncInterfaceToCurrentImage
Interface.NotifyImageChanged PDImages.GetActiveImageID()
Menus.UpdateSpecialMenu_WindowsOpen
End If

'At this point, it's safe to re-enable the main form and restore the default cursor
Expand Down
2 changes: 1 addition & 1 deletion PhotoDemon.vbp
Original file line number Diff line number Diff line change
Expand Up @@ -478,7 +478,7 @@ Description="PhotoDemon Photo Editor"
CompatibleMode="0"
MajorVer=8
MinorVer=9
RevisionVer=679
RevisionVer=681
AutoIncrementVer=1
ServerSupportFiles=0
VersionComments="Copyright 2000-2021 Tanner Helland - photodemon.org"
Expand Down

0 comments on commit 009721d

Please sign in to comment.