Skip to content

Commit

Permalink
Finish UI for toggling "snap to canvas edge" behavior
Browse files Browse the repository at this point in the history
A menu is now provided (`View > Snap to canvas edge`), and custom snap distance is changeable via `Tools > Options > Interface`.

A lot of code is required to provide a UI for this feature, since snap settings need to be persistent between sessions, but still easily toggleable in a top-level menu.

Next up: actually implementing the snap feature (sigh).
  • Loading branch information
tannerhelland committed Apr 5, 2024
1 parent 16c0e18 commit 85a4a76
Show file tree
Hide file tree
Showing 8 changed files with 125 additions and 20 deletions.
12 changes: 12 additions & 0 deletions Forms/MainWindow.frm
Original file line number Diff line number Diff line change
Expand Up @@ -1729,6 +1729,14 @@ Begin VB.Form FormMain
Caption = "Show status bar"
Index = 7
End
Begin VB.Menu MnuView
Caption = "-"
Index = 8
End
Begin VB.Menu MnuView
Caption = "Snap to canvas edges"
Index = 9
End
End
Begin VB.Menu MnuWindowTop
Caption = "Window"
Expand Down Expand Up @@ -3828,6 +3836,10 @@ Private Sub MnuView_Click(Index As Integer)
Actions.LaunchAction_ByName "view_rulers"
Case 7
Actions.LaunchAction_ByName "view_statusbar"
Case 8
'(separator)
Case 9
Actions.LaunchAction_ByName "snap_canvasedge"
End Select
End Sub

Expand Down
42 changes: 35 additions & 7 deletions Forms/Tools_Options.frm
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,23 @@ Begin VB.Form FormOptions
Width = 8295
_ExtentX = 14631
_ExtentY = 11853
Begin PhotoDemon.pdSpinner spnSnapDistance
Height = 375
Left = 120
TabIndex = 44
Top = 4560
Width = 1935
_ExtentX = 3413
_ExtentY = 661
DefaultValue = 8
Min = 1
Max = 255
Value = 8
End
Begin PhotoDemon.pdPictureBox picGrid
Height = 735
Left = 150
Top = 4530
Top = 5610
Width = 735
_ExtentX = 1296
_ExtentY = 1296
Expand Down Expand Up @@ -133,7 +146,7 @@ Begin VB.Form FormOptions
Height = 810
Left = 1080
TabIndex = 2
Top = 4500
Top = 5580
Width = 3015
_ExtentX = 5318
_ExtentY = 1429
Expand All @@ -144,7 +157,7 @@ Begin VB.Form FormOptions
Height = 795
Left = 4140
TabIndex = 4
Top = 4500
Top = 5580
Width = 3015
_ExtentX = 5318
_ExtentY = 1402
Expand All @@ -155,7 +168,7 @@ Begin VB.Form FormOptions
Height = 690
Left = 7260
TabIndex = 5
Top = 4560
Top = 5640
Width = 465
_ExtentX = 820
_ExtentY = 1217
Expand All @@ -165,7 +178,7 @@ Begin VB.Form FormOptions
Height = 690
Left = 7770
TabIndex = 6
Top = 4560
Top = 5640
Width = 465
_ExtentX = 820
_ExtentY = 1217
Expand All @@ -175,7 +188,7 @@ Begin VB.Form FormOptions
Height = 285
Index = 2
Left = 0
Top = 4080
Top = 5160
Width = 8205
_ExtentX = 14473
_ExtentY = 503
Expand Down Expand Up @@ -205,6 +218,18 @@ Begin VB.Form FormOptions
ForeColor = 4210752
Layout = 2
End
Begin PhotoDemon.pdLabel lblTitle
Height = 285
Index = 23
Left = 0
Top = 4080
Width = 8100
_ExtentX = 14288
_ExtentY = 503
Caption = "snap distance (in pixels)"
FontSize = 12
ForeColor = 4210752
End
End
Begin PhotoDemon.pdContainer picContainer
Height = 6720
Expand Down Expand Up @@ -1180,10 +1205,12 @@ Private Sub cmdBarMini_OKClick()
g_RecentMacros.MRU_NotifyNewMaxLimit
End If

UserPrefs.SetPref_Long "Interface", "snap-distance", spnSnapDistance.Value
Tools_Move.SetSnapDistance spnSnapDistance.Value

UserPrefs.SetPref_Long "Transparency", "Alpha Check Mode", CLng(cboAlphaCheck.ListIndex)
UserPrefs.SetPref_Long "Transparency", "Alpha Check One", CLng(csAlphaOne.Color)
UserPrefs.SetPref_Long "Transparency", "Alpha Check Two", CLng(csAlphaTwo.Color)

UserPrefs.SetPref_Long "Transparency", "Alpha Check Size", cboAlphaCheckSize.ListIndex
Drawing.CreateAlphaCheckerboardDIB g_CheckerboardPattern

Expand Down Expand Up @@ -1408,6 +1435,7 @@ Private Sub LoadAllPreferences()
csCanvasColor.Color = UserPrefs.GetCanvasColor()
tudRecentFiles.Value = UserPrefs.GetPref_Long("Interface", "Recent Files Limit", 10)
btsMRUStyle.ListIndex = UserPrefs.GetPref_Long("Interface", "MRU Caption Length", 0)
spnSnapDistance.Value = UserPrefs.GetPref_Long("Interface", "snap-distance", 8&)
m_userInitiatedAlphaSelection = False
cboAlphaCheck.ListIndex = UserPrefs.GetPref_Long("Transparency", "Alpha Check Mode", 0)
csAlphaOne.Color = UserPrefs.GetPref_Long("Transparency", "Alpha Check One", RGB(255, 255, 255))
Expand Down
19 changes: 11 additions & 8 deletions Modules/Actions.bas
Original file line number Diff line number Diff line change
Expand Up @@ -1299,6 +1299,7 @@ Private Function Launch_ByName_MenuView(ByRef srcMenuName As String, Optional By
If (Not PDImages.IsImageActive()) Then Exit Function

Dim cmdFound As Boolean: cmdFound = True
Dim newState As Boolean

Select Case srcMenuName

Expand Down Expand Up @@ -1344,16 +1345,17 @@ Private Function Launch_ByName_MenuView(ByRef srcMenuName As String, Optional By
If FormMain.MainCanvas(0).IsZoomEnabled Then FormMain.MainCanvas(0).SetZoomDropDownIndex 21

Case "view_rulers"
Dim newRulerState As Boolean
newRulerState = Not FormMain.MainCanvas(0).GetRulerVisibility()
FormMain.MnuView(6).Checked = newRulerState
FormMain.MainCanvas(0).SetRulerVisibility newRulerState
newState = Not FormMain.MainCanvas(0).GetRulerVisibility()
FormMain.MnuView(6).Checked = newState
FormMain.MainCanvas(0).SetRulerVisibility newState

Case "view_statusbar"
Dim newStatusBarState As Boolean
newStatusBarState = Not FormMain.MainCanvas(0).GetStatusBarVisibility()
FormMain.MnuView(7).Checked = newStatusBarState
FormMain.MainCanvas(0).SetStatusBarVisibility newStatusBarState
newState = Not FormMain.MainCanvas(0).GetStatusBarVisibility()
FormMain.MnuView(7).Checked = newState
FormMain.MainCanvas(0).SetStatusBarVisibility newState

Case "snap_canvasedge"
Interface.ToggleSnapOptions pdst_CanvasEdge

Case Else
cmdFound = False
Expand Down Expand Up @@ -2000,6 +2002,7 @@ Public Sub BuildActionDatabase()
AddAction "zoom_1_16", vbNullString
AddAction "view_rulers", vbNullString
AddAction "view_statusbar", vbNullString
AddAction "snap_canvasedge", vbNullString
'AddAction "window_toolbox"
AddAction "window_displaytoolbox", vbNullString
AddAction "window_displaytoolcategories", vbNullString
Expand Down
24 changes: 24 additions & 0 deletions Modules/Interface.bas
Original file line number Diff line number Diff line change
Expand Up @@ -1210,6 +1210,30 @@ Public Sub ToggleImageTabstripVisibility(ByVal newSetting As Long, Optional ByVa

End Sub

'Toggle one of the "snap to..." settings in the View menu.
' To forcibly set to a specific state (instead of toggling), set the forceInsteadOfToggle param to TRUE.
Public Sub ToggleSnapOptions(ByVal snapTarget As PD_SnapTargets, Optional ByVal forceInsteadOfToggle As Boolean = False, Optional ByVal newState As Boolean = True)

'Convert the snap target into a menu index
Const IDX_BASE As Long = 9
Dim idxTarget As Long

'While calculating which on-screen menu to update, we also need to relay changes to two places:
' 1) the tools_move module (which handles actual snap calculations)
' 2) the user preferences file (to ensure everything is synchronized between sessions)
Select Case snapTarget
Case pdst_CanvasEdge
idxTarget = IDX_BASE + 0
If (Not forceInsteadOfToggle) Then newState = Not Tools_Move.GetSnapCanvasEdge()
Tools_Move.SetSnapCanvasEdge newState
UserPrefs.SetPref_Boolean "Interface", "snap-canvas-edge", newState
End Select

'Update the target menu state
FormMain.MnuView(idxTarget).Checked = newState

End Sub

Public Function FixDPI(ByVal pxMeasurement As Long) As Long

'The first time this function is called, m_DPIRatio will be 0. Calculate it.
Expand Down
2 changes: 2 additions & 0 deletions Modules/Menus.bas
Original file line number Diff line number Diff line change
Expand Up @@ -590,6 +590,8 @@ Public Sub InitializeMenus()
AddMenuItem "-", "-", 8, 5
AddMenuItem "Show rulers", "view_rulers", 8, 6
AddMenuItem "Show status bar", "view_statusbar", 8, 7
AddMenuItem "-", "-", 8, 8
AddMenuItem "Snap to canvas edge", "snap_canvasedge", 8, 9

'Window Menu
AddMenuItem "Window", "window_top", 9
Expand Down
39 changes: 36 additions & 3 deletions Modules/MoveTool.bas
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,34 @@ Attribute VB_Name = "Tools_Move"
'PhotoDemon Move/Size Tool Manager
'Copyright 2014-2024 by Tanner Helland
'Created: 24/May/14
'Last updated: 22/December/22
'Last update: add some trivial key-handling bits for the Hand tool (which is a different tool, but it has
' so few features that it's easier to just condense things here)
'Last updated: 05/April/24
'Last update: start wiring up Snap capabilities
'
'This module interfaces between the layer move/size UI and actual layer backend. Look in the relevant
' tool panel form for more details on how the UI relays relevant tool data here.
'
'As of 2024, This module also handles move-related duties like snapping to various features.
'
'Unless otherwise noted, all source code in this file is shared under a simplified BSD license.
' Full license details are available in the LICENSE.md file, or at https://photodemon.org/license/
'
'***************************************************************************

Option Explicit

Public Enum PD_SnapTargets
pdst_CanvasEdge
End Enum

#If False Then
Private Const pdst_CanvasEdge = 0
#End If

'The move/size tool exposes a number of UI-only options (like drawing borders around active layers).
' To improve viewport performance, we cache those settings locally, and the viewport queries us instead
' of directly querying the associated UI elements.
Private m_DrawLayerBorders As Boolean, m_DrawCornerNodes As Boolean, m_DrawRotateNodes As Boolean
Private m_SnapToCanvasEdge As Boolean, m_SnapDistance As Long

'Same goes for various selection-related move settings (for moving selected pixels). These are simple
' flags whose value is relayed from the Move/Size options panel.
Expand Down Expand Up @@ -315,6 +325,19 @@ Public Function GetDrawLayerRotateNodes() As Boolean
GetDrawLayerRotateNodes = m_DrawRotateNodes
End Function

Public Function GetSnapCanvasEdge() As Boolean
GetSnapCanvasEdge = m_SnapToCanvasEdge
End Function

Public Function GetSnapDistance() As Long

GetSnapDistance = m_SnapDistance

'Failsafe only; should never trigger
If (GetSnapDistance < 1) Then GetSnapDistance = 8

End Function

Public Sub SetDrawLayerBorders(ByVal newState As Boolean)
m_DrawLayerBorders = newState
End Sub
Expand All @@ -327,6 +350,16 @@ Public Sub SetDrawLayerRotateNodes(ByVal newState As Boolean)
m_DrawRotateNodes = newState
End Sub

Public Sub SetSnapCanvasEdge(ByVal newState As Boolean)
m_SnapToCanvasEdge = newState
End Sub

Public Sub SetSnapDistance(ByVal newDistance As Long)
m_SnapDistance = newDistance
If (m_SnapDistance < 1) Then m_SnapDistance = 1
If (m_SnapDistance > 255) Then m_SnapDistance = 255 'GIMP uses a 255 max value; that seems reasonable
End Sub

'Relay functions for move selected pixels behavior
Public Function GetMoveSelectedPixels_DefaultCut() As Boolean
GetMoveSelectedPixels_DefaultCut = m_SelectionDefaultCut
Expand Down
5 changes: 4 additions & 1 deletion Modules/UserPrefs.bas
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Attribute VB_Name = "UserPrefs"
'Created: 03/November/12
'Last updated: 21/February/22
'Last update: revert nightly builds to default to "nightly build" update track (I've gotten much better
' at disciplined nightly build development, and they are far more stable than the used to be).
' at disciplined nightly build development, and they are far more stable than they used to be).
'
'This is the modern incarnation of PD's old "INI file" module. It is responsible for managing all
' persistent user settings.
Expand Down Expand Up @@ -609,6 +609,9 @@ Public Sub LoadUserSettings()
Tools.SetToolSetting_HighResMouse UserPrefs.GetPref_Boolean("Tools", "HighResMouseInput", True)
m_CanvasColor = Colors.GetRGBLongFromHex(UserPrefs.GetPref_String("Interface", "CanvasColor", "#a0a0a0"))

Interface.ToggleSnapOptions pdst_CanvasEdge, True, UserPrefs.GetPref_Boolean("Interface", "snap-canvas-edge", True)
Tools_Move.SetSnapDistance UserPrefs.GetPref_Long("Interface", "snap-distance", 8&)

'Users can supply a (secret!) "UIFont" setting in the "Interface" segment if they
' want to override PD's default font object.
m_UIFontName = UserPrefs.GetPref_String("Interface", "UIFont", vbNullString, False)
Expand Down
2 changes: 1 addition & 1 deletion PhotoDemon.vbp
Original file line number Diff line number Diff line change
Expand Up @@ -526,7 +526,7 @@ Description="PhotoDemon Photo Editor"
CompatibleMode="0"
MajorVer=9
MinorVer=1
RevisionVer=347
RevisionVer=348
AutoIncrementVer=1
ServerSupportFiles=0
VersionComments="Copyright 2000-2024 Tanner Helland - photodemon.org"
Expand Down

0 comments on commit 85a4a76

Please sign in to comment.