Page 16 of 16

Re: EditorFactory - Module for object management in a Canvas

Posted: Sun Nov 16, 2025 8:25 pm
by Caronte3D
ShadowStorm wrote: Sun Nov 16, 2025 8:04 pm But since no one seems interested, which I don't understand...
Maybe this license point is one of the causes:
NonCommercialYou may not use the material for commercial purposes.

Re: EditorFactory - Module for object management in a Canvas

Posted: Sun Nov 16, 2025 9:32 pm
by ShadowStorm
Caronte3D wrote: Sun Nov 16, 2025 8:25 pm
ShadowStorm wrote: Sun Nov 16, 2025 8:04 pm But since no one seems interested, which I don't understand...
Maybe this license point is one of the causes:
NonCommercialYou may not use the material for commercial purposes.
Caronte3D,

Yes, we've already talked about this. I have a big problem with it, a mental block. It's a real problem, but even if that were the case, I'm not sure it would be enough. I have to give away all this work for free and, on top of that, I have to make it freely available, including for commercial use. I can't do it!

Stargate is okay with it, and he's the one who wrote all the code at my request. His generosity is beyond me, as is that of the others who do this.

It's stronger than me, that's just how it is.

Re: EditorFactory - Module for object management in a Canvas

Posted: Sun Nov 16, 2025 9:52 pm
by Caronte3D
I'm not saying it should be free, but the license should allow commercial use, advertising a reasonable final price, so anyone can decide if it's a good idea to use this code if their project is commercialized.
That's just my opinion.

Re: EditorFactory - Module for object management in a Canvas

Posted: Mon Nov 17, 2025 12:57 am
by ShadowStorm
Here is the famous code translated into English, for what it's worth.

Cut, copy, and paste objects in an editor.

There is no specific function for this, but I have created an example that allows you to do it, with a little trick!
If this could be done natively, it would be a big plus, as would the “undo” and “restore” functions, which do not exist but which I have also created.

Code: Select all

; Example Cut, Copy, Paste Objects in the editor.

; Select your Objects with mouse selection or by left-clicking on an Object
; then, click the right mouse button on a selected object to bring up the context menu.

; Context menu items will only activate if the object under the mouse is selected
; or if you right-click on the editor outside of Objects
; and provided that data exists (Cut / Copy).

; Includes the program file.
XIncludeFile "Editors Factory.pbi"

; Initializes the module so you can use it.
UseModule EditorFactory

; ---------------------------------------------- Example: ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

UsePNGImageDecoder()

; Program constants.
Enumeration 1
  
  #Window  ; The Window.
  #Canevas ; The Canvas
  
  #CutIcon ; Icon number.
  #CopyIcon ; Icon number.
  #PasteIcon ; Icon number.
  
  #ContextualMenu ; The context menu of the canvas.
  #ContextualMenuCut ; Element Cut from the context menu of the canvas.
  #ContextualMenuCopy ; Element Copy from the context menu of the canvas.
  #ContextualMenuPaste ; Element Paste from the context menu of the canvas.
  
EndEnumeration

; The numbering of Objects starts from 1 up to 65535.
Enumeration 1
  #ObjectInvisible ; Used to display the context menu on the canvas if on no other object.
  #Object1         ; Item #1.
  #Object2         ; Item #2.
  #Object3         ; Item #3.
  #Object4         ; Item #4.
  #Object5         ; Item #5.
  #Object6         ; Item #6.
  #Object7         ; Item #7.
  #Object8         ; Item #8.
  #Object9         ; Item #9.
EndEnumeration

;{ Data for context menu images.
DataSection
  
IconCut_start:
; size: 3307 bytes
  Data.q $0A1A0A0D474E5089,$524448490D000000,$1000000010000000,$FFF31F0000000608,$5948700900000061,$0B0000130B000073,$0000189C9A000113,$6850504343694F0A,$20706F68736F746F,$666F727020434349
  Data.q $9DDA780000656C69,$F73D16E953546753,$4B9480884B42F4DE,$8B4252200815526F,$1009212A26911480,$C15115D9A121884A,$88A0C81B04454511,$2C51158C808E8E03,$A221E407D80A8A0C,$E1FBCA8A88A3838E
  Data.q $CDE6F7BCD66BA37B,$9DF3ACE73ED7B5FE,$48960C08C007CFB3,$1E42A90C80355133,$E4E1C6C4C783E011,$100070240A81402E,$0123FD732164B308,$C0222B3C3C7EF800,$080BD3780100BE07,$871C30C09B4DC000
  Data.q $80015C9942EA0FFF,$084B389174C00184,$A6428E7A40001480,$26989D8001464000,$63CB600004A00053,$2760002D5000E362,$99F89D8000D3E67F,$011521945B00017B,$44886513200091A0,$8A56CFAC003B6800
  Data.q $4B66140030580045,$4930002DD80039C4,$C000B7B000486657,$000C0800B20B10CE,$7B04002985885130,$8400782323C86000,$F13C57F246140099,$7800002AE710AE2B,$81453924B93CB299,$2E575707712D085B
  Data.q $36142B1749CE281E,$79C22E409A610261,$F3E00F3481321999,$E0111591A00000CC,$CEAE0ECE78FDF383,$EA2D5F0EB68E36CE,$FEE3626222FF06BF,$E100004070ABCFE5,$1AB32F2CFED17E74,$25A2FE6D80063B80
  Data.q $F775A00B5E6804EE,$A000B5400FB2668B,$3C7EF870F357DAE9,$E5D9D9B990A1453C,$615B42C44AD8E4E4,$C05FC267FE7D57CA,$F7FC3C7EF96CFD57,$5D328124E2BEE0F5,$F4CCC2E0F8044781,$62840992CF1CA54C
  Data.q $FF0BB7FC478FE6DC,$B96249C422D31DFC,$8E711251E3142A58,$8922A532F38C9A44,$64FFD225C5299242,$35DF3E03FB2CDFE2,$2D917B013E6AB000,$10274BF603635DA8,$F20000F7E2C07458,$80030828D4C16FBB
  Data.q $3FEFFF77CFE18368,$4966800025A047FD,$2E24445E00007192,$000008C73FB3CA54,$F41B41B02A81A044,$05C11C06C02C18C1,$42843660FC0BC1DC,$640A421042C2C424,$4282AC2960721C80,$2F602A1DB0CD8628
  Data.q $866851C0341D40D4,$0EB855C22E0E7093,$C19E0861FA0F703D,$08C841040981BC28,$8A620188DA216113,$F8859917088E2358,$20248B120448C121,$35914B22511488C9,$485520548A523148,$5C873902723DF21D
  Data.q $823200C83B91BA46,$B281943147BC86FC,$A8B943B50CD43D51,$64D00BA246841A37,$D09BA0168F9A3174,$E7A1368C3D1AB472,$433E8FDA0F68ABD0,$C4330718E8C030C7,$38B142C3C62E306C,$AC22B1CB6393092C
  Data.q $03AC56B01AC6AB0C,$0477B1CF63F589BB,$77043609C0458112,$4C5848411E612042,$241C20A848D84E58,$8403093709DA1134,$B44BA8932227C251,$326218C4F911BA26,$12D6232C48588731,$C443887B102F138F
  Data.q $B927324389122437,$12D254A4B1490290,$2CE923526ED246D2,$C993231A48349BA9,$2C943907B26B64DA,$C3E49DE485C82B20,$5BF221E41BE433E4,$53F8A47140629D0A,$E5194A6ACA5228E2,$32986506E534E510
  Data.q $A1A8DD529AA35541,$A1AD425A8F351154,$3413A88751AF52B6,$4B491683CD399A75,$17681AD395A2ADA5,$11BA74E8AF69F768,$D257D0974E1E95DD,$F403E897E847E9CB,$88C78315860D0C77,$671807189B192867
  Data.q $19A64C98AF187719,$31373054C7198BD3,$556F990F99E798EB,$CA91157C2AB62A58,$2A1B9526954A950A,$AADEAAA6AAA9542F,$A98F54CB55F3550B,$53335546AE7D535E,$AA55AB96D409A9E3,$A967531B53EB509D
  Data.q $546FA867AA87A83B,$590689FD597EA43F,$A051A4434FC34CC3,$630B20C6BCE35FB1,$AB0D6B212C78B319,$CDB126C435817586,$1DFD98BB2A767CD9,$4339A1A9AA3D8BBB,$94F352B357334A33,$9CF87198E3073F66
  Data.q $F397A728E7094E74,$29E229EF14DE8A7E,$5C6531B94C34A61B,$48AB58969796AA6B,$AE36BDEB47AB51AB,$59BB45BDA69DA7ED,$5C274AC7410E81FB,$E79D05CE8F674727,$16A70AA7DD53D953,$6BAA2EAEF53A3D4D
  Data.q $6EBF7744BBA11BA5,$9E805EBE9E98EEA7,$FAE7BD79DEA76F4C,$FA6DFD54FD2F7D1C,$0CB306580C47F5A7,$C53C18CE0CDB0624,$DBC72F1D3C6F7135,$A54340C35D4351F1,$B99184E197619561,$0F468D46D5A33CD1
  Data.q $6DE324E35CC6698C,$21260626A3C66DC6,$529AEE4DEA4D4B26,$3B4C3BA629A6B94D,$D6CDA2CDCCCDC74C,$E732D7313D9B3599,$60B7DF9BD79BE79B,$B8B6A8B62C5A785A,$EE59A65AE4B24965,$A559395A856EBCB6
  Data.q $9DAD46B35D5A5558,$11A7BBADBBD625AD,$D69EAB4E934EB9A7,$A9B6C9B6F1B0C367,$AEDB06D8E5B019B7,$176267617DB66DB6,$BD93EEC3AEC5B767,$073DFD8D7DBA7D93,$1D5A1DAB0ED9870D,$3A563A1472B4737E
  Data.q $C57D3FEE9CCE9ADE,$10CF58672FE996F4,$29CB13B6E333D8CF,$6747D39B539D69C4,$8B88F38373B96717,$2E3E972ECB824B89,$4AE4BDC8DDC61B9B,$F5D27AE15D71F574,$DBA8EDC29BB39B9D,$DC87EE69EE36EEAF
  Data.q $33599E299F34CC9F,$E551E043C8C3D073,$DF6B30959F0B3FD1,$B567814F434F7EAC,$AD57912F632F23E7,$61F7AA77A5B7B0D7,$E39F723EF63E17EF,$59DE32DE373CE33E,$CBB7C8B7C037CC5F,$43DF855F9E6FC34F
  Data.q $D1FF7AFF64FF237F,$890367012580A700,$7AF8FB025B814181,$65DB3A3F8EBF217C,$B9A08C41EDD9B2F6,$E582AD828F411541,$AD90ECC86821ADC1,$69CE91CE98E7F721,$07D0D6E87E50850E,$270C7EC38B61E661
  Data.q $708E3F8657858785,$77359731D11A5888,$44FA44DF7343DCD1,$394F31679BDE4496,$2EAA3E2A354A2DAF,$3FBA34BA37DA3C6A,$9D58D5CC59662EC6,$2A2E391C4B6C4958,$EDFCDFBE6C6E36AE,$7BE30BE29DE287F3
  Data.q $A179705DC82F9817,$2EA916A785F4C2CE,$4E884C40963A2C12,$16A82A1041F09438,$0A8E257713F2258C,$D12F2267C21DC279,$1E2A5C43D888D136,$EC927A4D2A48F24E,$A533C5247935BC91,$BC90A92784B9E52C
  Data.q $169E3A9BDD4C0D4C,$BD3A3D326D20769A,$AA42719091928331,$E667EA67B6934D21,$FEB28565ACCB7666,$07951E2FB78B6EC5,$2D5905AC90B36BC9,$285A54E8A642B60A,$66576567B2072AD7,$9EAB9639CA89CDBF
  Data.q $90DBCAB3CCEDCD2B,$C212EDFF9FEF9C37,$574B86A5B692E112,$396AACBDE6581D2D,$15E30ADB79713CB2,$B83CAC0656862B05,$EDAB4FD56D2AB68A,$4D7A26BD7EAE9757,$B5C182CAC15E816B,$85E50A550BEB6B01
  Data.q $584F5DEDD7DCEB7D,$9D86FA61B5DF592F,$DB14AE8A89153E1B,$78DC28D87F159717,$DC99BFCA6F871BE5,$CF64B9C4ABA9B494,$9E2DDEE6E966D266,$0E97E697AA960E5B,$56DF0DB4DAD90D6E,$972FDB45F6F5EDB4
  Data.q $B943B683BBDB28CD,$C9A765BCB83CBFA3,$F454A4543F3BCDCE,$B5DDD2EE3654FA54,$7B1BEED16EF8D761,$BC5BDBD5EC34F6BC,$0155DBBEC93EFDF7,$49FB65D566D54D55,$E9AA89AE3FF7B3FB,$6D4EAD5D6DFB96F8
  Data.q $07FD03D203C7ED71,$1DD5D4B9D7B60E23,$EB2BD68F52543DD2,$EF9DFEBE1FC70E47,$9C8D550D360D2D77,$E9E479447023E2C6,$DA3A0D1EF7DF09F7,$1FD307E1AC7B8C76,$9A426A2F1D671D76,$5BFB9A539B469AF2
  Data.q $D6D13ECC4FBA5B62,$0F1FDB47FC7ADEEA,$54F34A79593C349C,$6793D382E9DA69C9,$7E7D9D959D8CCFF2,$7BB6A2DB60DCF92E,$EF6F0F6ADFCE63E7,$8BFF45D2E17410BA,$B8F25CCE3BBC3BE7,$B85713E5DBB2F274
  Data.q $74EA6D5F3AAF9A57,$BBC74FD393FE3CEA,$B96B5CB9AE9ABB9C,$E9F7667BB5BD7AEE,$79BDF4DDCE379E1B,$3D399ED5D6FF16F1,$F7C5F76F7AF3BDDD,$FD27727EDD16DFF5,$ADEE2777D9BBCBCE,$41ED40F45FBC4FBC
  Data.q $FE5B3FD587DD43D9,$77C06A7FDCEFD8DC,$8506F747DCD1F3A0,$430F8FF591FECF83,$860D86CB8F998F05,$3FE239393E389EEB,$64CF43A7FCE9FD72,$CBFEA2FE179E26CF,$EBD5F87E2F1617AE,$F297A1D198D1CED7
  Data.q $EAFDA57C6DBF9397,$C6C2C6DBAF19EBC0,$F45E313378C9BE1E,$1D77DC77C1EDFB56,$207CE44F0FDFA3EF,$53F5B1F968FF287F,$FF93931993FBA7D0,$2D3363FCF3980304,$4D416704000000DB,$51FB7C8EB1000041
  Data.q $5248632000000093,$800000257A00004D,$800000FFF9000083,$EA000030750000E9,$170000983A000060,$02000046C55F926F,$94DA785441444906,$9FC6186113683F92,$25E926B972F4BEFB,$75360E34FF51C7B1
  Data.q $45C1304122839ED0,$105938DA2DE3B6A7,$C5D8B72A1E08B8BA,$2420E25C5938C9D2,$145C408706222A4E,$6D436D691245C569,$BA7F71CB9369DDED,$FBDF4EF3489B4158,$7A05E1E7DE1EFC7E,$BB8B55550555552C
  Data.q $79800DE00C2BD33D,$E605C7A413002500,$369EB50074000800,$6DB891224EF55550,$A720008E38EE8618,$49213C27DD02DA69,$65ACB2C175D703D2,$080013DA69A29659,$FBE47841059603EC,$6AC9C71DD4D34C3E
  Data.q $49008FFFF761F69A,$D42957BACFDF992B,$694A191BF5F2E001,$07556AD5094A9531,$322B490C000C17F0,$B0864922E522F8E1,$8DEFC3E287AA01A0,$FA7726452098EF2F,$07BDB6DBAB30C420,$10CE785D8ECA0006
  Data.q $3E65B725C6C63922,$8E8745C5373F1F8B,$2F2B5F5B7266ED7A,$7F3A7F3E9192B7AD,$A386848B2745F67F,$32852AF798FC63B2,$EAAF4BEF82107180,$06511183653ED73F,$96E85B9C3E9FD62F,$CC8F0DCEB69C6111
  Data.q $A9A1F8D8D56F2684,$53D5ADED4BAF8FCD,$BFDA145E4F07C600,$C8E15D4C85FFF5D6,$D9F5BDBB84D8C74B,$99678FB7DD37996D,$03F26752C6CE27C3,$A2E2C97807E00783,$F1D024EE58BCBF8C,$212C70B5ABD90290
  Data.q $B0CD0BE91C958D98,$0B476CBDD2CD1131,$928717EE4569067B,$86250A55E7256366,$878E85ABB3767812,$72B493CE001E7844,$64EAC6F632078685,$0D8BCBF81DFE0CD7,$C16BB1D1D192C748,$AF5DEBEDF9B47E7E
  Data.q $880019D81377C852,$006FBD8D59B5BD9D,$AE444E4549000000
  Data.b $42,$60,$82
IconCut_end:
  
CopyIcon_start:
; size: 3117 bytes
Data.q $0A1A0A0D474E5089,$524448490D000000,$1000000010000000,$FFF31F0000000608,$5948700900000061,$0B0000130B000073,$0000189C9A000113,$6850504343694F0A,$20706F68736F746F,$666F727020434349
  Data.q $9DDA780000656C69,$F73D16E953546753,$4B9480884B42F4DE,$8B4252200815526F,$1009212A26911480,$C15115D9A121884A,$88A0C81B04454511,$2C51158C808E8E03,$A221E407D80A8A0C,$E1FBCA8A88A3838E
  Data.q $CDE6F7BCD66BA37B,$9DF3ACE73ED7B5FE,$48960C08C007CFB3,$1E42A90C80355133,$E4E1C6C4C783E011,$100070240A81402E,$0123FD732164B308,$C0222B3C3C7EF800,$080BD3780100BE07,$871C30C09B4DC000
  Data.q $80015C9942EA0FFF,$084B389174C00184,$A6428E7A40001480,$26989D8001464000,$63CB600004A00053,$2760002D5000E362,$99F89D8000D3E67F,$011521945B00017B,$44886513200091A0,$8A56CFAC003B6800
  Data.q $4B66140030580045,$4930002DD80039C4,$C000B7B000486657,$000C0800B20B10CE,$7B04002985885130,$8400782323C86000,$F13C57F246140099,$7800002AE710AE2B,$81453924B93CB299,$2E575707712D085B
  Data.q $36142B1749CE281E,$79C22E409A610261,$F3E00F3481321999,$E0111591A00000CC,$CEAE0ECE78FDF383,$EA2D5F0EB68E36CE,$FEE3626222FF06BF,$E100004070ABCFE5,$1AB32F2CFED17E74,$25A2FE6D80063B80
  Data.q $F775A00B5E6804EE,$A000B5400FB2668B,$3C7EF870F357DAE9,$E5D9D9B990A1453C,$615B42C44AD8E4E4,$C05FC267FE7D57CA,$F7FC3C7EF96CFD57,$5D328124E2BEE0F5,$F4CCC2E0F8044781,$62840992CF1CA54C
  Data.q $FF0BB7FC478FE6DC,$B96249C422D31DFC,$8E711251E3142A58,$8922A532F38C9A44,$64FFD225C5299242,$35DF3E03FB2CDFE2,$2D917B013E6AB000,$10274BF603635DA8,$F20000F7E2C07458,$80030828D4C16FBB
  Data.q $3FEFFF77CFE18368,$4966800025A047FD,$2E24445E00007192,$000008C73FB3CA54,$F41B41B02A81A044,$05C11C06C02C18C1,$42843660FC0BC1DC,$640A421042C2C424,$4282AC2960721C80,$2F602A1DB0CD8628
  Data.q $866851C0341D40D4,$0EB855C22E0E7093,$C19E0861FA0F703D,$08C841040981BC28,$8A620188DA216113,$F8859917088E2358,$20248B120448C121,$35914B22511488C9,$485520548A523148,$5C873902723DF21D
  Data.q $823200C83B91BA46,$B281943147BC86FC,$A8B943B50CD43D51,$64D00BA246841A37,$D09BA0168F9A3174,$E7A1368C3D1AB472,$433E8FDA0F68ABD0,$C4330718E8C030C7,$38B142C3C62E306C,$AC22B1CB6393092C
  Data.q $03AC56B01AC6AB0C,$0477B1CF63F589BB,$77043609C0458112,$4C5848411E612042,$241C20A848D84E58,$8403093709DA1134,$B44BA8932227C251,$326218C4F911BA26,$12D6232C48588731,$C443887B102F138F
  Data.q $B927324389122437,$12D254A4B1490290,$2CE923526ED246D2,$C993231A48349BA9,$2C943907B26B64DA,$C3E49DE485C82B20,$5BF221E41BE433E4,$53F8A47140629D0A,$E5194A6ACA5228E2,$32986506E534E510
  Data.q $A1A8DD529AA35541,$A1AD425A8F351154,$3413A88751AF52B6,$4B491683CD399A75,$17681AD395A2ADA5,$11BA74E8AF69F768,$D257D0974E1E95DD,$F403E897E847E9CB,$88C78315860D0C77,$671807189B192867
  Data.q $19A64C98AF187719,$31373054C7198BD3,$556F990F99E798EB,$CA91157C2AB62A58,$2A1B9526954A950A,$AADEAAA6AAA9542F,$A98F54CB55F3550B,$53335546AE7D535E,$AA55AB96D409A9E3,$A967531B53EB509D
  Data.q $546FA867AA87A83B,$590689FD597EA43F,$A051A4434FC34CC3,$630B20C6BCE35FB1,$AB0D6B212C78B319,$CDB126C435817586,$1DFD98BB2A767CD9,$4339A1A9AA3D8BBB,$94F352B357334A33,$9CF87198E3073F66
  Data.q $F397A728E7094E74,$29E229EF14DE8A7E,$5C6531B94C34A61B,$48AB58969796AA6B,$AE36BDEB47AB51AB,$59BB45BDA69DA7ED,$5C274AC7410E81FB,$E79D05CE8F674727,$16A70AA7DD53D953,$6BAA2EAEF53A3D4D
  Data.q $6EBF7744BBA11BA5,$9E805EBE9E98EEA7,$FAE7BD79DEA76F4C,$FA6DFD54FD2F7D1C,$0CB306580C47F5A7,$C53C18CE0CDB0624,$DBC72F1D3C6F7135,$A54340C35D4351F1,$B99184E197619561,$0F468D46D5A33CD1
  Data.q $6DE324E35CC6698C,$21260626A3C66DC6,$529AEE4DEA4D4B26,$3B4C3BA629A6B94D,$D6CDA2CDCCCDC74C,$E732D7313D9B3599,$60B7DF9BD79BE79B,$B8B6A8B62C5A785A,$EE59A65AE4B24965,$A559395A856EBCB6
  Data.q $9DAD46B35D5A5558,$11A7BBADBBD625AD,$D69EAB4E934EB9A7,$A9B6C9B6F1B0C367,$AEDB06D8E5B019B7,$176267617DB66DB6,$BD93EEC3AEC5B767,$073DFD8D7DBA7D93,$1D5A1DAB0ED9870D,$3A563A1472B4737E
  Data.q $C57D3FEE9CCE9ADE,$10CF58672FE996F4,$29CB13B6E333D8CF,$6747D39B539D69C4,$8B88F38373B96717,$2E3E972ECB824B89,$4AE4BDC8DDC61B9B,$F5D27AE15D71F574,$DBA8EDC29BB39B9D,$DC87EE69EE36EEAF
  Data.q $33599E299F34CC9F,$E551E043C8C3D073,$DF6B30959F0B3FD1,$B567814F434F7EAC,$AD57912F632F23E7,$61F7AA77A5B7B0D7,$E39F723EF63E17EF,$59DE32DE373CE33E,$CBB7C8B7C037CC5F,$43DF855F9E6FC34F
  Data.q $D1FF7AFF64FF237F,$890367012580A700,$7AF8FB025B814181,$65DB3A3F8EBF217C,$B9A08C41EDD9B2F6,$E582AD828F411541,$AD90ECC86821ADC1,$69CE91CE98E7F721,$07D0D6E87E50850E,$270C7EC38B61E661
  Data.q $708E3F8657858785,$77359731D11A5888,$44FA44DF7343DCD1,$394F31679BDE4496,$2EAA3E2A354A2DAF,$3FBA34BA37DA3C6A,$9D58D5CC59662EC6,$2A2E391C4B6C4958,$EDFCDFBE6C6E36AE,$7BE30BE29DE287F3
  Data.q $A179705DC82F9817,$2EA916A785F4C2CE,$4E884C40963A2C12,$16A82A1041F09438,$0A8E257713F2258C,$D12F2267C21DC279,$1E2A5C43D888D136,$EC927A4D2A48F24E,$A533C5247935BC91,$BC90A92784B9E52C
  Data.q $169E3A9BDD4C0D4C,$BD3A3D326D20769A,$AA42719091928331,$E667EA67B6934D21,$FEB28565ACCB7666,$07951E2FB78B6EC5,$2D5905AC90B36BC9,$285A54E8A642B60A,$66576567B2072AD7,$9EAB9639CA89CDBF
  Data.q $90DBCAB3CCEDCD2B,$C212EDFF9FEF9C37,$574B86A5B692E112,$396AACBDE6581D2D,$15E30ADB79713CB2,$B83CAC0656862B05,$EDAB4FD56D2AB68A,$4D7A26BD7EAE9757,$B5C182CAC15E816B,$85E50A550BEB6B01
  Data.q $584F5DEDD7DCEB7D,$9D86FA61B5DF592F,$DB14AE8A89153E1B,$78DC28D87F159717,$DC99BFCA6F871BE5,$CF64B9C4ABA9B494,$9E2DDEE6E966D266,$0E97E697AA960E5B,$56DF0DB4DAD90D6E,$972FDB45F6F5EDB4
  Data.q $B943B683BBDB28CD,$C9A765BCB83CBFA3,$F454A4543F3BCDCE,$B5DDD2EE3654FA54,$7B1BEED16EF8D761,$BC5BDBD5EC34F6BC,$0155DBBEC93EFDF7,$49FB65D566D54D55,$E9AA89AE3FF7B3FB,$6D4EAD5D6DFB96F8
  Data.q $07FD03D203C7ED71,$1DD5D4B9D7B60E23,$EB2BD68F52543DD2,$EF9DFEBE1FC70E47,$9C8D550D360D2D77,$E9E479447023E2C6,$DA3A0D1EF7DF09F7,$1FD307E1AC7B8C76,$9A426A2F1D671D76,$5BFB9A539B469AF2
  Data.q $D6D13ECC4FBA5B62,$0F1FDB47FC7ADEEA,$54F34A79593C349C,$6793D382E9DA69C9,$7E7D9D959D8CCFF2,$7BB6A2DB60DCF92E,$EF6F0F6ADFCE63E7,$8BFF45D2E17410BA,$B8F25CCE3BBC3BE7,$B85713E5DBB2F274
  Data.q $74EA6D5F3AAF9A57,$BBC74FD393FE3CEA,$B96B5CB9AE9ABB9C,$E9F7667BB5BD7AEE,$79BDF4DDCE379E1B,$3D399ED5D6FF16F1,$F7C5F76F7AF3BDDD,$FD27727EDD16DFF5,$ADEE2777D9BBCBCE,$41ED40F45FBC4FBC
  Data.q $FE5B3FD587DD43D9,$77C06A7FDCEFD8DC,$8506F747DCD1F3A0,$430F8FF591FECF83,$860D86CB8F998F05,$3FE239393E389EEB,$64CF43A7FCE9FD72,$CBFEA2FE179E26CF,$EBD5F87E2F1617AE,$F297A1D198D1CED7
  Data.q $EAFDA57C6DBF9397,$C6C2C6DBAF19EBC0,$F45E313378C9BE1E,$1D77DC77C1EDFB56,$207CE44F0FDFA3EF,$53F5B1F968FF287F,$FF93931993FBA7D0,$2D3363FCF3980304,$4D416704000000DB,$51FB7C8EB1000041
  Data.q $5248632000000093,$800000257A00004D,$800000FFF9000083,$EA000030750000E9,$170000983A000060,$01000046C55F926F,$7CDA785441444948,$27441030C2AE3193,$8470B4445150D38E,$72826E13705003FC
  Data.q $29B0470B47426E13,$7671C5174A409090,$88B696093628E57E,$B09233AD59BF3F1C,$3E70E00EEBCB12D6,$124BBDF4E9D39B9F,$112C3088A49218C6,$7318D27CF9F088A1,$053D2D2249ACC633,$73CF3C11920B6DB5
  Data.q $5FC005FDEF2BAD68,$030C30008FC2A02A,$6D07CF9F58F7EFDE,$F6B595000F7BC2DB,$F4023D75D75DAD66,$B2C8920B76EDE85C,$3959205EBD79346C,$89A000F1E3C72EE7,$40A28AA1DFA5420C,$4B801556AD589659
  Data.q $A6AC20F69C1E9064,$592052943DF7D069,$76001879F9110045,$E3C7852942481DBB,$29ED598618713711,$ED9E5D08034F696C,$7DF40238C1333A43,$C9A938D99110920F,$D6B414A50739C017,$D008E443DBB99C51
  Data.q $D8F7BC2BD7AE1D75,$3C8841A99A5F366C,$FB9CBE367DFBF602,$738053483A73419D,$6628A29C4312796E,$CE2101BFE79E669F,$01FF8000D9A5D6F4,$124AF49765728600,$4E454900000000B6
  Data.b $44,$AE,$42,$60,$82
CopyIcon_end:
  
PasteIcon_start:
; size: 3293 bytes
Data.q $0A1A0A0D474E5089,$524448490D000000,$1000000010000000,$FFF31F0000000608,$5948700900000061,$0B0000130B000073,$0000189C9A000113,$6850504343694F0A,$20706F68736F746F,$666F727020434349
  Data.q $9DDA780000656C69,$F73D16E953546753,$4B9480884B42F4DE,$8B4252200815526F,$1009212A26911480,$C15115D9A121884A,$88A0C81B04454511,$2C51158C808E8E03,$A221E407D80A8A0C,$E1FBCA8A88A3838E
  Data.q $CDE6F7BCD66BA37B,$9DF3ACE73ED7B5FE,$48960C08C007CFB3,$1E42A90C80355133,$E4E1C6C4C783E011,$100070240A81402E,$0123FD732164B308,$C0222B3C3C7EF800,$080BD3780100BE07,$871C30C09B4DC000
  Data.q $80015C9942EA0FFF,$084B389174C00184,$A6428E7A40001480,$26989D8001464000,$63CB600004A00053,$2760002D5000E362,$99F89D8000D3E67F,$011521945B00017B,$44886513200091A0,$8A56CFAC003B6800
  Data.q $4B66140030580045,$4930002DD80039C4,$C000B7B000486657,$000C0800B20B10CE,$7B04002985885130,$8400782323C86000,$F13C57F246140099,$7800002AE710AE2B,$81453924B93CB299,$2E575707712D085B
  Data.q $36142B1749CE281E,$79C22E409A610261,$F3E00F3481321999,$E0111591A00000CC,$CEAE0ECE78FDF383,$EA2D5F0EB68E36CE,$FEE3626222FF06BF,$E100004070ABCFE5,$1AB32F2CFED17E74,$25A2FE6D80063B80
  Data.q $F775A00B5E6804EE,$A000B5400FB2668B,$3C7EF870F357DAE9,$E5D9D9B990A1453C,$615B42C44AD8E4E4,$C05FC267FE7D57CA,$F7FC3C7EF96CFD57,$5D328124E2BEE0F5,$F4CCC2E0F8044781,$62840992CF1CA54C
  Data.q $FF0BB7FC478FE6DC,$B96249C422D31DFC,$8E711251E3142A58,$8922A532F38C9A44,$64FFD225C5299242,$35DF3E03FB2CDFE2,$2D917B013E6AB000,$10274BF603635DA8,$F20000F7E2C07458,$80030828D4C16FBB
  Data.q $3FEFFF77CFE18368,$4966800025A047FD,$2E24445E00007192,$000008C73FB3CA54,$F41B41B02A81A044,$05C11C06C02C18C1,$42843660FC0BC1DC,$640A421042C2C424,$4282AC2960721C80,$2F602A1DB0CD8628
  Data.q $866851C0341D40D4,$0EB855C22E0E7093,$C19E0861FA0F703D,$08C841040981BC28,$8A620188DA216113,$F8859917088E2358,$20248B120448C121,$35914B22511488C9,$485520548A523148,$5C873902723DF21D
  Data.q $823200C83B91BA46,$B281943147BC86FC,$A8B943B50CD43D51,$64D00BA246841A37,$D09BA0168F9A3174,$E7A1368C3D1AB472,$433E8FDA0F68ABD0,$C4330718E8C030C7,$38B142C3C62E306C,$AC22B1CB6393092C
  Data.q $03AC56B01AC6AB0C,$0477B1CF63F589BB,$77043609C0458112,$4C5848411E612042,$241C20A848D84E58,$8403093709DA1134,$B44BA8932227C251,$326218C4F911BA26,$12D6232C48588731,$C443887B102F138F
  Data.q $B927324389122437,$12D254A4B1490290,$2CE923526ED246D2,$C993231A48349BA9,$2C943907B26B64DA,$C3E49DE485C82B20,$5BF221E41BE433E4,$53F8A47140629D0A,$E5194A6ACA5228E2,$32986506E534E510
  Data.q $A1A8DD529AA35541,$A1AD425A8F351154,$3413A88751AF52B6,$4B491683CD399A75,$17681AD395A2ADA5,$11BA74E8AF69F768,$D257D0974E1E95DD,$F403E897E847E9CB,$88C78315860D0C77,$671807189B192867
  Data.q $19A64C98AF187719,$31373054C7198BD3,$556F990F99E798EB,$CA91157C2AB62A58,$2A1B9526954A950A,$AADEAAA6AAA9542F,$A98F54CB55F3550B,$53335546AE7D535E,$AA55AB96D409A9E3,$A967531B53EB509D
  Data.q $546FA867AA87A83B,$590689FD597EA43F,$A051A4434FC34CC3,$630B20C6BCE35FB1,$AB0D6B212C78B319,$CDB126C435817586,$1DFD98BB2A767CD9,$4339A1A9AA3D8BBB,$94F352B357334A33,$9CF87198E3073F66
  Data.q $F397A728E7094E74,$29E229EF14DE8A7E,$5C6531B94C34A61B,$48AB58969796AA6B,$AE36BDEB47AB51AB,$59BB45BDA69DA7ED,$5C274AC7410E81FB,$E79D05CE8F674727,$16A70AA7DD53D953,$6BAA2EAEF53A3D4D
  Data.q $6EBF7744BBA11BA5,$9E805EBE9E98EEA7,$FAE7BD79DEA76F4C,$FA6DFD54FD2F7D1C,$0CB306580C47F5A7,$C53C18CE0CDB0624,$DBC72F1D3C6F7135,$A54340C35D4351F1,$B99184E197619561,$0F468D46D5A33CD1
  Data.q $6DE324E35CC6698C,$21260626A3C66DC6,$529AEE4DEA4D4B26,$3B4C3BA629A6B94D,$D6CDA2CDCCCDC74C,$E732D7313D9B3599,$60B7DF9BD79BE79B,$B8B6A8B62C5A785A,$EE59A65AE4B24965,$A559395A856EBCB6
  Data.q $9DAD46B35D5A5558,$11A7BBADBBD625AD,$D69EAB4E934EB9A7,$A9B6C9B6F1B0C367,$AEDB06D8E5B019B7,$176267617DB66DB6,$BD93EEC3AEC5B767,$073DFD8D7DBA7D93,$1D5A1DAB0ED9870D,$3A563A1472B4737E
  Data.q $C57D3FEE9CCE9ADE,$10CF58672FE996F4,$29CB13B6E333D8CF,$6747D39B539D69C4,$8B88F38373B96717,$2E3E972ECB824B89,$4AE4BDC8DDC61B9B,$F5D27AE15D71F574,$DBA8EDC29BB39B9D,$DC87EE69EE36EEAF
  Data.q $33599E299F34CC9F,$E551E043C8C3D073,$DF6B30959F0B3FD1,$B567814F434F7EAC,$AD57912F632F23E7,$61F7AA77A5B7B0D7,$E39F723EF63E17EF,$59DE32DE373CE33E,$CBB7C8B7C037CC5F,$43DF855F9E6FC34F
  Data.q $D1FF7AFF64FF237F,$890367012580A700,$7AF8FB025B814181,$65DB3A3F8EBF217C,$B9A08C41EDD9B2F6,$E582AD828F411541,$AD90ECC86821ADC1,$69CE91CE98E7F721,$07D0D6E87E50850E,$270C7EC38B61E661
  Data.q $708E3F8657858785,$77359731D11A5888,$44FA44DF7343DCD1,$394F31679BDE4496,$2EAA3E2A354A2DAF,$3FBA34BA37DA3C6A,$9D58D5CC59662EC6,$2A2E391C4B6C4958,$EDFCDFBE6C6E36AE,$7BE30BE29DE287F3
  Data.q $A179705DC82F9817,$2EA916A785F4C2CE,$4E884C40963A2C12,$16A82A1041F09438,$0A8E257713F2258C,$D12F2267C21DC279,$1E2A5C43D888D136,$EC927A4D2A48F24E,$A533C5247935BC91,$BC90A92784B9E52C
  Data.q $169E3A9BDD4C0D4C,$BD3A3D326D20769A,$AA42719091928331,$E667EA67B6934D21,$FEB28565ACCB7666,$07951E2FB78B6EC5,$2D5905AC90B36BC9,$285A54E8A642B60A,$66576567B2072AD7,$9EAB9639CA89CDBF
  Data.q $90DBCAB3CCEDCD2B,$C212EDFF9FEF9C37,$574B86A5B692E112,$396AACBDE6581D2D,$15E30ADB79713CB2,$B83CAC0656862B05,$EDAB4FD56D2AB68A,$4D7A26BD7EAE9757,$B5C182CAC15E816B,$85E50A550BEB6B01
  Data.q $584F5DEDD7DCEB7D,$9D86FA61B5DF592F,$DB14AE8A89153E1B,$78DC28D87F159717,$DC99BFCA6F871BE5,$CF64B9C4ABA9B494,$9E2DDEE6E966D266,$0E97E697AA960E5B,$56DF0DB4DAD90D6E,$972FDB45F6F5EDB4
  Data.q $B943B683BBDB28CD,$C9A765BCB83CBFA3,$F454A4543F3BCDCE,$B5DDD2EE3654FA54,$7B1BEED16EF8D761,$BC5BDBD5EC34F6BC,$0155DBBEC93EFDF7,$49FB65D566D54D55,$E9AA89AE3FF7B3FB,$6D4EAD5D6DFB96F8
  Data.q $07FD03D203C7ED71,$1DD5D4B9D7B60E23,$EB2BD68F52543DD2,$EF9DFEBE1FC70E47,$9C8D550D360D2D77,$E9E479447023E2C6,$DA3A0D1EF7DF09F7,$1FD307E1AC7B8C76,$9A426A2F1D671D76,$5BFB9A539B469AF2
  Data.q $D6D13ECC4FBA5B62,$0F1FDB47FC7ADEEA,$54F34A79593C349C,$6793D382E9DA69C9,$7E7D9D959D8CCFF2,$7BB6A2DB60DCF92E,$EF6F0F6ADFCE63E7,$8BFF45D2E17410BA,$B8F25CCE3BBC3BE7,$B85713E5DBB2F274
  Data.q $74EA6D5F3AAF9A57,$BBC74FD393FE3CEA,$B96B5CB9AE9ABB9C,$E9F7667BB5BD7AEE,$79BDF4DDCE379E1B,$3D399ED5D6FF16F1,$F7C5F76F7AF3BDDD,$FD27727EDD16DFF5,$ADEE2777D9BBCBCE,$41ED40F45FBC4FBC
  Data.q $FE5B3FD587DD43D9,$77C06A7FDCEFD8DC,$8506F747DCD1F3A0,$430F8FF591FECF83,$860D86CB8F998F05,$3FE239393E389EEB,$64CF43A7FCE9FD72,$CBFEA2FE179E26CF,$EBD5F87E2F1617AE,$F297A1D198D1CED7
  Data.q $EAFDA57C6DBF9397,$C6C2C6DBAF19EBC0,$F45E313378C9BE1E,$1D77DC77C1EDFB56,$207CE44F0FDFA3EF,$53F5B1F968FF287F,$FF93931993FBA7D0,$2D3363FCF3980304,$4D416704000000DB,$51FB7C8EB1000041
  Data.q $5248632000000093,$800000257A00004D,$800000FFF9000083,$EA000030750000E9,$170000983A000060,$01000046C55F926F,$6CDA7854414449F8,$3FC71441146BBF92,$301898888B743FB3,$582084120CA48207
  Data.q $963ACAC069624488,$57362163680A5FE6,$44E4140E628D8098,$8D824126D04090B8,$BCCECEEDDEC2E049,$0307C4BDBB99B167,$C677DF7CCFBDE3F3,$6300573CDF5F2AA8,$FA15D9AB8E3BDB0C,$44479711127134D5
  Data.q $633C3B14BDCAC471,$3CE193F2F2B01838,$4C4DC2FCCAF50012,$8F8793CA7BEEF114,$9FE966E6B4070C18,$D707DDC0FCDFBC15,$46699FB7C7C45130,$2A1FEC2738AA2002,$66B7730BE776C1CE,$E21FE1C1CBFD3D39
  Data.q $16AD5A1DE6D5E228,$A255500B5318C4CC,$A679A3DD84E219F3,$CDFC383818C75C6F,$AAA98F8E4E2FDEDE,$989696960FDE9D92,$B27AFDBB7698FDBA,$49FFDD9E17BC5505,$0888ABABAB29E4EF,$B0E9D3A0055517C1
  Data.q $B76B5BD7AF48B8B8,$1E7381E0A22F00DB,$88B142002D247E71,$29A692EDDBA5AD60,$C40B0C505236B222,$587986144D1C414D,$534D27BDE32F2F2F,$C2B2D82DC6B6B6B6,$8884239B13AD017B,$169550027807EC4C
  Data.q $E0888F7BC08D04E7,$492795ED41E4BFBD,$6A2F30C063739C12,$BC5C66C484275C40,$02F10AAA0AD79C3D,$9BBDE1008ED6B06A,$C581E9B6B588049E,$6E272CB286C68257,$C72CB2C291800268,$8A235479C42B6700
  Data.q $04845E3D464440A2,$179C00031F3CF28F,$5553DEF1CF3C8562,$EC05FF1B4216A5D5,$2C81666CE007DB7E,$965910804BD550CB,$001E6A57EBF7EFD1,$1FF9A0B36BAFAFAC,$6FF30D8D8D8DFE2E,$3E9BF60493041E00
  Data.q $4E45490000000082
  Data.b $44,$AE,$42,$60,$82
PasteIcon_end:
  
EndDataSection

CatchImage(#CutIcon, ?IconCut_start)
CatchImage(#CopyIcon, ?CopyIcon_start)
CatchImage(#PasteIcon, ?PasteIcon_start)

;}

; List to memorize the number of cut or copy objects.
NewList ListeObjet.i()

; ----------------------------------------------

;{ Callback procedure to draw an image on the object in the Canvas because when it is created, there is nothing (Gray).
; MyDrawing = The name of the custom procedure to draw something on the desired object, give it the name you want but it must have these arguments: Object.i, Width.i, Height.i
; The parameters: (Object.i, Width.i, Height.i) will automatically be used in the MyDrawing() procedure.
; Object.i is the object number, this variable does not appear in the procedure but is essential.
; Width.i is the width of the object.
; Height.i is the height of the object.
;} iData.i est une donnée personnalisé, un chiffre ici (Couleur), n'est pas obligatoire, même dans les paramètre de la procédure, MyDrawing(Object.i, Width.i, Height.i) fonctionne aussi.
; This procedure will automatically draw or redraw the contents of this procedure on the Object whenever necessary.
Runtime Procedure MyDrawing(Object.i, Width.i, Height.i, iData.i)
  AddPathBox(0.5, 0.5, Width-1, Height-1)
  VectorSourceColor(iData|$40000000)
  FillPath(#PB_Path_Preserve)
  VectorSourceColor(iData|$FF000000)
  StrokePath(1)
EndProcedure

; ----------------------------------------------

; Creating a window.
OpenWindow(#Window, 0, 0, 800, 450, "Example #017, Cut, Copy, Paste Objects in the editor.", #PB_Window_MinimizeGadget|#PB_Window_ScreenCentered)

; Creation of a Gadget Canvas.
CanvasGadget(#Canevas, 0, 0, WindowWidth(#Window), WindowHeight(#Window))

; Creation of the context menu of the canvas.
CreatePopupImageMenu(#ContextualMenu) 
MenuItem(#ContextualMenuCut, "Cut", ImageID(#CutIcon))
MenuItem(#ContextualMenuCopy, "Copy", ImageID(#CopyIcon))
MenuItem(#ContextualMenuPaste, "Paste", ImageID(#PasteIcon))

; Disables all items.
DisableMenuItem(#ContextualMenu, #ContextualMenuPaste, #True)
DisableMenuItem(#ContextualMenu, #ContextualMenuCut, #True)
DisableMenuItem(#ContextualMenu, #ContextualMenuCopy, #True)

;{ Initializes the Object manager for the specified Gadget Canvas in the specified window, must be done for each Gadget Canvas.
;  iCanvasGadget: PB Number of the Canvas gadget.
;  iWindow: PB Window number.
;  Result: Returns #True, if initialization was successful, otherwise, #False.
;}
; Initializes management for the Gadget Canvas.
InitializeCanvasObjects(#Canevas, #Window)

;{ Creates and adds an Object to the specified Canvas. WARNING: InitializeCanvasObjects() must be called before adding Objects to this Canvas.
;  iCanvasGadget: PB Canvas gadget number.
;  iObject: A self-defined Object Number or #PB_Any to generate a unique number. The self-defined number must be between 1 and 65535.
;  iX, iY: The position of the Object on the Canvas.
;  iWidth, iHeight: The size of the Object on the Canvas.
;	 iParentObject: A valid object number to which the object should be attached (optional). By default, the object will be placed on the canvas frame.
;  iFrameIndex: An index of the frame (starting with 0) or one of the following constants, into which the object should be attached (optional).
;                          - #Frame_NoFrame: The object will be attached to the standard non-indexed frame (frame for attachments).
;                          - #Frame_ViewedFrame: The object will be attached to the currently displayed indexed frame.
;  Result: The object number of the created object or 0 if the creation failed.
;}
; The #Objects were created on the #Canvas, but here are empty (Gray and without handles).
; The following parameters: iParentObject and iFrameIndex, have no use in this example, we will see this later in another example!

CreateObject(#Canevas, #Object1, 20, 20, 100, 75)
CreateObject(#Canevas, #Object2, 130, 20, 100, 75)
CreateObject(#Canevas, #Object3, 240, 20, 100, 75)
CreateObject(#Canevas, #Object4, 20, 105, 100, 75)
CreateObject(#Canevas, #Object5, 130, 105, 100, 75)
CreateObject(#Canevas, #Object6, 240, 105, 100, 75)
CreateObject(#Canevas, #Object7, 20, 190, 100, 75)
CreateObject(#Canevas, #Object8, 130, 190, 100, 75)
CreateObject(#Canevas, #Object9, 240, 190, 100, 75)

; Here each object will have the same drawing procedure with just one color as a parameter.
; It is entirely possible to use a drawing procedure specific to each Object!
; To do this, simply create a procedure for each Object!

;{ Defines a custom drawing procedure for the specified Object.
;  iObject: The Object number, the following constants can be used instead of the object number.
;                          - #Object_Default: Defines the default image for all new objects created.
;                          - #Object_All: Sets the image of all objects.
;                          - #Object_Selected: Sets the image of all selected objects.
;  sCallbackName: An empty string or valid execution procedure name to a procedure with the following arguments: Callback(iObject.i, iWidth.i, iHeight.i, iData.i)
;                          - iObject contains the number of the Object.
;                          - iWidth contains the current width.
;                          - iHeight contains the current height.
;                          - iData contains individual custom user data (Number) which will also be sent to the function.
;  Result: Returns #True if the callback was successfully set to the Object or #False if the Object does not exist.
;}
; Draw a filled square and a border with the MyDrawing() procedure.
SetObjectDrawingCallback(#Object1, "MyDrawing()", RGB(158, 172, 181)) ; Gray
SetObjectDrawingCallback(#Object2, "MyDrawing()", RGB(242, 186, 40))  ; YELLOW
SetObjectDrawingCallback(#Object3, "MyDrawing()", RGB(255, 121, 21))  ; Orange
SetObjectDrawingCallback(#Object4, "MyDrawing()", RGB(241, 64, 33))   ; Red
SetObjectDrawingCallback(#Object5, "MyDrawing()", RGB(130, 222, 29))  ; Green 1
SetObjectDrawingCallback(#Object6, "MyDrawing()", RGB(54, 201, 24))   ; Green 2
SetObjectDrawingCallback(#Object7, "MyDrawing()", RGB(42, 53, 255))   ; Blue
SetObjectDrawingCallback(#Object8, "MyDrawing()", RGB(160, 75, 247))  ; Purple
SetObjectDrawingCallback(#Object9, "MyDrawing()", RGB(175, 100, 67))  ; Brown

;{ Sets the style of the bounding box for the specified Object.
;  iObject: The Object number, the following constants can be used instead of the object number.
;                          - #Object_Default: Defines the default selection style for all new objects created.
;                          - #Object_All: Defines the selection style of all objects.
;                          - #Object_Selected: Defines the selection style of all selected objects.
;  eType: One of the following style types:
;                          - #SelectionStyle_Default: Uses the default style.
;                          - #SelectionStyle_None: Hides the selection frame.
;                          - #SelectionStyle_Solid: continuous line.
;                          - #SelectionStyle_Dotted: Dotted line.
;                          - #SelectionStyle_Dashed: dash line.
;  iColor: RGBA color of the frame or #SelectionStyle_Ignore to ignore this setting. Not used if eType is #SelectionStyle_Default or #SelectionStyle_None.
;  dThickness: Frame line thickness or #SelectionStyle_Ignore to ignore this setting. Not used if eType is #SelectionStyle_Default or #SelectionStyle_None.
;  dDistance: Distance from the frame line to the object border or #SelectionStyle_Ignore to ignore this setting.
;  Result: #True if the state of the selected frame has been defined or #False if the object does not exist.
;}
SetObjectSelectionStyle(#Object_All, #SelectionStyle_Dashed)

;{ Adds one or more standard or custom handles to the specified Object. Custom grips can have positional alignment and offset.
;  iObject: The Object number, the following constants can be used instead of the object number.
;                     - #Object_Default: Defines the default handles for all new objects created.
;                     - #Object_All: Defines the handles of all objects.
;                     - #Object_Selected: Sets the handles of all selected objects.
;  eType: A combination of all handle types that need to be added. *
;  iImage: An image number for the handle. By default (#PB_Default) the default handle image is used.
;  eAlignment: The alignment of the custom handle. By default it is #Alignment_Default = #Alignment_Center **
;  iX, iY: Offset position of the handle relative to the alignment and the Object.
;  Result: Returns #True, if the addition of the handle was successful, otherwise #False.
;
;                  * The following handle types can be used and combined:
;                    #Handle_Position: A handle to move the Object.
;                    #Handle_Rotation: A handle to rotate the Object. (UNUSED).
;                    #Handle_BottomLeft, #Handle_Bottom, #Handle_BottomRight, #Handle_Left, #Handle_Right, #Handle_TopLeft, #Handle_Top, #Handle_TopRight: A handle To resize the Object in this direction.
;                    #Handle_Custom1 ... #Handle_Custom8: A custom handle:
;
;                    Additionally, the following constants are predefined combinations:
;                    #Handle_Width = #Handle_Left | #Handle_Right.
;                    #Handle_Height = #Handle_Top | #Handle_Bottom.
;                    #Handle_Edge = #Handle_Width | #Handle_Height.
;                    #Handle_Corner = #Handle_BottomLeft | #Handle_BottomRight | #Handle_TopLeft | #Handle_TopRight.
;                    #Handle_Size = #Handle_Edge | #Handle_Corner.
;
;                 **The following alignment types can be used and combined:
;                    #Alignment_Top: Aligns the center of the handle to the top edge of the Object.
;                    #Alignment_Bottom: Aligns the center of the handle to the bottom edge of the Object.
;                    #Alignment_Left: Aligns the center of the handle to the left edge of the Object.
;                    #Alignment_Right: Aligns the center of the handle to the right edge of the Object.
;                    #Alignment_Center: Aligns the center of the handle to the center (x and/or y) of the Object.
;}
; Adds move and resize handles to all objects.
AddObjectHandle(#Object_All, #Handle_Size | #Handle_Position)

;{ Sets the style of the mouse cursor bounding box on the specified canvas.
;  iCanvasGadget.i The Gadget Canvas number.
;  eType: One of the following style types:
;                          - #SelectionStyle_None: Hides the selection frame.
;                          - #SelectionStyle_Solid: solid frame line.
;                          - #SelectionStyle_Dotted: Dotted frame line.
;                          - #SelectionStyle_Dashed: Dahsed frame line.
;                          - #SelectionStyle_Ignore: Ignore this setting.
;                          - #SelectionStyle_Partially: You can combine this constant (|) with the style type to allow partial selection.
;  iColor: RGBA color of the frame or #SelectionStyle_Ignore to ignore this setting.
;  dThickness: Thickness of the frame line or #SelectionStyle_Ignore to ignore this parameter.
;  iBackgroundColor.i The color inside the selection or #SelectionStyle_Ignore to ignore this setting.
;}
SetCursorSelectionStyle(#Canevas, #SelectionStyle_Dashed)

;{ Changes how the handles of the specified Canvas Objects or all Objects in the specified Canvas are displayed.
;  iObject: The Object number, the following constants can be used instead of the object number.
;                          - #Object_Default: Changes the display of handles of all new objects created.
;                          - #Object_All: Changes the display of handles of all objects.
;                          - #Object_Selected: Changes the display of the handles of all selected objects.
;  eMode: One of the following constants:
;                          - #Handle_ShowIfHovered: Show handles if the mouse is on the Object.
;                          - #Handle_ShowIfSelected: Show handles if the Object is selected.
;                          - #Handle_ShowAlways: Always show handles.
;  iCanvasGadget: Canvas gadget number, only needed if iObject is set to #PB_All.
;  Result: #True, if successful, Otherwise #False.
;}
ObjectHandleDisplayMode(#Object_All, #Handle_ShowIfSelected, #Canevas)

; Creates a directory if it does not exist otherwise does nothing.
CreateDirectory("Data - Copy") 

; You see, it’s super easy!

; The window event loop and gadgets.
Repeat
  
  Select WaitWindowEvent()
      
    Case #PB_Event_Gadget ; A Gadget type event.
      
      Select EventGadget()
          
        Case #Canevas
          
          Select EventType()
              
            Case #PB_EventType_RightButtonDown
              
              ;{ Returns the object that the mouse cursor is hovering over.
;  Result: The object number or 0 if no object is hovered over by the mouse cursor.
              ;}
              ObjetSousSouris.i = GetMouseHoveredObject()
              
              ; If the mouse is on an Object
              If ObjetSousSouris.i > 0
                
                ; If the object under the mouse is not selected.
                If Not ObjectState(ObjetSousSouris.i) & #State_Selected
                  
                  ;{ Deselects the specified Object or all Objects on the specified Canvas.
;  iObject: The Object number, the following constants can be used instead of the object number.
;                          - #Object_All: Deselects all objects.
;                          - #Object_Selected: Deselects all selected objects.
;  iCanvasGadget: Canvas number to restrict Deselection only to this canvas, or #PB_Ignore to authorize Deselection of all objects regardless of where it is located.
                  ;}
                  ; Deselects all selected Objects.
                  UnselectObject(#Object_Selected, #Canevas)
                  
                  ; Select the Object under the mouse
                  SelectObject(ObjetSousSouris.i, #Canevas)
                  
                EndIf
                
                ; Enables cut and copy elements because the mouse is over an Object.
                DisableMenuItem(#ContextualMenu, #ContextualMenuCut, #False)
                DisableMenuItem(#ContextualMenu, #ContextualMenuCopy, #False)
                
                ; Displays the context menu.
                DisplayPopupMenu(#ContextualMenu, WindowID(#Window))
                
              Else
                
                ;{ Deselects the specified Object or all Objects on the specified Canvas.
;  iObject: The Object number, the following constants can be used instead of the object number.
;                          - #Object_All: Deselects all objects.
;                          - #Object_Selected: Deselects all selected objects.
;  iCanvasGadget: Canvas number to restrict Deselection only to this canvas, or #PB_Ignore to authorize Deselection of all objects regardless of where it is located.
                ;}
                ; Deselects all selected Objects.
                UnselectObject(#Object_Selected, #Canevas)
                
                ; Disables cut and copy elements because the mouse is not over an Object.
                DisableMenuItem(#ContextualMenu, #ContextualMenuCut, #True)
                DisableMenuItem(#ContextualMenu, #ContextualMenuCopy, #True)
                
                ; Displays the context menu.
                DisplayPopupMenu(#ContextualMenu, WindowID(#Window))
                
              EndIf
              
          EndSelect
          
      EndSelect
      
    Case #PB_Event_Menu
      
      Select EventMenu()
          
        Case #ContextualMenuCut
          
          ; Creates a directory if it does not exist otherwise does nothing.
          CreateDirectory("Data - Copy") 
          
          ;{ Save one or more specific Objects in a Json file.
;  iObject: Object Number or one of the following constants:
          ;                         - #Object_All: Sauvegarde tous les Objets, voir le paramètre "iCanvasGadget" pour plus de détail.
;                         - #Object_Selected: Saves all selected Objects of the specified canvas.
;  sFileName: The name of the destination Json file.
;  iCanvasGadget: Gadget canvas number to restrict #Object_All or #Object_Selected to the specified gadget, or #PB_Ignore to allow all gadgets in the application.
;  Result: Returns 1 if the registration was successful, otherwise 0.
          ;}
          SaveObject(#Object_Selected, "Data - Copy\Copy.json", #Canevas)  ; Saves all #Canvas Objects in a Json file.
          
          ; Saves the Objects that are selected to compare them later once they have been pasted to the selected ones.
          
          ; Clears the list.
          ClearList(ListeObjet.i())
          
          ;{ Examines all Objects selected or not in the canvas
;  iCanvasGadget: Gadget Canvas number.
;  bSelected: #True, if only the selected Objects should be returned, or #False to return all Objects.
;  Result: Returns the number of selected Objects or all Objects in the Canvas or 0 if the Canvas was invalid.
          ;}
          ; Examines all selected objects.
          ExamineObjects(#Canevas, #True)
          
          ; Loop used to save in a list all the Objects selected from the canvas.
          Repeat
            
            ;{ Returns the next Object selected or not in the specified canvas. WARNING: ExamineObjects() must be called the first time, this is used to review (and return their number) all the Objects.
;  iCanvasGadget: Canvas gadget number.
;  Result: The Object Number corresponds to an Object selected or not, or 0 if no other Object was found.
            ;}
            ; Here will retrieve the selected Objects.
            ObjetSelectionner.i = NextObject(#Canevas)
            
            ; If there is an Object selected.
            If ObjetSelectionner.i > 0
              
              ; Memorize the object number.
              AddElement(ListeObjet.i())
              ListeObjet.i() = ObjetSelectionner.i
              
            EndIf
            
          Until ObjetSelectionner.i = 0
          
          ; Clears all selected objects that are in the list.
          ; Does not work if the FreeObject() command is placed in the previous loop or the elements are placed in the list because
          ; As the Items are being examined, deleting them at the same time causes problems.
          ForEach ListeObjet.i()
            
            ; Deletes the object.
            FreeObject(ListeObjet.i())
            
          Next
          
          ; Activate the paste item because something is pasted.
          DisableMenuItem(#ContextualMenu, #ContextualMenuPaste, #False)
          
        Case #ContextualMenuCopy
          
          ; Creates a directory if it does not exist otherwise does nothing.
          CreateDirectory("Data - Copy") 
          
          ;{ Save one or more specific Objects in a Json file.
;  iObject: Object Number or one of the following constants:
          ;                         - #Object_All: Sauvegarde tous les Objets, voir le paramètre "iCanvasGadget" pour plus de détail.
;                         - #Object_Selected: Saves all selected Objects of the specified canvas.
;  sFileName: The name of the destination Json file.
;  iCanvasGadget: Gadget canvas number to restrict #Object_All or #Object_Selected to the specified gadget, or #PB_Ignore to allow all gadgets in the application.
;  Result: Returns 1 if the registration was successful, otherwise 0.
          ;}
          SaveObject(#Object_Selected, "Data - Copy\Copy.json", #Canevas)  ; Saves all #Canvas Objects in a Json file.
          
          ; Activate the paste item because something is pasted.
          DisableMenuItem(#ContextualMenu, #ContextualMenuPaste, #False)
          
        Case #ContextualMenuPaste
          
          ;{ Deselects the specified Object or all Objects on the specified Canvas.
;  iObject: The Object number, the following constants can be used instead of the object number.
;                          - #Object_All: Deselects all objects.
;                          - #Object_Selected: Deselects all selected objects.
;  iCanvasGadget: Canvas number to restrict Deselection only to this canvas, or #PB_Ignore to authorize Deselection of all objects regardless of where it is located.
          ;}
          ; Deselects all selected Objects.
          UnselectObject(#Object_Selected, #Canevas)
          
          ; Saves all object numbers present on the canvas to differentiate them from those loaded.
          
          ; Clears the list.
          ClearList(ListeObjet.i())
          
          ;{ Examines all Objects selected or not in the canvas
;  iCanvasGadget: Gadget Canvas number.
;  bSelected: #True, if only the selected Objects should be returned, or #False to return all Objects.
;  Result: Returns the number of selected Objects or all Objects in the Canvas or 0 if the Canvas was invalid.
          ;}
          ; Examine all objects.
          ExamineObjects(#Canevas, #False)
          
          ; Loop used to save all the Objects on the canvas in a list.
          Repeat
            
            ;{ Returns the next Object selected or not in the specified canvas. WARNING: ExamineObjects() must be called the first time, this is used to review (and return their number) all the Objects.
;  iCanvasGadget: Canvas gadget number.
;  Result: The Object Number corresponds to an Object selected or not, or 0 if no other Object was found.
            ;}
            ; Here will collect the Objects.
            ObjetExaminer.i = NextObject(#Canevas)
            
            ; If there is an Object.
            If ObjetExaminer.i > 0
              
              ; Memorize the object number.
              AddElement(ListeObjet.i())
              ListeObjet.i() = ObjetExaminer.i
              
            EndIf
            
          Until ObjetExaminer.i = 0
          
          ;{ Loads and adds one or more Objects to the specified gadget canvas. WARNING: InitializeCanvasObjects() must be called before adding Objects.
          
; The Object number must be between 1 and 65535 to load only the desired Object or use one of the following constants:
;                        - #PB_Any allows you to automatically assign a random Object number to loaded Objects, useful for duplicating Objects for example.
;                        - #PB_Igniore (Default) replaces Objects in the canvas.
;
; sFileName: A name of the source Json file.
; iParentObject: A valid Object number to which the Object must be attached (optional). By default, the Object will be placed on the canvas frame.
; iFrameIndex: An index of the frame (starting with 0) or one of the following constants, into which the Object should be attached (optional).
;                        - #Frame_NoFrame: The Object will be attached to the standard non-indexed frame (frame for attachments).
;                        - #Frame_ViewedFrame: The Object will be attached to the currently displayed indexed frame.
; Result: The Object number of the Object created or 0 if the creation failed.
          ;}
          LoadObject(#Canevas, #PB_Any, "Data - Copy\Copy.json")  ; Load all Objects into the #Canvas from a Json file.
                                                                  ; LoadObject returns the Object number if only one Object is loaded.
                                                                  ; You need to use #pb_ignore in LoadObject to use the ids in the save.
          
          ;{ Examines all Objects selected or not in the canvas
;  iCanvasGadget: Gadget Canvas number.
;  bSelected: #True, if only the selected Objects should be returned, or #False to return all Objects.
;  Result: Returns the number of selected Objects or all Objects in the Canvas or 0 if the Canvas was invalid.
          ;}
          ; Examine all objects.
          ExamineObjects(#Canevas, #False)
          
          ; Loop which is used to compare the Objects which have been pasted to those on the canvas, searches for the new Objects, those which have just been pasted.
          Repeat
            
            ;{ Returns the next Object selected or not in the specified canvas. WARNING: ExamineObjects() must be called the first time, this is used to review (and return their number) all the Objects.
;  iCanvasGadget: Canvas gadget number.
;  Result: The Object Number corresponds to an Object selected or not, or 0 if no other Object was found.
            ;}
            ; Here will collect the Objects.
            ObjetExaminer.i = NextObject(#Canevas)
            
            ; Returns the tag to "False" to say that there is no Object found.
            ObjetTrouver.b = #False
            
            ; If there is an object.
            If ObjetExaminer.i > 0
              
              ; See if the Object exists.
              ForEach ListeObjet()
                If ListeObjet() = ObjetExaminer.i
                  ObjetTrouver.b = #True
                  Break
                EndIf
              Next
              
              ; If the object is unknown.
              If ObjetTrouver.b = #False
                
                ; Select the Objects and shift it by 10 pixels in X and Y.
                SelectObject(ObjetExaminer.i, #Canevas)
                SetObjectX(ObjetExaminer.i, GetObjectX(ObjetExaminer.i) + 25)
                SetObjectY(ObjetExaminer.i, GetObjectY(ObjetExaminer.i) + 25)
                
                ; Adds this new Object to the list.
                
                ; Go to the end of the list.
                LastElement(ListeObjet.i())
                
                ; Memorize the object number.
                AddElement(ListeObjet.i())
                ListeObjet.i() = ObjetExaminer.i
                
              EndIf
              
            EndIf
            
          Until ObjetExaminer.i = 0
          
      EndSelect
      
    Case #PB_Event_CloseWindow ; Exits the program.
      Break
      
  EndSelect
  
  ; Objects in Canvas event loop.
  Repeat
    
    Select CanvasObjectsEvent(#Canevas) ; Something happened in the Canvas.
        
      Case #Event_Object ; This is an Object type event.
        
        Select CanvasObjectsEventType(#Canevas) ; What type of event happened on the Object?
            
          Case #EventType_MouseEnter
            
          Case #EventType_RightMouseBottonDown
            
          Case #EventType_RightMouseBottonUp
            
          Case #EventType_RightMouseClick
            
        EndSelect
        
      Case #Event_None ; No event, Never omit or else the program will run in a loop!
        
        Break
        
    EndSelect
    
  ForEver
  
ForEver

; Deletes the backups directory.
While DeleteDirectory("Data - Copy", "") = 0
Wend

End

Re: EditorFactory - Module for object management in a Canvas

Posted: Mon Nov 17, 2025 2:56 am
by ShadowStorm
Here is an example of how to undo and restore changes made to objects in the editor.

Again, this is not supported natively, but with a workaround, it is possible to do so. It would be better if it were native, but for now, that does not exist.

Code: Select all

; Example: Undo and restore changes to Objects in the editor.

; Saves all changes in the editor and allows them to be undone and restored with two buttons, "Undo" and "Restore".
; Changes are saved in Json files which will be loaded based on the state of the changes in the editor.
; The files created are persistent and in a folder because written on disk in the location of the code file, the folder is: "Undo - Redo".

; When you use the program for the first time, a backup is made automatically so that you can go back if you make a change later.
; The backup index will be 1, the maximum backup will be 1.

; Be careful however, in this example, created for the occasion, the backup files will be overwritten in certain situations in order to create a real realistic behavior of cancellation and restoration.
; For example, if you made 10 changes in the editor (So 1 from start + 10 from you = 11 total files created) and you go back for example 5 actions (So 11 - 5 = 6)
; The index backup will be 6, the maximum backup number will be 11, so the total number of backup files will be 11 but if you make other changes at this level then
; all files from 7 will be overwritten later depending on the number of modifications you make, the other files will be useless and will wait to be overwritten.
; At the end of the program, all backup files will be deleted in this example.

; This code uses the following functions: SaveObject() and LoadObject().

; Includes the program file.
XIncludeFile "Editors Factory.pbi"

; Initializes the module so you can use it.
UseModule EditorFactory

; ---------------------------------------------- Example: ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

; Program constants.
Enumeration 1
  #Window  ; The Window.
  #Canevas; The Left Canvas.
  #Font    ; A font.
  #BoutonAnnuler ; Cancel button.
  #BoutonRestaurer    ; Restore button.
EndEnumeration

; The numbering of Objects starts from 1 up to 65535.
Enumeration 1
  
  #ObjetConteneurObjets ; Object that contains all Objects.
  
  #Objet1               ; Item #1.
  #Objet2               ; Item #2.
  #SubObjet1_Objet2     ; Object #1 in the container Object Object2.
  #Sub_SubObjet1_Objet2 ; Object #1 in Sub Object #1 of Container Object Object2.
  #Sub_SubObjet2_Objet2 ; Object #2 in Sub Object #1 of Container Object Object2.
  #SubObjet2_Objet2     ; Object #2 in the Container Object Object2.
  #Objet3               ; Item #3.
  
EndEnumeration

; ----------------------------------------------

;{ Callback procedure to draw an image on the Object in the Canvas because when it is created, there is nothing (Gray).
; MyDrawingObjet1 = The name of the custom procedure to draw something on the desired Object, give it the name you want but it must have these arguments: Object.i, Width.i, Height.i
; The parameters: (Object.i, Width.i, Height.i) will automatically be used in the MyDrawingObject1() procedure.
; Object.i is the number of the Object, this variable does not appear in the procedure but is essential.
; Width.i is the width of the Object.
; Height.i is the height of the Object.
;} iData.i est une donnée personnalisé, un chiffre ici (Couleur), n'est pas obligatoire, même dans les paramètre de la procédure, MyDrawingObjet1(Object.i, Width.i, Height.i) fonctionne aussi.
; This procedure will automatically draw or redraw the contents of this procedure on the Object whenever necessary.
Runtime Procedure MyDrawingObject1(Object.i, Width.i, Height.i, iData.i)
  AddPathBox(0.5, 0.5, Width - 1, Height - 1)
  VectorSourceColor(iData | $80000000)
  FillPath(#PB_Path_Preserve)
  VectorSourceColor(iData | $FF000000)
  MovePathCursor(10, 10)
  VectorFont(FontID(#Font))
  VectorSourceColor(RGBA(0, 0, 0, 255))
  DrawVectorText("Object #" + Str(Object))
  StrokePath(1)
EndProcedure

Runtime Procedure MyDrawingObject2(Object.i, Width.i, Height.i, iData.i)
  
  If GetObjectDictionary(Object.i, "Active panel button") = "0"
    AddPathBox(0.5, 0.5, Width - 1, Height - 1)
    VectorSourceColor(iData | $80000000)
    FillPath(#PB_Path_Preserve)
    VectorSourceColor(iData | $FF000000)
    MovePathCursor(10, 10)
    VectorFont(FontID(#Font))
    VectorSourceColor(RGBA(0, 0, 0, 255))
    DrawVectorText("Tab no." + Str(Object))
    StrokePath(1)
  ElseIf GetObjectDictionary(Object.i, "Active panel button") = "1"
    AddPathBox(0.5, 0.5, Width - 1, Height - 1)
    VectorSourceColor(RGB(255, 150, 0) | $80000000)
    FillPath(#PB_Path_Preserve)
    VectorSourceColor(iData | $FF000000)
    MovePathCursor(10, 10)
    VectorFont(FontID(#Font))
    VectorSourceColor(RGBA(0, 0, 0, 255))
    DrawVectorText("Tab no." + Str(Object))
    StrokePath(1)
  EndIf
  
EndProcedure

; ----------------------------------------------

; Loading the font.
LoadFont(#Font, "Arial", 14)

; Creating a window.
OpenWindow(#Window, 0, 0, 800, 600, "Example #016, Undo and restore changes in the editor - Minimalist.", #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget | #PB_Window_SizeGadget | #PB_Window_ScreenCentered)

; Creation of the left Gadget Canvas.
CanvasGadget(#Canevas, 0, 31, WindowWidth(#Window), WindowHeight(#Window) - 31, #PB_Canvas_Keyboard | #PB_Canvas_Border)

; Creation of buttons.
ButtonGadget(#BoutonAnnuler, 0, 1, 75, 30, "Cancel")
ButtonGadget(#BoutonRestaurer, 74, 1, 75, 30, "Restore")

;{ Initializes the Object manager for the specified Gadget Canvas in the specified window, must be done for each Gadget Canvas.
;  iCanvasGadget: PB Number of the Canvas gadget.
;  iWindow: PB Window number.
;  Result: Returns #True, if initialization was successful, otherwise, #False.
;}
; Initializes management for the Gadget Canvas.
InitializeCanvasObjects(#Canevas, #Window)

;{ Creates and adds an Object to the specified Canvas. WARNING: InitializeCanvasObjects() must be called before adding Objects to this Canvas.
;  iCanvasGadget: PB Canvas gadget number.
;  iObject: A self-defined Object Number or #PB_Any to generate a unique number. The self-defined number must be between 1 and 65535.
;  iX, iY: The position of the Object on the Canvas.
;  iWidth, iHeight: The size of the Object on the Canvas.
;	 iParentObject: A valid Object number to which the Object must be attached (optional). By default, the Object will be placed on the canvas frame.
;  iFrameIndex: An index of the frame (starting with 0) or one of the following constants, into which the Object should be attached (optional).
;                          - #Frame_NoFrame: The Object will be attached to the standard non-indexed frame (frame for attachments).
;                          - #Frame_ViewedFrame: The Object will be attached to the currently displayed indexed frame.
;  Result: The Object number of the Object created or 0 if the creation failed.
;}
; Creation of the Container Object of type Panel #ObjetConteneurObjects.
CreateObject(#Canevas, #ObjetConteneurObjets, 20, 50, 550, 450) ; Creation of the PanelGadget type container object.

;{ Adds a new frame to the object.
;  iObject: Object number.
;  iFrameIndex: Index (starting with 0), at which the frame should be inserted. #Frame_LastFrame can be used to add the frame to the end of all frames.
;                         This new frame will automatically be set as the current visible frame.
;  iViewBoxX: Local X position of clipping for internal child objects. 0 means the clipping is exactly at the edge of the object.
;  iViewBoxY: Local Y position of clipping for internal child objects. 0 means the clipping is exactly at the edge of the object.
;  iViewBoxWidth: Width of the clipping box for internal child objects. Add #Boundary_ParentSize to a value (#Boundary_ParentSize ± value) to make the width relative to the size of the object.
;  iViewBoxHeight: Height of clipping box for internal child objects. Add #Boundary_ParentSize to a value (#Boundary_ParentSize ± value) to make the height relative to the size of the object.
;  Result: The index of the new frame added, or -1 on failure.
;}
AddObjectFrame(#ObjetConteneurObjets, 0) ; Adds a frame to the Container Object of type PanelGadget.

;{ Creates and adds an Object to the specified Canvas. WARNING: InitializeCanvasObjects() must be called before adding Objects to this Canvas.
;  iCanvasGadget: PB Canvas gadget number.
;  iObject: A self-defined Object Number or #PB_Any to generate a unique number. The self-defined number must be between 1 and 65535.
;  iX, iY: The position of the Object on the Canvas.
;  iWidth, iHeight: The size of the Object on the Canvas.
;	 iParentObject: A valid Object number to which the Object must be attached (optional). By default, the Object will be placed on the canvas frame.
;  iFrameIndex: An index of the frame (starting with 0) or one of the following constants, into which the Object should be attached (optional).
;                          - #Frame_NoFrame: The Object will be attached to the standard non-indexed frame (frame for attachments).
;                          - #Frame_ViewedFrame: The Object will be attached to the currently displayed indexed frame.
;  Result: The Object number of the Object created or 0 if the creation failed.
;}
; The #Objects were created on the #Canvas, but here are empty (Gray and without handles).
CreateObject(#Canevas, #Objet1, 20, 50, 200, 40, #ObjetConteneurObjets, 0) ; Creation of the child Object (#Object1) of the parent Object (#ObjectContainerObject).

CreateObject(#Canevas, #Objet2, 20, 95, 400, 254, #ObjetConteneurObjets, 0) ; Creation of the child Object (#Object1) of the parent Object (#ObjectContainerObject).
CreateObject(#Canevas, #SubObjet1_Objet2, 20, 42, 300, 145, #Objet2)        ; Creation of the child Object (#SubObjet1_Objet2) of the parent Object (#Objet2).
CreateObject(#Canevas, #Sub_SubObjet1_Objet2, 20, 40, 250, 40, #SubObjet1_Objet2) ; Creation of the child Object (#Sub_SubObjet1_Objet2) of the child Object (#SubObjet1_Objet2) of the parent Object (#Objet2).
CreateObject(#Canevas, #Sub_SubObjet2_Objet2, 20, 85, 250, 40, #SubObjet1_Objet2) ; Creation of the child Object (#Sub_SubObjet2_Objet2) of the child Object (#SubObjet1_Objet2) of the parent Object (#Objet2).

CreateObject(#Canevas, #SubObjet2_Objet2, 20, 193, 210, 40, #Objet2) ; Creation of the child Object (#SubObjet2_Objet2) of the parent Object (#Objet2).

CreateObject(#Canevas, #Objet3, 20, 354, 200, 40, #ObjetConteneurObjets, 0) ; Creation of the child Object (#Object1) of the parent Object (#ObjectContainerObject).

;{ Modifies the displayed frame of an object.
;  iObject: Object number.
;  iFrameIndex: Frame index, starting with 0.
;}
ShowObjectFrame(#ObjetConteneurObjets, 0) ; Displays page n°2 of the Objects #ObjetConteneurObjects.

;{ Defines a custom drawing procedure for the specified Object.
;  iObject: The Object number, the following constants can be used instead of the object number.
;                          - #Object_Default: Defines the default image for all new objects created.
;                          - #Object_All: Sets the image of all objects.
;                          - #Object_Selected: Sets the image of all selected objects.
;  sCallbackName: An empty string or valid execution procedure name to a procedure with the following arguments: Callback(iObject.i, iWidth.i, iHeight.i, iData.i)
;                          - iObject contains the number of the Object.
;                          - iWidth contains the current width.
;                          - iHeight contains the current height.
;                          - iData contains individual custom user data (Number) which will also be sent to the function.
;  Result: Returns #True if the callback was successfully set to the Object or #False if the Object does not exist.
;}
SetObjectDrawingCallback(#ObjetConteneurObjets, "MyDrawingObject1()", RGB(192, 192, 192))

SetObjectDrawingCallback(#Objet1, "MyDrawingObject1()", RGB(128, 192, 64))

SetObjectDrawingCallback(#Objet2, "MyDrawingObject1()", RGB(192, 64, 128))
SetObjectDrawingCallback(#SubObjet1_Objet2, "MyDrawingObject1()", RGB(192, 128, 64))
SetObjectDrawingCallback(#Sub_SubObjet1_Objet2, "MyDrawingObject1()", RGB(255, 192, 0))
SetObjectDrawingCallback(#Sub_SubObjet2_Objet2, "MyDrawingObject1()", RGB(64, 128, 192))

SetObjectDrawingCallback(#SubObjet2_Objet2, "MyDrawingObject1()", RGB(128, 192, 64))

SetObjectDrawingCallback(#Objet3, "MyDrawingObject1()", RGB(192, 128, 64))

;{ Sets the style of the mouse cursor bounding box on the specified canvas.
;  iCanvasGadget.i The Gadget Canvas number.
;  eType: One of the following style types:
;                          - #SelectionStyle_None: Hides the selection frame.
;                          - #SelectionStyle_Solid: solid frame line.
;                          - #SelectionStyle_Dotted: Dotted frame line.
;                          - #SelectionStyle_Dashed: Dahsed frame line.
;                          - #SelectionStyle_Ignore: Ignore this setting.
;                          - #SelectionStyle_Partially: You can combine this constant (|) with the style type to allow partial selection.
;  iColor: RGBA color of the frame or #SelectionStyle_Ignore to ignore this setting.
;  dThickness: Thickness of the frame line or #SelectionStyle_Ignore to ignore this parameter.
;  iBackgroundColor.i The color inside the selection or #SelectionStyle_Ignore to ignore this setting.
;}
; Enables and sets mouse selection on the canvas.
SetCursorSelectionStyle(#Canevas, #SelectionStyle_Dashed)

;{ Adds one or more standard or custom handles to the specified Object. Custom grips can have positional alignment and offset.
;  iObject: The Object number, the following constants can be used instead of the object number.
;                     - #Object_Default: Defines the default handles for all new objects created.
;                     - #Object_All: Defines the handles of all objects.
;                     - #Object_Selected: Sets the handles of all selected objects.
;  eType: A combination of all handle types that need to be added. *
;  iImage: An image number for the handle. By default (#PB_Default) the default handle image is used.
;  eAlignment: The alignment of the custom handle. By default it is #Alignment_Default = #Alignment_Center **
;  iX, iY: Offset position of the handle relative to the alignment and the Object.
;  Result: Returns #True, if the addition of the handle was successful, otherwise #False.
;
;                  * The following handle types can be used and combined:
;                    #Handle_Position: A handle to move the Object.
;                    #Handle_Rotation: A handle to rotate the Object. (UNUSED).
;                    #Handle_BottomLeft, #Handle_Bottom, #Handle_BottomRight, #Handle_Left, #Handle_Right, #Handle_TopLeft, #Handle_Top, #Handle_TopRight: A handle To resize the Object in this direction.
;                    #Handle_Custom1 ... #Handle_Custom8: A custom handle:
;
;                    Additionally, the following constants are predefined combinations:
;                    #Handle_Width = #Handle_Left | #Handle_Right.
;                    #Handle_Height = #Handle_Top | #Handle_Bottom.
;                    #Handle_Edge = #Handle_Width | #Handle_Height.
;                    #Handle_Corner = #Handle_BottomLeft | #Handle_BottomRight | #Handle_TopLeft | #Handle_TopRight.
;                    #Handle_Size = #Handle_Edge | #Handle_Corner.
;
;                 **The following alignment types can be used and combined:
;                    #Alignment_Top: Aligns the center of the handle to the top edge of the Object.
;                    #Alignment_Bottom: Aligns the center of the handle to the bottom edge of the Object.
;                    #Alignment_Left: Aligns the center of the handle to the left edge of the Object.
;                    #Alignment_Right: Aligns the center of the handle to the right edge of the Object.
;                    #Alignment_Center: Aligns the center of the handle to the center (x and/or y) of the Object.
;}
; Adds move and resize handles to all Objects.
AddObjectHandle(#Object_All, #Handle_Size | #Handle_Position)

DisableGadget(#BoutonAnnuler, #True) ; Disables the undo button.
DisableGadget(#BoutonRestaurer, #True); Disables the restore button.

Define NiveauAnnulationMaximal.i = 1 ; The maximum cancellation level in the program, this indicates the maximum number of cancellations counted by the program.
Define IndexAnnulationActuel.i = 1 ; The current undo index where the program is located, this is used to load the adéquoite backup file following this index.
Define Change.b = #False           ; When a change occurs in the editor, it is used to create an automatic backup.

; Creates a directory if it does not exist otherwise does nothing.
CreateDirectory("Undo - Redo") 

;{ Save one or more specific Objects in a Json file.
;  iObject: Object Number or one of the following constants:
;                         - #Object_All: Sauvegarde tous les Objets, voir le paramètre "iCanvasGadget" pour plus de détail.
;                         - #Object_Selected: Saves all selected Objects of the specified canvas.
;  sFileName: The name of the destination Json file.
;  iCanvasGadget: Gadget canvas number to restrict #Object_All or #Object_Selected to the specified gadget, or #PB_Ignore to allow all gadgets in the application.
;  Result: Returns 1 if the registration was successful, otherwise 0.
;}
; makes a first backup when the program starts.
SaveObject(#Object_All, "Undo - Redo\Save n°1.json", #Canevas)  ; Save all #Canvas Objects in a Json file.

; You see, it’s very easy!

; The window event loop and gadgets.
Repeat
  
  Select WaitWindowEvent()
      
    Case #PB_Event_Gadget  ; A Gadget type event.
      
      Select EventGadget()
          
        Case #BoutonAnnuler ; When the Save button is clicked.
          
          If NiveauAnnulationMaximal.i > 0 And IndexAnnulationActuel.i > 1 ; Security check to be sure that at least one backup file exists and that the current index is at least 2 minimum.
            
            IndexAnnulationActuel.i - 1 ; Removes 1 from the current undo index.
            
            ;{ Loads and adds one or more Objects to the specified gadget canvas. WARNING: InitializeCanvasObjects() must be called before adding Objects.
            
; The Object number must be between 1 and 65535 to load only the desired Object or use one of the following constants:
;                        - #PB_Any allows you to automatically assign a random Object number to loaded Objects, useful for duplicating Objects for example.
;                        - #PB_Igniore (Default) replaces Objects in the canvas.
;
; sFileName: A name of the source Json file.
; iParentObject: A valid Object number to which the Object must be attached (optional). By default, the Object will be placed on the canvas frame.
; iFrameIndex: An index of the frame (starting with 0) or one of the following constants, into which the Object should be attached (optional).
;                        - #Frame_NoFrame: The Object will be attached to the standard non-indexed frame (frame for attachments).
;                        - #Frame_ViewedFrame: The Object will be attached to the currently displayed indexed frame.
; Result: The Object number of the Object created or 0 if the creation failed.
            ;}
            LoadObject(#Canevas, #PB_Ignore, "Undo - Redo\Save n°" + Str(IndexAnnulationActuel.i) + ".json")  ; Load all Objects into the #Canvas from a Json file.
                                                                                                               ; LoadObject returns the Object number if only one Object is loaded.
                                                                                                               ; You need to use #pb_ignore in LoadObject to use the ids in the save.
            
            If IndexAnnulationActuel.i = 1 ; If the current undo index is 1, at the very beginning.
              DisableGadget(#BoutonAnnuler, #True) ; Disables the cancel button because there is no more backup before.
            EndIf
            
            ; Enable the restore button because there is a backup available afterwards.
            DisableGadget(#BoutonRestaurer, #False) 
            
          EndIf
          
        Case #BoutonRestaurer ; When the Load button is clicked.
          
          If NiveauAnnulationMaximal.i > 0 And IndexAnnulationActuel.i < NiveauAnnulationMaximal.i
            
            IndexAnnulationActuel.i + 1 ; Adds 1 to the current undo index.
            
            ;{ Loads and adds one or more Objects to the specified gadget canvas. WARNING: InitializeCanvasObjects() must be called before adding Objects.
            
; The Object number must be between 1 and 65535 to load only the desired Object or use one of the following constants:
;                        - #PB_Any allows you to automatically assign a random Object number to loaded Objects, useful for duplicating Objects for example.
;                        - #PB_Igniore (Default) replaces Objects in the canvas.
;
; sFileName: A name of the source Json file.
; iParentObject: A valid Object number to which the Object must be attached (optional). By default, the Object will be placed on the canvas frame.
; iFrameIndex: An index of the frame (starting with 0) or one of the following constants, into which the Object should be attached (optional).
;                        - #Frame_NoFrame: The Object will be attached to the standard non-indexed frame (frame for attachments).
;                        - #Frame_ViewedFrame: The Object will be attached to the currently displayed indexed frame.
; Result: The Object number of the Object created or 0 if the creation failed.
            ;}
            LoadObject(#Canevas, #PB_Ignore, "Undo - Redo\Save n°" + Str(IndexAnnulationActuel.i) + ".json")  ; Load all Objects into the #Canvas from a Json file.
                                                                                                               ; LoadObject returns the Object number if only one Object is loaded.
                                                                                                               ; You need to use #pb_ignore in LoadObject to use the ids in the save.
            
            If IndexAnnulationActuel.i = NiveauAnnulationMaximal.i ; If the current undo index is at the end.
              DisableGadget(#BoutonRestaurer, #True)               ; Disables the restore button because there is no backup afterward.
            EndIf
            
            ; Enables the cancel button because there is a backup available before.
            DisableGadget(#BoutonAnnuler, #False) 
            
          EndIf
          
      EndSelect
      
    Case #PB_Event_SizeWindow, #PB_Event_MaximizeWindow, #PB_Event_RestoreWindow ; Adjusts the size and position of gadgets when the window is resized, maximized or restored.
      ResizeGadget(#Canevas, 0, 31, WindowWidth(#Window), WindowHeight(#Window) - 31)
      ResizeGadget(#BoutonAnnuler, 0, 1, 150, 30)
      ResizeGadget(#BoutonRestaurer, 149, 1, 125, 30)
      
    Case #PB_Event_CloseWindow ; Exits the program.
      Break
      
  EndSelect
  
  ; Objects in Canvas event loop.
  Repeat
    
    Select CanvasObjectsEvent(#Canevas) ; Something happened in the Canvas.
        
      Case #Event_Object ; This is an Object type event.
        
        Select CanvasObjectsEventType(#Canevas) ; What type of event happened on the Object?
            
          Case #EventType_Moved, #EventType_Resized ; #EventType_Created
            Change.b = #True ; A change has occurred in the editor.
            
        EndSelect
        
      Case #Event_None ; No event, Never omit or else the program will run in a loop!
        Break
        
    EndSelect
    
  ForEver
  
  ; If a change has taken place in the editor.
    If Change.b = #True
      
      Change.b = #False ; Disables the change tag.
      IndexAnnulationActuel.i + 1 ; Adds 1 to the current undo index.
      NiveauAnnulationMaximal.i = IndexAnnulationActuel.i ; Puts the total backup number at the same level as the undo index.
      
      ; Creates a directory if it does not exist otherwise does nothing.
      CreateDirectory("Undo - Redo") 
      
      ;{ Save one or more specific Objects in a Json file.
;  iObject: Object Number or one of the following constants:
      ;                         - #Object_All: Sauvegarde tous les Objets, voir le paramètre "iCanvasGadget" pour plus de détail.
;                         - #Object_Selected: Saves all selected Objects of the specified canvas.
;  sFileName: The name of the destination Json file.
;  iCanvasGadget: Gadget canvas number to restrict #Object_All or #Object_Selected to the specified gadget, or #PB_Ignore to allow all gadgets in the application.
;  Result: Returns 1 if the registration was successful, otherwise 0.
      ;}
      SaveObject(#Object_All, "Undo - Redo\Save n°" + Str(IndexAnnulationActuel.i) + ".json", #Canevas)  ; Saves all #Canvas Objects in a Json file.
      
      DisableGadget(#BoutonAnnuler, #False) ; Enables the cancel button because there is a backup available before.
      DisableGadget(#BoutonRestaurer, #True) ; Disables the restore button because there is no backup afterward.
      
    EndIf
    
  ForEver
  
  ; Deletes the backups directory.
  While DeleteDirectory("Undo - Redo", "") = 0
  Wend

End


Re: EditorFactory - Module for object management in a Canvas

Posted: Mon Nov 17, 2025 3:00 am
by ShadowStorm
Here is an example of how to save and load objects in an editor. This function is used in the previous code examples I have given you.

Code: Select all

; Example Saving and loading Objects.
; Saving and loading Objects.

; Includes the program file.
XIncludeFile "Editors Factory.pbi"

; Initializes the module so you can use it.
UseModule EditorFactory

; ---------------------------------------------- Example: ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

; Program constants.
Enumeration 1
  #Window  ; The Window.
  #Canevas ; The Canvas.
  #Font    ; A font.
  #BoutonSauvegarder ; Button to save Objects.
  #BoutonCharger     ; Button to load Objects.
EndEnumeration

; The numbering of Objects starts from 1 up to 65535.
Enumeration 1

  #ObjetConteneurObjets ; Object that contains all Objects.
  
  #Objet1               ; Object #1 in the Container Object #ContainerObjectObjects.
  #Objet2               ; Object n°2 in the Container Object #ObjetConteneurObjects.
  #SubObjet1_Objet2     ; Object #1 in the Container Object Object2 in the Container Object #ContainerObjectObjects.
  #Sub_SubObjet1_Objet2 ; Object #1 in Sub Object #1 of Container Object Object2 in Container Object #ContainerObjectObjects.
  #Sub_SubObjet2_Objet2 ; Object #2 in Sub Object #1 of Container Object Object2 in Container Object #ContainerObjectObjects.
  #SubObjet2_Objet2     ; Object #2 in the Container Object Object2 in the Container Object #ContainerObjectObjects.
  #Objet3               ; Object #3 in the Container Object #ContainerObjectObjects.

EndEnumeration

; ----------------------------------------------

;{ Callback procedure to draw an image on the Object in the Canvas because when it is created, there is nothing (Gray).
; MyDrawingObjet1 = The name of the custom procedure to draw something on the desired Object, give it the name you want but it must have these arguments: Object.i, Width.i, Height.i
; The parameters: (Object.i, Width.i, Height.i) will automatically be used in the MyDrawingObject1() procedure.
; Object.i is the number of the Object, this variable does not appear in the procedure but is essential.
; Width.i is the width of the Object.
; Height.i is the height of the Object.
;} iData.i est une donnée personnalisé, un chiffre ici (Couleur), n'est pas obligatoire, même dans les paramètre de la procédure, MyDrawingObjet1(Object.i, Width.i, Height.i) fonctionne aussi.
; This procedure will automatically draw or redraw the contents of this procedure on the Object whenever necessary.
Runtime Procedure MyDrawingObject1(Object.i, Width.i, Height.i, iData.i)
  AddPathBox(0.5, 0.5, Width - 1, Height - 1)
  VectorSourceColor(iData | $80000000)
  FillPath(#PB_Path_Preserve)
  VectorSourceColor(iData | $FF000000)
  MovePathCursor(10, 10)
  VectorFont(FontID(#Font))
  VectorSourceColor(RGBA(0, 0, 0, 255))
  If Object = 1
    DrawVectorText("Object no." + Str(Object) + "- Page n°1")
  Else
    DrawVectorText("Object no." + Str(Object) + "- No Page")
  EndIf
  StrokePath(1)
EndProcedure

; ----------------------------------------------

; Loading the font.
LoadFont(#Font, "Arial", 14)

; Creating a window.
OpenWindow(#Window, 0, 0, 800, 600, "Example n°015: Saving and loading Objects.", #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget | #PB_Window_SizeGadget | #PB_Window_ScreenCentered)

; Creation of the left Gadget Canvas.
CanvasGadget(#Canevas, 0, 31, WindowWidth(#Window), WindowHeight(#Window) - 31, #PB_Canvas_Keyboard | #PB_Canvas_Border)

; Creation of buttons.
ButtonGadget(#BoutonSauvegarder, 0, 1, 150, 30, "Saving Objects")
ButtonGadget(#BoutonCharger, 149, 1, 125, 30, "Load Objects")

;{ Initializes the Object manager for the specified Gadget Canvas in the specified window, must be done for each Gadget Canvas.
;  iCanvasGadget: PB Number of the Canvas gadget.
;  iWindow: PB Window number.
;  Result: Returns #True, if initialization was successful, otherwise, #False.
;}
; Initializes management for the Gadget Canvas.
InitializeCanvasObjects(#Canevas, #Window)

;{ Creates and adds an Object to the specified Canvas. WARNING: InitializeCanvasObjects() must be called before adding Objects to this Canvas.
;  iCanvasGadget: PB Canvas gadget number.
;  iObject: A self-defined Object Number or #PB_Any to generate a unique number. The self-defined number must be between 1 and 65535.
;  iX, iY: The position of the Object on the Canvas.
;  iWidth, iHeight: The size of the Object on the Canvas.
;	 iParentObject: A valid Object number to which the Object must be attached (optional). By default, the Object will be placed on the canvas frame.
;  iFrameIndex: An index of the frame (starting with 0) or one of the following constants, into which the Object should be attached (optional).
;                          - #Frame_NoFrame: The Object will be attached to the standard non-indexed frame (frame for attachments).
;                          - #Frame_ViewedFrame: The Object will be attached to the currently displayed indexed frame.
;  Result: The Object number of the Object created or 0 if the creation failed.
;}
; Creation of the Container Object of type Panel #ObjetConteneurObjects.
CreateObject(#Canevas, #ObjetConteneurObjets, 20, 20, 550, 450) ; Creation of the Container Object.

;{ Adds a new frame to the object.
;  iObject: Object number.
;  iFrameIndex: Index (starting with 0), at which the frame should be inserted. #Frame_LastFrame can be used to add the frame to the end of all frames.
;                         This new frame will automatically be set as the current visible frame.
;  iViewBoxX: Local X position of clipping for internal child objects. 0 means the clipping is exactly at the edge of the object.
;  iViewBoxY: Local Y position of clipping for internal child objects. 0 means the clipping is exactly at the edge of the object.
;  iViewBoxWidth: Width of the clipping box for internal child objects. Add #Boundary_ParentSize to a value (#Boundary_ParentSize ± value) to make the width relative to the size of the object.
;  iViewBoxHeight: Height of clipping box for internal child objects. Add #Boundary_ParentSize to a value (#Boundary_ParentSize ± value) to make the height relative to the size of the object.
;  Result: The index of the new frame added, or -1 on failure.
;}
; Adds a page (Frame) to the #ContainerObjectContainer Object.
; Objects which have Frames will have a different behavior from those without them, they will only be movable on the edges of them and a selection with the mouse can be made inside this Frame.
; The first Page starts from 0, then 1, then 2, etc., several pages can thus be added to a container type Object.
; The other options affect the visibility of this Frame (Position, etc.), but we will not talk about them here because they are a bit complicated for beginners.
; To subsequently add Objects to this container, you will need to indicate the child object to add to this parent container Objects as well as the number of the Frame where the Object should be placed.

; When a container type Object has a Frame (Page), if you want to add children to it and force them to stay on this page, then you will have to indicate on which Page you will need to add them
; and if you do not do this then the object will not be constrained to the Page of this Objects and can therefore be moved outside of this Page, however the children will still be linked to the parent Object.
AddObjectFrame(#ObjetConteneurObjets, 0) ; Adds a Page (Frame) n°0.

;{ Creates and adds an Object to the specified Canvas. WARNING: InitializeCanvasObjects() must be called before adding Objects to this Canvas.
;  iCanvasGadget: PB Canvas gadget number.
;  iObject: A self-defined Object Number or #PB_Any to generate a unique number. The self-defined number must be between 1 and 65535.
;  iX, iY: The position of the Object on the Canvas.
;  iWidth, iHeight: The size of the Object on the Canvas.
;	 iParentObject: A valid Object number to which the Object must be attached (optional). By default, the Object will be placed on the canvas frame.
;  iFrameIndex: An index of the frame (starting with 0) or one of the following constants, into which the Object should be attached (optional).
;                          - #Frame_NoFrame: The Object will be attached to the standard non-indexed frame (frame for attachments).
;                          - #Frame_ViewedFrame: The Object will be attached to the currently displayed indexed frame.
;  Result: The Object number of the Object created or 0 if the creation failed.
;}
; The Objects were created on the #Canvas, but here are empty (Gray and without handles).
CreateObject(#Canevas, #Objet1, 20, 50, 250, 40, #ObjetConteneurObjets, 0) ; Creation of the child Object (#Object1) in the parent Object (#ObjectContainerObject) on Frame n°0.

CreateObject(#Canevas, #Objet2, 20, 95, 400, 254, #ObjetConteneurObjets, 0) ; Creation of the child Object (#Object2) in the parent Object (#ObjectContainerObject) on Frame n°0.
CreateObject(#Canevas, #SubObjet1_Objet2, 20, 42, 300, 145, #Objet2)        ; Creation of the child Object (#SubObjet1_Objet2) in the parent Object (#Objet2), do not indicate a frame number here because the object #Objet2 does not have a Frame.
CreateObject(#Canevas, #Sub_SubObjet1_Objet2, 20, 40, 250, 40, #SubObjet1_Objet2) ; Creation of the child Object (#Sub_SubObjet1_Objet2) in the child Object (#SubObjet1_Objet2) of the parent Object (#Objet2), do not indicate a frame number here because the object #SubObjet1_Objet2 does not have a Frame.
CreateObject(#Canevas, #Sub_SubObjet2_Objet2, 20, 85, 250, 40, #SubObjet1_Objet2) ; Creation of the child Object (#Sub_SubObjet2_Objet2) in the child Object (#SubObjet1_Objet2) of the parent Object (#Objet2), do not indicate a frame number here because the object #SubObjet1_Objet2 does not have a Frame.

CreateObject(#Canevas, #SubObjet2_Objet2, 20, 193, 260, 40, #Objet2) ; Creation of the child Object (#SubObjet2_Objet2) in the parent Object (#Objet2), do not indicate a frame number here because the object #Objet2 does not have a Frame.

CreateObject(#Canevas, #Objet3, 20, 354, 250, 40, #ObjetConteneurObjets, 0) ; Creation of the child Object (#Object3) in the parent Object (#ObjetConteneurObjects) on Frame n°0.

;{ Modifies the displayed frame of an object.
;  iObject: Object number.
;  iFrameIndex: Frame index, starting with 0.
;}
ShowObjectFrame(#ObjetConteneurObjets, 0) ; Displays page n°1 of the Objects #ObjetConteneurObjects.

;{ Defines a custom drawing procedure for the specified Object.
;  iObject: The Object number, the following constants can be used instead of the Object number.
;                          - #Default_Object: Defines the default image for all new Objects created.
;                          - #Object_All: Defines the image of all Objects.
;                          - #Object_Selected: Defines the image of all selected Objects.
;  sCallbackName: An empty string or valid execution procedure name to a procedure with the following arguments: CallbackName(iObject.i, iWidth.i, iHeight.i, iData.i)
;                          - iObject contains the number of the Object.
;                          - iWidth contains the current width.
;                          - iHeight contains the current height.
;                          - iData contains individual custom user data (Number) which will also be sent to the function.
;  Result: Returns #True if the callback was successfully set to the Object or #False if the Object does not exist.
;}
SetObjectDrawingCallback(#ObjetConteneurObjets, "MyDrawingObject1()", RGB(192, 192, 192))

SetObjectDrawingCallback(#Objet1, "MyDrawingObject1()", RGB(128, 192, 64))

SetObjectDrawingCallback(#Objet2, "MyDrawingObject1()", RGB(192, 64, 128))
SetObjectDrawingCallback(#SubObjet1_Objet2, "MyDrawingObject1()", RGB(192, 128, 64))
SetObjectDrawingCallback(#Sub_SubObjet1_Objet2, "MyDrawingObject1()", RGB(255, 192, 0))
SetObjectDrawingCallback(#Sub_SubObjet2_Objet2, "MyDrawingObject1()", RGB(64, 128, 192))

SetObjectDrawingCallback(#SubObjet2_Objet2, "MyDrawingObject1()", RGB(128, 192, 64))

SetObjectDrawingCallback(#Objet3, "MyDrawingObject1()", RGB(192, 128, 64))

;{ Sets the style of the mouse cursor bounding box on the specified canvas.
;  iCanvasGadget.i The Gadget Canvas number.
;  eType: One of the following style types:
;                          - #SelectionStyle_None: Hides the selection frame.
;                          - #SelectionStyle_Solid: solid frame line.
;                          - #SelectionStyle_Dotted: Dotted frame line.
;                          - #SelectionStyle_Dashed: Dahsed frame line.
;                          - #SelectionStyle_Ignore: Ignore this setting.
;                          - #SelectionStyle_Partially: You can combine this constant (|) with the style type to allow partial selection.
;  iColor: RGBA color of the frame or #SelectionStyle_Ignore to ignore this setting.
;  dThickness: Thickness of the frame line or #SelectionStyle_Ignore to ignore this parameter.
;  iBackgroundColor.i The color inside the selection or #SelectionStyle_Ignore to ignore this setting.
;}
; Enables and sets mouse selection on the canvas.
SetCursorSelectionStyle(#Canevas, #SelectionStyle_Dashed)

;{ Adds one or more standard or custom handles to the specified Object. Custom grips can have positional alignment and offset.
;  iObject: The Object number, the following constants can be used instead of the object number.
;                     - #Object_Default: Defines the default handles for all new objects created.
;                     - #Object_All: Defines the handles of all objects.
;                     - #Object_Selected: Sets the handles of all selected objects.
;  eType: A combination of all handle types that need to be added. *
;  iImage: An image number for the handle. By default (#PB_Default) the default handle image is used.
;  eAlignment: The alignment of the custom handle. By default it is #Alignment_Default = #Alignment_Center **
;  iX, iY: Offset position of the handle relative to the alignment and the Object.
;  Result: Returns #True, if the addition of the handle was successful, otherwise #False.
;
;                  * The following handle types can be used and combined:
;                    #Handle_Position: A handle to move the Object.
;                    #Handle_Rotation: A handle to rotate the Object. (UNUSED).
;                    #Handle_BottomLeft, #Handle_Bottom, #Handle_BottomRight, #Handle_Left, #Handle_Right, #Handle_TopLeft, #Handle_Top, #Handle_TopRight: A handle To resize the Object in this direction.
;                    #Handle_Custom1 ... #Handle_Custom8: A custom handle:
;
;                    Additionally, the following constants are predefined combinations:
;                    #Handle_Width = #Handle_Left | #Handle_Right.
;                    #Handle_Height = #Handle_Top | #Handle_Bottom.
;                    #Handle_Edge = #Handle_Width | #Handle_Height.
;                    #Handle_Corner = #Handle_BottomLeft | #Handle_BottomRight | #Handle_TopLeft | #Handle_TopRight.
;                    #Handle_Size = #Handle_Edge | #Handle_Corner.
;
;                 **The following alignment types can be used and combined:
;                    #Alignment_Top: Aligns the center of the handle to the top edge of the Object.
;                    #Alignment_Bottom: Aligns the center of the handle to the bottom edge of the Object.
;                    #Alignment_Left: Aligns the center of the handle to the left edge of the Object.
;                    #Alignment_Right: Aligns the center of the handle to the right edge of the Object.
;                    #Alignment_Center: Aligns the center of the handle to the center (x and/or y) of the Object.
;}
; Adds move and resize handles to all Objects.
AddObjectHandle(#Object_All, #Handle_Size | #Handle_Position)

; You see, it’s easy!

; The window event loop and gadgets.
Repeat
  
  Select WaitWindowEvent()
      
    Case #PB_Event_Gadget  ; A Gadget type event.
      
      Select EventGadget()
          
        Case #BoutonSauvegarder ; When the Save button is clicked.
          
          NomFichier.s = SaveFileRequester("Save...", "Objects.json", "JSON|*.json", 0) ; Opens a standard dialog box for saving a file.
          
          If NomFichier.s
            ;{ Save an object to a file. This file is in JSON format and contains either an object or an array of objects.
;  iObject: Object number or one of the following constants:
;                          - #Object_All: Saves all objects.
;                          - #Object_Selected: Saves all selected objects.
; sFileName: The name of the destination file.
; iCanvasGadget: Canvas gadget number to restrict #Object_All or #Object_Selected to the specified gadget, or #PB_Ignore to allow all gadgets.
; Result: #True, if the recording was successful, otherwise #False.
            ;}
            Debug SaveObject(#Object_All, NomFichier.s, #Canevas)  ; Save all #Canvas Objects in a Json file.
          EndIf
          
        Case #BoutonCharger ; When the Load button is clicked.
          
          NomFichier.s = OpenFileRequester("Load...", "Objects.json", "JSON|*.json", 0) ; Opens a standard dialog box for loading a file.
          
          If NomFichier.s
            ;{ Loads and adds an object or multiple objects to the specified canvas object. WARNING: InitializeCanvasObjects() must be called before adding objects.
;  The file must be in JSON format and must contain either an object or an array of objects.
;  iCanvasGadget: PB gadget number.
;  iObject: In the case of a JSON file containing a single object:
;                           A self-defined object number, #PB_Any to generate a unique number or #PB_Ignore to use the saved object number.
;                           The self-defined number must be between 1 and 65535.
;                          In the case of a JSON file with an array of multiple objects:
;                           A number between 1 and 65535 to choose the object specified in this file, #PB_Any to load all objects and give them a unique number
;                           or #PB_Ignore to load all objects but use saved object numbers.
;                          ATTENTION: Objects with the same number as loaded objects are replaced during loading.
;  sFileName: A file name of the source.
;  iOffsetX, iOffsetY: The position offset of the object from the recorded position.
;  iParentObject: A valid object number to which the object should be attached (optional). By default, the object will be placed on the canvas frame.
;  iFrameIndex: An index of the frame (starting with 0) or one of the following constants, into which the object should be attached (optional).
;                          - #Frame_NoFrame: The object will be attached to the standard non-indexed frame (frame for attachments).
;                          - #Frame_ViewedFrame: The object will be attached to the currently displayed indexed frame.
; - Result: The object number of the created object or 0 if the creation failed.
            ;}
            Debug LoadObject(#Canevas, #PB_Any, NomFichier.s)  ; Load all Objects into the #Canvas from a Json file.
                                                                  ; LoadObject returns the Object number if only one Object is loaded.
                                                                  ; You need to use #pb_ignore in LoadObject to use the ids in the save.
          EndIf
          
      EndSelect
      
    Case #PB_Event_SizeWindow, #PB_Event_MaximizeWindow, #PB_Event_RestoreWindow ; Adjusts the size and position of gadgets when the window is resized, maximized or restored.
      ResizeGadget(#Canevas, 0, 31, WindowWidth(#Window), WindowHeight(#Window) - 31)
      ResizeGadget(#BoutonSauvegarder, 0, 1, 150, 30)
      ResizeGadget(#BoutonCharger, 149, 1, 125, 30)
      
    Case #PB_Event_CloseWindow; Exits the program.
      Break
      
  EndSelect
  
  ; Objects in Canvas event loop.
  Repeat
    
    Select CanvasObjectsEvent(#Canevas) ; Something happened in the Canvas.
        
      Case #Event_Object ; This is an Object type event.
        
        Select EventObject(#Canevas) ; Which Object received an event?
            
          Case 0
            
            Select CanvasObjectsEventType(#Canevas) ; What type of event happened on the Object?
                
              Case 0
                
            EndSelect
            
        EndSelect
        
      Case #Event_None ; No event, Never omit or else the program will run in a loop!
        Break
        
    EndSelect
    
  ForEver
  
ForEver

End

Re: EditorFactory - Module for object management in a Canvas

Posted: Mon Nov 17, 2025 7:37 am
by Denis
ShadowStorm wrote: Sun Nov 16, 2025 8:04 pm
Yes, we've already talked about this. I have a big problem with it, a mental block. It's a real problem, but even if that were the case, I'm not sure it would be enough. I have to give away all this work for free and, on top of that, I have to make it freely available, including for commercial use. I can't do it!

Stargate is okay with it, and he's the one who wrote all the code at my request. His generosity is beyond me, as is that of the others who do this.

It's stronger than me, that's just how it is.
Slt ShadowStorm,
That's a real shame (oui vraiment dommage...).

Re: EditorFactory - Module for object management in a Canvas

Posted: Mon Nov 17, 2025 9:31 am
by Mindphazer
Denis wrote: Mon Nov 17, 2025 7:37 am Slt ShadowStorm,
That's a real shame (oui vraiment dommage...).
And a huge waste...

Re: EditorFactory - Module for object management in a Canvas

Posted: Mon Nov 17, 2025 6:18 pm
by ShadowStorm
But tell me, in addition to doing the work (especially Stargate), would I have to make it freely available, even commercially, and all that for free so that others could profit from it?

You say it's a real shame and a waste, but honestly, for whom?

And what would it achieve, what would it bring us if we did that? Probably nothing. It's easy to criticize, but what would you do?

Would you honestly be willing to make your very long work available for free? For free? And on top of that, the icing on the cake, as open source (which I believe is already the case), and also allow it to be sold?

For me, the code is free, but you can't use it for commercial projects, or even sell the software you make with the code. I know it's annoying, but you have to understand my position.

Or maybe we should set up a royalty system or something like that?

Give me your opinions, how would you do it? If you think I'm having fun, I'd rather see the project move forward, but then again, no one wants to help, but we all have to make it free, open source, and commercial, of course, lol.

Don't you think that's unfair?

Re: EditorFactory - Module for object management in a Canvas

Posted: Tue Nov 18, 2025 12:05 am
by Mindphazer
ShadowStorm wrote: Mon Nov 17, 2025 6:18 pm You say it's a real shame and a waste, but honestly, for whom?
I was only talking about STARGÅTE's work.

Re: EditorFactory - Module for object management in a Canvas

Posted: Tue Nov 18, 2025 3:01 am
by ShadowStorm
Yes, I know I don't count, that I'm nothing, that I only had ideas (which seem pretty good, to be honest), that I didn't write the code, and that my contribution is worthless. In fact, I'm even a “nuisance” to this project. If only I hadn't been there, right? So it's a shame, a real shame, what a waste!

I understand better now!

It's really not a problem that I'm the black sheep, that I'm not liked. Honestly, I don't care at all, if only you knew!

I know my work is worthless, that I'm nothing.

It doesn't matter, I've gotten used to it, I'm fine with it now because I understand things, so what's the problem, you might ask? It's too big (the project), I'm nice, it's true, but I'm not stupid!

So yes, you're right: it's a shame, a real shame, what a waste!

I discussed it at length with Stargate, he never bothered me about it, I think he understood me, and it's not like I didn't do anything!

So I'm afraid that as long as the ugly duckling is alive, you won't be able to use the code for commercial projects!

It's a shame, a real shame, what a waste!

Maybe I should write a song with that title: It's a shame, a real shame, what a waste ! :lol:

He tried, at my request, to create a library for this project (DLL), but it wasn't possible, and the problem would remain the same.

What if we made it open source with the possibility of selling and doing commercial projects with all of this? Do you think Stargate would be motivated again? :mrgreen:

Stargate, please continue the project so that I can sell your work. I have big plans, and I'm going to make a lot of money thanks to you! :D :mrgreen:

No, sorry, but that's not my style. :wink:

Re: EditorFactory - Module for object management in a Canvas

Posted: Tue Nov 18, 2025 7:37 am
by Denis
Salut ShadowStorm,

Why get so worked up?
There's really no reason to make such a big deal out of this.

I tested the code and was thrilled with it.
I'm not criticizing your work.
It's just my personal opinion on the potential use of the code. I see this forum as a place for mutual assistance.
There are many skilled coders here.

Pourquoi s'emporter ?
Il n'y a pas vraiment de raisons de monter tout cela en épingle.

J'ai testé le code et j'étais emballé.
Aucune critique sur votre travail.
Juste une opinion personnelle sur l'utilisation potentielle du code, je considère ce forum comme un forum d'entraide, il y a de nombreux codeurs compétents ici.

Re: EditorFactory - Module for object management in a Canvas

Posted: Tue Nov 18, 2025 9:43 am
by ShadowStorm
Hi Denis,

It's true that I got a little carried away, but it was for a reason,
and I assure you, it had nothing to do with you :wink:

I was talking about Mindphazer. You should see how he criticized me in 2022.
Like everyone else, he said something like:

Mindphazer (2022): “Your ideas lead nowhere,” “A waste of time for Stargate.”
netmaestro (2022): “The idea has no value.”
HeX0R (2022): Insinuations that I want to make money off Stargate (I think).
skywalk (2022): “Why do you write more than you code?”

But anyway, it doesn't matter, the project is already well underway and we can already do a lot
thanks to Stargate and my ideas (which are worthless).

Yes, Denis, you're absolutely right and I agree with you, but what a waste ! :cry:

Re: EditorFactory - Module for object management in a Canvas

Posted: Tue Nov 18, 2025 9:56 am
by Mindphazer
ShadowStorm wrote: Tue Nov 18, 2025 9:43 am netmaestro (2022): “The idea has no value.”
HeX0R (2022): Insinuations that I want to make money off Stargate (I think).
skywalk (2022): “Why do you write more than you code?”
These guys have contributed a lot to the forum over the years. So what they say might make sense... Think about it instead of complaining and beating yourself up

Re: EditorFactory - Module for object management in a Canvas

Posted: Tue Nov 18, 2025 2:26 pm
by Fred
Ok we will stop the drama here, it's going nowhere.