Skip to content

Commit 24f5082

Browse files
committed
New Layer > Replace menu
Relates to #317. Thank you to @jpbro for this suggestion, and my apologies for taking so long to implement it. PhotoDemon now provides a Layer > Replace menu which has three options for updating the current layer's contents in-place: 1) From the clipboard 2) From an arbitrary image file 3) From the current image (visible layers merged together) These options provide a convenient way to update the contents of an existing layer from an outside source, without the hassle of jumping through various Copy+Paste operations.
1 parent 973852b commit 24f5082

File tree

6 files changed

+318
-173
lines changed

6 files changed

+318
-173
lines changed

Classes/pdClipboardMain.cls

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -411,7 +411,7 @@ End Sub
411411

412412
'Paste an image (e.g. create new image data based on whatever is in the clipboard).
413413
' The parameter "srcIsMeantAsLayer" controls whether the clipboard data is loaded as a new image, or as a new layer in an existing image.
414-
Friend Sub ClipboardPaste(ByVal srcIsMeantAsLayer As Boolean, Optional ByRef pasteToThisDIBInstead As pdDIB = Nothing, Optional ByRef fullParamString As String)
414+
Friend Function ClipboardPaste(ByVal srcIsMeantAsLayer As Boolean, Optional ByRef pasteToThisDIBInstead As pdDIB = Nothing, Optional ByRef fullParamString As String = vbNullString) As Boolean
415415

416416
Dim pasteWasSuccessful As Boolean
417417
pasteWasSuccessful = False
@@ -431,58 +431,58 @@ Friend Sub ClipboardPaste(ByVal srcIsMeantAsLayer As Boolean, Optional ByRef pas
431431

432432
'If PD was used to Cut or Copy something onto the clipboard, our own private format(s) will be listed first.
433433
If m_Clipboard.DoesClipboardHaveFormatID(CF_PD_DIB) And PD_CB_ALLOW_INTERNAL_FORMAT_PASTE Then
434-
pasteWasSuccessful = ClipboardPaste_InternalData(srcIsMeantAsLayer)
434+
pasteWasSuccessful = ClipboardPaste_InternalData(srcIsMeantAsLayer, pasteToThisDIBInstead)
435435
End If
436436

437437
'PNGs on the clipboard get preferential treatment, as they preserve transparency data - so check for them first.
438438
If m_Clipboard.DoesClipboardHaveFormatName("PNG") And (Not pasteWasSuccessful) And PD_CB_ALLOW_PNG_PASTE Then
439-
pasteWasSuccessful = ClipboardPaste_CustomImageFormat("PNG", srcIsMeantAsLayer, "png")
439+
pasteWasSuccessful = ClipboardPaste_CustomImageFormat("PNG", srcIsMeantAsLayer, "png", pasteToThisDIBInstead)
440440
End If
441441

442442
'If we couldn't find PNG data (or something went horribly wrong during that step), look for an HTML fragment next.
443443
' Images copied from web browsers typically create an HTML fragment, which should have a direct link to the copied image.
444444
' Downloading the image manually lets us maintain things like ICC profiles and the image's original filename.
445445
If m_Clipboard.DoesClipboardHaveHTML() And (Not pasteWasSuccessful) And PD_CB_ALLOW_ONLINE_PASTE Then
446-
pasteWasSuccessful = ClipboardPaste_HTML(srcIsMeantAsLayer)
446+
pasteWasSuccessful = ClipboardPaste_HTML(srcIsMeantAsLayer, pasteToThisDIBInstead)
447447
End If
448448

449449
'JPEGs are another possibility. We prefer them less than PNG or direct download (because there's no guarantee that the
450450
' damn browser didn't re-encode them, but they're better than bitmaps or DIBs because they may retain metadata and
451451
' color profiles, so test for JPEG next. (Also, note that certain versions of Microsoft Office use "JFIF" as the identifier,
452452
' for reasons known only to them...)
453453
If m_Clipboard.DoesClipboardHaveFormatName("JPEG") And (Not pasteWasSuccessful) And PD_CB_ALLOW_JPEG_PASTE Then
454-
pasteWasSuccessful = ClipboardPaste_CustomImageFormat("JPEG", srcIsMeantAsLayer, "jpg")
454+
pasteWasSuccessful = ClipboardPaste_CustomImageFormat("JPEG", srcIsMeantAsLayer, "jpg", pasteToThisDIBInstead)
455455
End If
456456

457457
If m_Clipboard.DoesClipboardHaveFormatName("JPG") And (Not pasteWasSuccessful) And PD_CB_ALLOW_JPEG_PASTE Then
458-
pasteWasSuccessful = ClipboardPaste_CustomImageFormat("JPG", srcIsMeantAsLayer, "jpg")
458+
pasteWasSuccessful = ClipboardPaste_CustomImageFormat("JPG", srcIsMeantAsLayer, "jpg", pasteToThisDIBInstead)
459459
End If
460460

461461
If m_Clipboard.DoesClipboardHaveFormatName("JFIF") And (Not pasteWasSuccessful) And PD_CB_ALLOW_JPEG_PASTE Then
462-
pasteWasSuccessful = ClipboardPaste_CustomImageFormat("JFIF", srcIsMeantAsLayer, "jpg")
462+
pasteWasSuccessful = ClipboardPaste_CustomImageFormat("JFIF", srcIsMeantAsLayer, "jpg", pasteToThisDIBInstead)
463463
End If
464464

465465
'Next, see if the clipboard contains a generic file list. If it does, try to load each file in turn.
466466
If m_Clipboard.DoesClipboardHaveFiles() And (Not pasteWasSuccessful) And PD_CB_ALLOW_FILE_PASTE Then
467-
pasteWasSuccessful = ClipboardPaste_ListOfFiles(srcIsMeantAsLayer)
467+
pasteWasSuccessful = ClipboardPaste_ListOfFiles(srcIsMeantAsLayer, pasteToThisDIBInstead)
468468
End If
469469

470470
'Next, look for plaintext. This could be a URL, or maybe a text representation of a filepath.
471471
' (Also, note that we only have to search for one text format, because the OS auto-converts between text formats for free.)
472472
If m_Clipboard.DoesClipboardHaveText() And (Not pasteWasSuccessful) And PD_CB_ALLOW_GENERIC_TEXT_PASTE Then
473-
pasteWasSuccessful = ClipboardPaste_TextSource(srcIsMeantAsLayer)
473+
pasteWasSuccessful = ClipboardPaste_TextSource(srcIsMeantAsLayer, pasteToThisDIBInstead)
474474
End If
475475

476476
'Next, use any DIBs or bitmaps. Once again, the OS auto-converts between bitmap and DIB formats, and if it all possible,
477477
' we prefer DIBv5 as it actually supports alpha data.
478478
If m_Clipboard.DoesClipboardHaveBitmapImage() And (Not pasteWasSuccessful) And PD_CB_ALLOW_BMP_DIB_PASTE Then
479-
pasteWasSuccessful = ClipboardPaste_BitmapImage(srcIsMeantAsLayer)
479+
pasteWasSuccessful = ClipboardPaste_BitmapImage(srcIsMeantAsLayer, pasteToThisDIBInstead)
480480
End If
481481

482482
'As a last resort, try to grab metafiles. These are not ideal as some software (*cough* OFFICE *cough*) generates
483483
' pretty terrible metafiles, but it's better than nothing.
484484
If m_Clipboard.DoesClipboardHaveMetafile() And (Not pasteWasSuccessful) And PD_CB_ALLOW_METAFILE_PASTE Then
485-
pasteWasSuccessful = ClipboardPaste_Metafile(srcIsMeantAsLayer)
485+
pasteWasSuccessful = ClipboardPaste_Metafile(srcIsMeantAsLayer, pasteToThisDIBInstead)
486486
End If
487487

488488
'Regardless of success or failure, make sure to close the clipboard now that we're done with it.
@@ -494,7 +494,9 @@ Friend Sub ClipboardPaste(ByVal srcIsMeantAsLayer As Boolean, Optional ByRef pas
494494
Else
495495
PDDebug.LogAction "WARNING! Couldn't open the clipboard; is it possible another program has locked it?"
496496
End If
497-
497+
498+
ClipboardPaste = pasteWasSuccessful
499+
498500
'If a paste operation was successful, switch the current tool to the layer move/resize tool, which is most likely needed after a
499501
' new layer has been pasted.
500502
If pasteWasSuccessful Then
@@ -575,7 +577,7 @@ Friend Sub ClipboardPaste(ByVal srcIsMeantAsLayer As Boolean, Optional ByRef pas
575577
PDMsgBox "The clipboard is empty or it does not contain a valid picture format. Please copy a valid image onto the clipboard and try again.", vbExclamation Or vbOKOnly, "Error"
576578
End If
577579

578-
End Sub
580+
End Function
579581

580582
'If the clipboard contains internal PD-format data (most commonly a bare DIB), you can call this function to initiate a "paste" command
581583
' using the internal data as a source. The parameter "srcIsMeantAsLayer" controls whether the clipboard data is loaded as a new image,
@@ -1634,7 +1636,7 @@ Private Function DragDrop_TextData(ByRef OLEDragDrop_DataObject As DataObject, O
16341636
If (LenB(targetFile) <> 0) Then
16351637

16361638
If PDImages.IsImageActive() And loadAsLayers Then
1637-
Layers.LoadImageAsNewLayer False, targetFile, , True, , srcX, srcY
1639+
Layers.LoadImageAsNewLayer False, targetFile, vbNullString, True, True, srcX, srcY
16381640
Else
16391641
LoadFileAsNewImage targetFile
16401642
End If

Forms/MainWindow.frm

Lines changed: 42 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -482,20 +482,36 @@ Begin VB.Form FormMain
482482
End
483483
End
484484
Begin VB.Menu MnuLayer
485-
Caption = "-"
485+
Caption = "Replace"
486486
Index = 2
487+
Begin VB.Menu MnuLayerReplace
488+
Caption = "From clipboard"
489+
Index = 0
490+
End
491+
Begin VB.Menu MnuLayerReplace
492+
Caption = "From file..."
493+
Index = 1
494+
End
495+
Begin VB.Menu MnuLayerReplace
496+
Caption = "From visible layers"
497+
Index = 2
498+
End
487499
End
488500
Begin VB.Menu MnuLayer
489-
Caption = "Merge up"
501+
Caption = "-"
490502
Index = 3
491503
End
492504
Begin VB.Menu MnuLayer
493-
Caption = "Merge down"
505+
Caption = "Merge up"
494506
Index = 4
495507
End
496508
Begin VB.Menu MnuLayer
497-
Caption = "Order"
509+
Caption = "Merge down"
498510
Index = 5
511+
End
512+
Begin VB.Menu MnuLayer
513+
Caption = "Order"
514+
Index = 6
499515
Begin VB.Menu MnuLayerOrder
500516
Caption = "Go to top layer"
501517
Index = 0
@@ -543,7 +559,7 @@ Begin VB.Form FormMain
543559
End
544560
Begin VB.Menu MnuLayer
545561
Caption = "Visibility"
546-
Index = 6
562+
Index = 7
547563
Begin VB.Menu MnuLayerVisibility
548564
Caption = "Show this layer"
549565
Checked = -1 'True
@@ -576,11 +592,11 @@ Begin VB.Form FormMain
576592
End
577593
Begin VB.Menu MnuLayer
578594
Caption = "-"
579-
Index = 7
595+
Index = 8
580596
End
581597
Begin VB.Menu MnuLayer
582598
Caption = "Crop"
583-
Index = 8
599+
Index = 9
584600
Begin VB.Menu MnuLayerCrop
585601
Caption = "Crop to selection"
586602
Index = 0
@@ -600,7 +616,7 @@ Begin VB.Form FormMain
600616
End
601617
Begin VB.Menu MnuLayer
602618
Caption = "Orientation"
603-
Index = 9
619+
Index = 10
604620
Begin VB.Menu MnuLayerOrientation
605621
Caption = "Straighten..."
606622
Index = 0
@@ -640,7 +656,7 @@ Begin VB.Form FormMain
640656
End
641657
Begin VB.Menu MnuLayer
642658
Caption = "Size"
643-
Index = 10
659+
Index = 11
644660
Begin VB.Menu MnuLayerSize
645661
Caption = "Reset to actual size"
646662
Index = 0
@@ -668,11 +684,11 @@ Begin VB.Form FormMain
668684
End
669685
Begin VB.Menu MnuLayer
670686
Caption = "-"
671-
Index = 11
687+
Index = 12
672688
End
673689
Begin VB.Menu MnuLayer
674690
Caption = "Transparency"
675-
Index = 12
691+
Index = 13
676692
Begin VB.Menu MnuLayerTransparency
677693
Caption = "From color (chroma key)..."
678694
Index = 0
@@ -696,11 +712,11 @@ Begin VB.Form FormMain
696712
End
697713
Begin VB.Menu MnuLayer
698714
Caption = "-"
699-
Index = 13
715+
Index = 14
700716
End
701717
Begin VB.Menu MnuLayer
702718
Caption = "Rasterize"
703-
Index = 14
719+
Index = 15
704720
Begin VB.Menu MnuLayerRasterize
705721
Caption = "Current layer"
706722
Index = 0
@@ -712,7 +728,7 @@ Begin VB.Form FormMain
712728
End
713729
Begin VB.Menu MnuLayer
714730
Caption = "Split"
715-
Index = 15
731+
Index = 16
716732
Begin VB.Menu MnuLayerSplit
717733
Caption = "Current layer into standalone image"
718734
Index = 0
@@ -2012,6 +2028,17 @@ Private Sub MnuLayerCrop_Click(Index As Integer)
20122028
End Select
20132029
End Sub
20142030

2031+
Private Sub MnuLayerReplace_Click(Index As Integer)
2032+
Select Case Index
2033+
Case 0
2034+
Menus.ProcessDefaultAction_ByName "layer_replacefromclipboard"
2035+
Case 1
2036+
Menus.ProcessDefaultAction_ByName "layer_replacefromfile"
2037+
Case 2
2038+
Menus.ProcessDefaultAction_ByName "layer_replacefromvisiblelayers"
2039+
End Select
2040+
End Sub
2041+
20152042
Private Sub MnuLayerSplit_Click(Index As Integer)
20162043
Select Case Index
20172044
Case 0
@@ -2915,7 +2942,7 @@ Private Sub Form_Load()
29152942
On Error GoTo FormMainLoadError
29162943

29172944
'*************************************************************************************************************************************
2918-
' Start by rerouting control to "LoadTheProgram", which initializes all key PD systems
2945+
' Start by rerouting control to "ContinueLoadingProgram", which initializes all key PD systems
29192946
'*************************************************************************************************************************************
29202947

29212948
'The bulk of the loading code actually takes place inside the main module's ContinueLoadingProgram() function

0 commit comments

Comments
 (0)