GR32_Layers.pas 115 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964
  1. unit GR32_Layers;
  2. (* ***** BEGIN LICENSE BLOCK *****
  3. * Version: MPL 1.1 or LGPL 2.1 with linking exception
  4. *
  5. * The contents of this file are subject to the Mozilla Public License Version
  6. * 1.1 (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. * http://www.mozilla.org/MPL/
  9. *
  10. * Software distributed under the License is distributed on an "AS IS" basis,
  11. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  12. * for the specific language governing rights and limitations under the
  13. * License.
  14. *
  15. * Alternatively, the contents of this file may be used under the terms of the
  16. * Free Pascal modified version of the GNU Lesser General Public License
  17. * Version 2.1 (the "FPC modified LGPL License"), in which case the provisions
  18. * of this license are applicable instead of those above.
  19. * Please see the file LICENSE.txt for additional information concerning this
  20. * license.
  21. *
  22. * The Original Code is Graphics32
  23. *
  24. * The Initial Developer of the Original Code is
  25. * Alex A. Denisov
  26. *
  27. * Portions created by the Initial Developer are Copyright (C) 2000-2009
  28. * the Initial Developer. All Rights Reserved.
  29. *
  30. * ***** END LICENSE BLOCK ***** *)
  31. interface
  32. {$INCLUDE GR32.inc}
  33. uses
  34. {$if defined(FRAMEWORK_VCL)}
  35. System.UITypes,
  36. WinApi.Windows,
  37. Vcl.Controls,
  38. Vcl.Graphics,
  39. Vcl.Forms,
  40. {$elseif defined(FRAMEWORK_FMX)}
  41. System.UITypes,
  42. WinApi.Windows,
  43. FMX.Types,
  44. FMX.Controls,
  45. FMX.Graphics,
  46. FMX.Forms,
  47. {$elseif defined(FRAMEWORK_LCL)}
  48. Controls,
  49. Graphics,
  50. Forms,
  51. {$ifend}
  52. Generics.Collections,
  53. Classes,
  54. SysUtils,
  55. Math,
  56. GR32;
  57. //------------------------------------------------------------------------------
  58. //
  59. // Layer option bit flags
  60. //
  61. //------------------------------------------------------------------------------
  62. // Used by TCustomLayer.LayerOptions
  63. //------------------------------------------------------------------------------
  64. const
  65. LOB_VISIBLE = $80000000; // 31-st bit: Controls the layer visibility
  66. LOB_GDI_OVERLAY = $40000000; // 30-th bit: Indicates that the layer performs drawing when its owner draws its GDI Overlays.
  67. LOB_MOUSE_EVENTS = $20000000; // 29-th bit: Specifies whether the layer responds to mouse messages.
  68. LOB_NO_UPDATE = $10000000; // 28-th bit: Disables automatic repainting when the layer changes its location or other properties.
  69. LOB_NO_CAPTURE = $08000000; // 27-th bit: Allows to override automatic capturing of mouse messages when the left mouse is pressed on top of the layer. This bit has no effect if LOB_MOUSE_EVENTS is not set.
  70. LOB_INVALID = $04000000; // 26-th bit: Used internall by repaint optimizer.
  71. LOB_FORCE_UPDATE = $02000000; // 25-th bit: Used internally to force a layer to update when it is being hidden.
  72. LOB_RESERVED_24 = $01000000; // 24-th bit
  73. LOB_RESERVED_MASK = $FF000000;
  74. type
  75. TCustomLayer = class;
  76. TLayerClass = class of TCustomLayer;
  77. TLayerCollection = class;
  78. //------------------------------------------------------------------------------
  79. //
  80. // Layer event types
  81. //
  82. //------------------------------------------------------------------------------
  83. TLayerUpdateEvent = procedure(Sender: TObject; Layer: TCustomLayer) of object;
  84. TAreaUpdateEvent = TAreaChangedEvent;
  85. TLayerListNotification = (lnLayerAdded, lnLayerInserted, lnLayerDeleted, lnCleared);
  86. TLayerListNotifyEvent = procedure(Sender: TLayerCollection; Action: TLayerListNotification; Layer: TCustomLayer; Index: Integer) of object;
  87. TGetScaleEvent = procedure(Sender: TObject; out ScaleX, ScaleY: TFloat) of object;
  88. TGetShiftEvent = procedure(Sender: TObject; out ShiftX, ShiftY: TFloat) of object;
  89. //------------------------------------------------------------------------------
  90. //
  91. // Layer notification interfaces
  92. //
  93. //------------------------------------------------------------------------------
  94. ILayerNotification = interface
  95. ['{5549DE7E-778E-4500-9F20-6455EC3BC574}']
  96. procedure LayerUpdated(ALayer: TCustomLayer);
  97. procedure LayerAreaUpdated(ALayer: TCustomLayer; const AArea: TRect; const AInfo: Cardinal);
  98. procedure LayerListNotify(ALayer: TCustomLayer; AAction: TLayerListNotification; AIndex: Integer);
  99. end;
  100. IUpdateRectNotification = interface
  101. ['{457C0840-F4C3-48CE-8440-C790CC2CA103}']
  102. procedure AreaUpdated(const AArea: TRect; const AInfo: Cardinal);
  103. end;
  104. ILayerUpdateNotification = interface
  105. ['{FE142F0F-D009-4B6A-8874-6F7BF2208E84}']
  106. procedure LayerUpdated(ALayer: TCustomLayer);
  107. end;
  108. ILayerListNotification = interface
  109. ['{7E8F0FC3-F9B7-4E38-9CF4-5B1A38901849}']
  110. procedure LayerListNotify(ALayer: TCustomLayer; AAction: TLayerListNotification; AIndex: Integer);
  111. end;
  112. //------------------------------------------------------------------------------
  113. //
  114. // TLayerCollection
  115. //
  116. //------------------------------------------------------------------------------
  117. // A collection of layers.
  118. //------------------------------------------------------------------------------
  119. TLayerCollection = class(TPersistent)
  120. strict private type
  121. TLayerList = TList<TCustomLayer>;
  122. strict private
  123. FItems: TLayerList;
  124. FMouseEvents: Boolean;
  125. FMouseListener: TCustomLayer;
  126. FUpdateCount: Integer;
  127. FLockUpdateCount: Integer;
  128. FModified: boolean;
  129. FOwner: TPersistent;
  130. FSubscribers: TList<IInterface>;
  131. FOnChanging: TNotifyEvent;
  132. FOnChange: TNotifyEvent;
  133. FOnGDIUpdate: TNotifyEvent;
  134. FOnListNotify: TLayerListNotifyEvent;
  135. FOnLayerUpdated: TLayerUpdateEvent;
  136. FOnAreaUpdated: TAreaUpdateEvent;
  137. FOnGetViewportScale: TGetScaleEvent;
  138. FOnGetViewportShift: TGetShiftEvent;
  139. protected
  140. // Friend-methods; Used by TCustomLayer
  141. procedure InsertItem(Item: TCustomLayer);
  142. procedure ExtractItem(Item: TCustomLayer);
  143. procedure MoveItem(Item: TCustomLayer; NewIndex: Integer);
  144. protected
  145. procedure BeginUpdate; {$IFDEF USEINLINING} inline; {$ENDIF}
  146. procedure EndUpdate; {$IFDEF USEINLINING} inline; {$ENDIF}
  147. procedure BeginLockUpdate;
  148. procedure EndLockUpdate;
  149. procedure Changed; {$IFDEF USEINLINING} inline; {$ENDIF}
  150. procedure Changing; {$IFDEF USEINLINING} inline; {$ENDIF}
  151. function FindLayerAtPos(X, Y: Integer; OptionsMask: Cardinal): TCustomLayer;
  152. procedure GDIUpdate;
  153. procedure DoUpdateLayer(Layer: TCustomLayer);
  154. procedure DoUpdateArea(const Rect: TRect; const Info: Cardinal);
  155. procedure Notify(Action: TLayerListNotification; Layer: TCustomLayer; Index: Integer);
  156. function MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer): TCustomLayer;
  157. function MouseMove(Shift: TShiftState; X, Y: Integer): TCustomLayer;
  158. function MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer): TCustomLayer;
  159. function GetCount: Integer;
  160. function GetItem(Index: Integer): TCustomLayer;
  161. function GetOwner: TPersistent; override;
  162. procedure SetItem(Index: Integer; Value: TCustomLayer);
  163. procedure SetMouseEvents(Value: Boolean);
  164. procedure SetMouseListener(Value: TCustomLayer);
  165. property UpdateCount: Integer read FUpdateCount;
  166. property LockUpdateCount: Integer read FLockUpdateCount;
  167. property Modified: boolean read FModified;
  168. property OnChanging: TNotifyEvent read FOnChanging write FOnChanging;
  169. property OnChange: TNotifyEvent read FOnChange write FOnChange;
  170. property OnListNotify: TLayerListNotifyEvent read FOnListNotify write FOnListNotify;
  171. property OnGDIUpdate: TNotifyEvent read FOnGDIUpdate write FOnGDIUpdate;
  172. property OnLayerUpdated: TLayerUpdateEvent read FOnLayerUpdated write FOnLayerUpdated;
  173. property OnAreaUpdated: TAreaUpdateEvent read FOnAreaUpdated write FOnAreaUpdated;
  174. property OnGetViewportScale: TGetScaleEvent read FOnGetViewportScale write FOnGetViewportScale;
  175. property OnGetViewportShift: TGetShiftEvent read FOnGetViewportShift write FOnGetViewportShift;
  176. public
  177. constructor Create(AOwner: TPersistent); virtual;
  178. destructor Destroy; override;
  179. function GetEnumerator: TEnumerator<TCustomLayer>;
  180. procedure Subscribe(const ASubscriber: IInterface);
  181. procedure Unsubscribe(const ASubscriber: IInterface);
  182. function Add(ItemClass: TLayerClass): TCustomLayer; overload;
  183. function Insert(Index: Integer; ItemClass: TLayerClass): TCustomLayer; overload;
  184. {$if defined(FPC) or (CompilerVersion > 29.0)} // Delphi 10 or later
  185. function Add<T: TCustomLayer>: T; overload;
  186. function Insert<T: TCustomLayer>(Index: Integer): T; overload;
  187. {$ifend}
  188. procedure Delete(Index: Integer);
  189. procedure Clear;
  190. function IndexOf(Item: TCustomLayer): integer;
  191. procedure Assign(Source: TPersistent); override;
  192. // LocalToViewport: Convert from bitmap (local) coordinates to buffer/control (viewport) coordinates
  193. function LocalToViewport(const APoint: TFloatPoint; AScaled: Boolean): TFloatPoint; overload;
  194. function LocalToViewport(const APoint: TPoint; AScaled: Boolean): TFloatPoint; overload; // Needed because FPC lacks implicit TPoint<->TFloatPoint conversion
  195. // ViewportToLocal: Convert from buffer/control (viewport) coordinates to bitmap (local) coordinates
  196. function ViewportToLocal(const APoint: TFloatPoint; AScaled: Boolean): TFloatPoint; overload;
  197. function ViewportToLocal(const APoint: TPoint; AScaled: Boolean): TFloatPoint; overload; // Needed because FPC lacks implicit TPoint<->TFloatPoint conversion
  198. procedure GetViewportScale(out ScaleX, ScaleY: TFloat); virtual;
  199. procedure GetViewportShift(out ShiftX, ShiftY: TFloat); virtual;
  200. property Count: Integer read GetCount;
  201. property Owner: TPersistent read FOwner;
  202. property Items[Index: Integer]: TCustomLayer read GetItem write SetItem; default;
  203. property MouseListener: TCustomLayer read FMouseListener write SetMouseListener;
  204. property MouseEvents: Boolean read FMouseEvents write SetMouseEvents;
  205. end;
  206. TLayerCollectionClass = class of TLayerCollection;
  207. //------------------------------------------------------------------------------
  208. //
  209. // TCustomLayer
  210. //
  211. //------------------------------------------------------------------------------
  212. // The layer base class.
  213. //------------------------------------------------------------------------------
  214. TLayerState = (lsMouseLeft, lsMouseRight, lsMouseMiddle);
  215. TLayerStates = set of TLayerState;
  216. TPaintLayerEvent = procedure(Sender: TObject; Buffer: TBitmap32) of object;
  217. THitTestEvent = procedure(Sender: TObject; X, Y: Integer; var Passed: Boolean) of object;
  218. TCustomLayer = class(TNotifiablePersistent)
  219. strict private
  220. FCursor: TCursor;
  221. FFreeNotifies: TList<TCustomLayer>;
  222. FLayerCollection: TLayerCollection;
  223. FTag: NativeInt;
  224. FClicked: Boolean;
  225. FPendingForceUpdate: boolean;
  226. FOnHitTest: THitTestEvent;
  227. FOnKeyDown: TKeyEvent;
  228. FOnKeyUp: TKeyEvent;
  229. FOnMouseDown: TMouseEvent;
  230. FOnMouseMove: TMouseMoveEvent;
  231. FOnMouseUp: TMouseEvent;
  232. FOnPaint: TPaintLayerEvent;
  233. FOnDestroy: TNotifyEvent;
  234. FOnDblClick: TNotifyEvent;
  235. FOnClick: TNotifyEvent;
  236. function GetIndex: Integer;
  237. function GetMouseEvents: Boolean;
  238. function GetVisible: Boolean;
  239. procedure SetMouseEvents(Value: Boolean);
  240. procedure SetVisible(Value: Boolean);
  241. function GetInvalid: Boolean;
  242. procedure SetInvalid(Value: Boolean);
  243. function GetForceUpdate: Boolean;
  244. procedure SetForceUpdate(Value: Boolean);
  245. protected
  246. // Members that need friend access from TLayerCollection
  247. FLayerStates: TLayerStates;
  248. strict protected
  249. FLayerOptions: Cardinal;
  250. protected
  251. procedure AddNotification(ALayer: TCustomLayer); deprecated 'Use AddFreeNotification instead';
  252. procedure RemoveNotification(ALayer: TCustomLayer); deprecated 'Use RemoveFreeNotification instead';
  253. procedure Notification(ALayer: TCustomLayer); deprecated 'Use FreeNotification instead'; // No longer virtual; We want to force desecendant to use FreeNotification.
  254. procedure AddFreeNotification(ALayer: TCustomLayer);
  255. procedure RemoveFreeNotification(ALayer: TCustomLayer);
  256. procedure FreeNotification(ALayer: TCustomLayer); virtual;
  257. protected
  258. procedure Changing;
  259. procedure Click; virtual;
  260. procedure DblClick; virtual;
  261. function DoHitTest(X, Y: Integer): Boolean; virtual;
  262. procedure DoPaint(Buffer: TBitmap32);
  263. function GetOwner: TPersistent; override;
  264. procedure KeyDown(var Key: Word; Shift: TShiftState); virtual;
  265. procedure KeyUp(var Key: Word; Shift: TShiftState); virtual;
  266. procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); virtual;
  267. procedure MouseMove(Shift: TShiftState; X, Y: Integer); virtual;
  268. procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); virtual;
  269. procedure MouseEnter; virtual;
  270. procedure MouseLeave; virtual;
  271. procedure Paint(Buffer: TBitmap32); virtual;
  272. procedure PaintGDI(Canvas: TCanvas); virtual;
  273. procedure SetIndex(Value: Integer); virtual;
  274. procedure SetCursor(Value: TCursor); virtual;
  275. procedure SetLayerCollection(Value: TLayerCollection); virtual;
  276. procedure SetLayerOptions(Value: Cardinal); virtual;
  277. procedure DoChanged; overload; override;
  278. procedure AreaUpdated(const AArea: TRect; const AInfo: Cardinal);
  279. procedure UpdateRect(const ARect: TRect);
  280. procedure Update(const ARect: TRect); overload; deprecated 'Use UpdateRect';
  281. procedure Changed(const Rect: TRect; const Info: Cardinal = 0); reintroduce; overload;
  282. property Invalid: Boolean read GetInvalid write SetInvalid;
  283. property ForceUpdate: Boolean read GetForceUpdate write SetForceUpdate;
  284. public
  285. constructor Create(ALayerCollection: TLayerCollection); virtual;
  286. destructor Destroy; override;
  287. procedure BeforeDestruction; override;
  288. procedure Update; overload; virtual;
  289. function HitTest(X, Y: Integer): Boolean;
  290. procedure BringToFront;
  291. procedure SendToBack;
  292. procedure SetAsMouseListener;
  293. // LayerToControl: Convert from layer coordinates to viewport (buffer/control) coordinates.
  294. function LayerToControl(const p: TPoint): TPoint; overload; virtual;
  295. function LayerToControl(const r: TRect): TRect; overload; virtual;
  296. function LayerToControl(const p: TFloatPoint): TFloatPoint; overload; virtual;
  297. function LayerToControl(const r: TFloatRect): TFloatRect; overload; virtual;
  298. // ControlToLayer: Convert from viewport (buffer) coordinates to layer coordinates.
  299. function ControlToLayer(const p: TPoint): TPoint; overload; virtual;
  300. function ControlToLayer(const r: TRect): TRect; overload; virtual;
  301. function ControlToLayer(const p: TFloatPoint): TFloatPoint; overload; virtual;
  302. function ControlToLayer(const r: TFloatRect): TFloatRect; overload; virtual;
  303. // LayerToContent: Convert from layer to content coordinates, taking the layer's
  304. // internal content scaling into account.
  305. // Used, for example, with TBitmapLayers that must stretch their bitmap to fill
  306. // the layer.
  307. function LayerToContent(const APoint: TPoint): TPoint; overload; virtual;
  308. function LayerToContent(const APoint: TFloatPoint): TFloatPoint; overload; virtual;
  309. // ContentToLayer: Convert from content to layer coordinates, taking the layer's
  310. // internal content scaling into account.
  311. function ContentToLayer(const APoint: TPoint): TPoint; overload; virtual;
  312. function ContentToLayer(const APoint: TFloatPoint): TFloatPoint; overload; virtual;
  313. property Cursor: TCursor read FCursor write SetCursor;
  314. property Index: Integer read GetIndex write SetIndex;
  315. property LayerCollection: TLayerCollection read FLayerCollection write SetLayerCollection;
  316. property LayerOptions: Cardinal read FLayerOptions write SetLayerOptions;
  317. property LayerStates: TLayerStates read FLayerStates;
  318. property MouseEvents: Boolean read GetMouseEvents write SetMouseEvents;
  319. property Tag: NativeInt read FTag write FTag;
  320. property Visible: Boolean read GetVisible write SetVisible;
  321. property OnDestroy: TNotifyEvent read FOnDestroy write FOnDestroy;
  322. property OnHitTest: THitTestEvent read FOnHitTest write FOnHitTest;
  323. property OnPaint: TPaintLayerEvent read FOnPaint write FOnPaint;
  324. property OnClick: TNotifyEvent read FOnClick write FOnClick;
  325. property OnDblClick: TNotifyEvent read FOnDblClick write FOnDblClick;
  326. property OnKeyDown: TKeyEvent read FOnKeyDown write FOnKeyDown;
  327. property OnKeyUp: TKeyEvent read FOnKeyUp write FOnKeyUp;
  328. property OnMouseDown: TMouseEvent read FOnMouseDown write FOnMouseDown;
  329. property OnMouseMove: TMouseMoveEvent read FOnMouseMove write FOnMouseMove;
  330. property OnMouseUp: TMouseEvent read FOnMouseUp write FOnMouseUp;
  331. end;
  332. //------------------------------------------------------------------------------
  333. //
  334. // TPositionedLayer
  335. //
  336. //------------------------------------------------------------------------------
  337. // Base class for layers that have position and size.
  338. //------------------------------------------------------------------------------
  339. type
  340. TLayerGetUpdateRectEvent = procedure(Sender: TObject; var UpdateRect: TRect) of object;
  341. TPositionedLayer = class(TCustomLayer)
  342. strict private
  343. FLocation: TFloatRect;
  344. FScaled: Boolean;
  345. FOnGetUpdateRect: TLayerGetUpdateRectEvent;
  346. procedure SetLocation(const Value: TFloatRect);
  347. protected
  348. function DoHitTest(X, Y: Integer): Boolean; override;
  349. procedure DoSetLocation(const NewLocation: TFloatRect); virtual;
  350. function GetScaled: Boolean; virtual;
  351. procedure SetScaled(Value: Boolean); virtual;
  352. function DoGetUpdateRect: TRect; virtual;
  353. // GetUpdateRect: Returns the area covered by the layer in viewport (buffer/control) coordinates.
  354. // By default returns the same area as GetAdjustedLocation. Result can be customized
  355. // via the OnGetUpdateRect event or by overriding the DoGetUpdateRect method.
  356. function GetUpdateRect: TRect;
  357. // GetContentSize: Size of layer content (e.g. the bitmap if is has one).
  358. // Used by LayerToContent and ContentToLayer to translate between layer and content
  359. // coordinates.
  360. // Returns (0, 0) if the layer does not perform content scaling.
  361. function GetContentSize: TPoint; virtual;
  362. public
  363. constructor Create(ALayerCollection: TLayerCollection); override;
  364. procedure Update; override;
  365. function LayerToControl(const APoint: TPoint): TPoint; overload; override;
  366. function LayerToControl(const ARect: TRect): TRect; overload; override;
  367. function LayerToControl(const APoint: TFloatPoint): TFloatPoint; overload; override;
  368. function LayerToControl(const ARect: TFloatRect): TFloatRect; overload; override;
  369. function ControlToLayer(const APoint: TPoint): TPoint; overload; override;
  370. function ControlToLayer(const ARect: TRect): TRect; overload; override;
  371. function ControlToLayer(const APoint: TFloatPoint): TFloatPoint; overload; override;
  372. function ControlToLayer(const ARect: TFloatRect): TFloatRect; overload; override;
  373. function LayerToContent(const APoint: TPoint): TPoint; overload; override;
  374. function LayerToContent(const APoint: TFloatPoint): TFloatPoint; overload; override;
  375. function ContentToLayer(const APoint: TPoint): TPoint; overload; override;
  376. function ContentToLayer(const APoint: TFloatPoint): TFloatPoint; overload; override;
  377. // GetAdjustedRect: Convert from bitmap coordinates to viewport (buffer/control) coordinates.
  378. function GetAdjustedRect(const R: TFloatRect): TFloatRect; virtual;
  379. // GetAdjustedLocation: Return the layer's location in viewport (buffer/control) coordinates.
  380. function GetAdjustedLocation: TFloatRect;
  381. // Location: The layer's position & size.
  382. // If Scaled=True, the coordinates are relative to the bitmap, in bitmap coordinates.
  383. // If Scaled=False, the coordinates are relative to the control/viewport, in control coordinates.
  384. property Location: TFloatRect read FLocation write SetLocation;
  385. property Scaled: Boolean read GetScaled write SetScaled;
  386. property OnGetUpdateRect: TLayerGetUpdateRectEvent read FOnGetUpdateRect write FOnGetUpdateRect;
  387. end;
  388. //------------------------------------------------------------------------------
  389. //
  390. // TCustomIndirectBitmapLayer
  391. //
  392. //------------------------------------------------------------------------------
  393. // Base class for layers referencing a bitmap. The layer does not own the bitmap.
  394. //------------------------------------------------------------------------------
  395. type
  396. TCustomIndirectBitmapLayer = class(TPositionedLayer)
  397. strict private
  398. FAlphaHit: Boolean;
  399. FCropped: Boolean;
  400. strict protected
  401. FBitmap: TCustomBitmap32;
  402. function OwnsBitmap: boolean; virtual;
  403. private
  404. procedure DoSetBitmap(Value: TCustomBitmap32);
  405. protected
  406. function DoHitTest(X, Y: Integer): Boolean; override;
  407. procedure Paint(Buffer: TBitmap32); override;
  408. function GetContentSize: TPoint; override;
  409. protected
  410. procedure BitmapAreaChanged(Sender: TObject; const Area: TRect; const Info: Cardinal);
  411. procedure SetBitmap(Value: TCustomBitmap32); virtual;
  412. procedure SetCropped(Value: Boolean);
  413. property Bitmap: TCustomBitmap32 read FBitmap write SetBitmap;
  414. public
  415. constructor Create(ALayerCollection: TLayerCollection); overload; override;
  416. constructor Create(ALayerCollection: TLayerCollection; ABitmap: TCustomBitmap32); reintroduce; overload;
  417. destructor Destroy; override;
  418. property AlphaHit: Boolean read FAlphaHit write FAlphaHit;
  419. property Cropped: Boolean read FCropped write SetCropped;
  420. end;
  421. TIndirectBitmapLayer = class(TCustomIndirectBitmapLayer)
  422. public
  423. property Bitmap;
  424. end;
  425. //------------------------------------------------------------------------------
  426. //
  427. // TCustomBitmapLayer
  428. //
  429. //------------------------------------------------------------------------------
  430. // Abstract base class for layers containing a bitmap. The layer owns the bitmap.
  431. //------------------------------------------------------------------------------
  432. type
  433. TCustomBitmapLayer = class abstract(TCustomIndirectBitmapLayer)
  434. strict protected
  435. function OwnsBitmap: boolean; override;
  436. protected
  437. procedure SetBitmap(Value: TCustomBitmap32); override;
  438. function GetBitmapClass: TCustomBitmap32Class; virtual; abstract;
  439. function CreateBitmap: TCustomBitmap32; virtual;
  440. public
  441. constructor Create(ALayerCollection: TLayerCollection); override;
  442. end;
  443. //------------------------------------------------------------------------------
  444. //
  445. // TBitmapLayer
  446. //
  447. //------------------------------------------------------------------------------
  448. // A layer containing a TBitmap32. The layer owns the bitmap.
  449. //------------------------------------------------------------------------------
  450. type
  451. TBitmapLayer = class(TCustomBitmapLayer)
  452. protected
  453. function GetBitmapClass: TCustomBitmap32Class; override;
  454. function GetBitmap: TBitmap32;
  455. procedure SetBitmap(Value: TBitmap32); reintroduce;
  456. public
  457. property Bitmap: TBitmap32 read GetBitmap write SetBitmap;
  458. end;
  459. //------------------------------------------------------------------------------
  460. //
  461. // TCustomRubberBandLayer
  462. //
  463. //------------------------------------------------------------------------------
  464. // Base class for design layers displaying a stippled polygon with optional
  465. // selection handles at the vertices.
  466. //------------------------------------------------------------------------------
  467. type
  468. TCustomRubberBandLayer = class;
  469. TRubberbandPassMouse = class(TPersistent)
  470. strict private
  471. FOwner: TCustomRubberBandLayer;
  472. FEnabled: Boolean;
  473. FToChild: Boolean;
  474. FLayerUnderCursor: Boolean;
  475. FCancelIfPassed: Boolean;
  476. protected
  477. function GetChildUnderCursor(X, Y: Integer; Exclude: TPositionedLayer = nil): TPositionedLayer;
  478. public
  479. constructor Create(AOwner: TCustomRubberBandLayer);
  480. property Enabled: Boolean read FEnabled write FEnabled default False;
  481. property ToChild: Boolean read FToChild write FToChild default False;
  482. property ToLayerUnderCursor: Boolean read FLayerUnderCursor write FLayerUnderCursor default False;
  483. property CancelIfPassed: Boolean read FCancelIfPassed write FCancelIfPassed default False;
  484. end;
  485. ILayerHitTest = interface
  486. ['{5F458999-F3BE-47F1-9215-B496927D7BA9}']
  487. // Layer position/size when the context was created
  488. function GetStartLocation: TFloatRect;
  489. procedure SetStartLocation(const Value: TFloatRect);
  490. property StartLocation: TFloatRect read GetStartLocation write SetStartLocation;
  491. // Mouse position when context was created
  492. function GetStartPosition: TPoint;
  493. property StartPosition: TPoint read GetStartPosition;
  494. // Current mouse position
  495. procedure SetCurrentPosition(const Value: TPoint);
  496. function GetCurrentPosition: TPoint;
  497. property CurrentPosition: TPoint read GetCurrentPosition write SetCurrentPosition;
  498. // Current shift state
  499. function GetShift: TShiftState;
  500. procedure SetShift(Value: TShiftState);
  501. property Shift: TShiftState read GetShift write SetShift;
  502. // Cursor corresponding to current position and shift state
  503. function GetCursor: integer;
  504. procedure SetCursor(Value: integer);
  505. property Cursor: integer read GetCursor write SetCursor;
  506. end;
  507. ILayerHitTestVertex = interface(ILayerHitTest)
  508. ['{6BFC44FB-02FA-4999-BBCD-1085FC81F9DC}']
  509. // The index of the vertex being dragged
  510. function GetVertex: integer;
  511. procedure SetVertex(Value: integer);
  512. property Vertex: integer read GetVertex write SetVertex;
  513. // The initial value of the vertex being dragged
  514. function GetStartValue: TFloatPoint;
  515. procedure SetStartValue(const Value: TFloatPoint);
  516. property StartValue: TFloatPoint read GetStartValue write SetStartValue;
  517. end;
  518. ILayerHitTestMove = interface(ILayerHitTest)
  519. ['{3CA95766-7294-42FB-A5F6-85153376F0B4}']
  520. end;
  521. TRubberBandHandleStyle = (hsSquare, hsCircle, hsDiamond);
  522. TRubberBandHandleDrawParams = record
  523. HandleStyle: TRubberBandHandleStyle;
  524. HandleSize: TFloat;
  525. HandleFill: TColor32;
  526. HandleFrame: TColor32;
  527. HandleFrameSize: TFloat;
  528. end;
  529. TRubberBandHandleEvent = procedure(Sender: TCustomRubberBandLayer; AIndex: integer) of object;
  530. TRubberBandHandleMoveEvent = procedure(Sender: TCustomRubberBandLayer; AIndex: integer; var APos: TFloatPoint) of object;
  531. TRubberBandPaintHandleEvent = procedure(Sender: TCustomRubberBandLayer; Buffer: TBitmap32; const p: TFloatPoint; AIndex: integer; var ADrawParams: TRubberBandHandleDrawParams; var Handled: boolean) of object;
  532. TRubberBandUpdateHandleEvent = procedure(Sender: TCustomRubberBandLayer; Buffer: TBitmap32; const p: TFloatPoint; AIndex: integer; var UpdateRect: TRect; var Handled: boolean) of object;
  533. TLayerShiftState = TShiftState; // Actually only [ssShift, ssAlt, ssCtrl] but we can't subtype because of the way TShiftState is declared.
  534. TCustomRubberBandLayer = class(TPositionedLayer)
  535. strict protected type
  536. // TODO : Replace these with anonymous methods once FPC catches up (expected for FPC 4)
  537. TRubberBandPaintFrameHandler = procedure(Buffer: TBitmap32; const r: TRect) of object;
  538. TRubberBandPaintHandleHandler = procedure(Buffer: TBitmap32; const r: TRect; Index: integer) of object;
  539. TRubberBandPaintHandlesHandler = procedure(Buffer: TBitmap32; const r: TRect; var Handled: boolean) of object;
  540. strict private
  541. FChildLayer: TPositionedLayer;
  542. FVertices: TArrayOfFloatPoint;
  543. FFrameStipplePattern: TArrayOfColor32;
  544. FFrameStippleStep: TFloat;
  545. FFrameStippleCounter: TFloat;
  546. FHandleFrame: TColor32;
  547. FHandleFill: TColor32;
  548. FHandleSize: TFloat;
  549. FHandleHitZone: TFloat;
  550. FHandleFrameSize: TFloat;
  551. FHandleStyle: TRubberBandHandleStyle;
  552. FOnUserChange: TNotifyEvent;
  553. FOnHandleClicked: TRubberBandHandleEvent;
  554. FOnHandleMove: TRubberBandHandleMoveEvent;
  555. FOnHandleMoved: TRubberBandHandleEvent;
  556. FOnPaintHandle: TRubberBandPaintHandleEvent;
  557. FOnUpdateHandle: TRubberBandUpdateHandleEvent;
  558. FQuantized: Integer;
  559. FQuantizeShiftToggle: TLayerShiftState;
  560. FPassMouse: TRubberbandPassMouse;
  561. FHitTest: ILayerHitTest;
  562. procedure SetFrameStipple(const Value: TArrayOfColor32);
  563. procedure SetFrameStippleStep(const Value: TFloat);
  564. procedure SetFrameStippleCounter(const Value: TFloat);
  565. procedure SetChildLayer(Value: TPositionedLayer);
  566. procedure SetHandleStyle(const Value: TRubberBandHandleStyle);
  567. procedure SetHandleSize(Value: TFloat);
  568. procedure SetHandleHitZone(const Value: TFloat);
  569. procedure SetHandleFill(Value: TColor32);
  570. procedure SetHandleFrame(Value: TColor32);
  571. procedure SetHandleFrameSize(Value: TFloat);
  572. procedure SetQuantized(const Value: Integer);
  573. procedure SetVertices(const Value: TArrayOfFloatPoint);
  574. procedure SetVertex(Index: integer; const Value: TFloatPoint);
  575. function GetVertex(Index: integer): TFloatPoint;
  576. protected
  577. FIsDragging: Boolean; // For backward compatibility. Equals (ActiveHitTest <> nil)
  578. function DoHitTest(X, Y: Integer): Boolean; override;
  579. procedure DoSetLocation(const NewLocation: TFloatRect); override;
  580. function GetScaled: Boolean; override; //TODO : We need to be notified+repainted when child.Scaled/Location changes
  581. procedure SetScaled(Value: Boolean); override;
  582. function FindVertex(const APosition: TPoint): integer; virtual;
  583. function GetHitTest(const APosition: TPoint; AShift: TShiftState = []): ILayerHitTest; virtual;
  584. procedure SetHitTest(const AHitTest: ILayerHitTest); virtual;
  585. procedure ApplyHitTestCursor(const AHitTest: ILayerHitTest); virtual;
  586. function GetHitTestCursor(const AHitTest: ILayerHitTest): TCursor; virtual;
  587. procedure DoHandleClicked(VertexIndex: integer); virtual;
  588. procedure DoHandleMove(VertexIndex: integer; var APos: TFloatPoint); virtual;
  589. procedure DoHandleMoved(VertexIndex: integer); virtual;
  590. procedure KeyDown(var Key: Word; Shift: TShiftState); override;
  591. procedure KeyUp(var Key: Word; Shift: TShiftState); override;
  592. procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
  593. procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
  594. procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
  595. procedure FreeNotification(ALayer: TCustomLayer); override;
  596. procedure Paint(Buffer: TBitmap32); override;
  597. procedure SetLayerOptions(Value: Cardinal); override;
  598. procedure UpdateChildLayer; virtual;
  599. function IsFrameVisible: boolean; virtual;
  600. function IsVertexVisible(VertexIndex: integer): boolean; virtual;
  601. function AllowMove: boolean; virtual;
  602. procedure DrawHandle(Buffer: TBitmap32; const p: TFloatPoint; AIndex: integer; const DrawParams: TRubberBandHandleDrawParams); virtual;
  603. procedure DoDrawVertex(Buffer: TBitmap32; const R: TRect; VertexIndex: integer); virtual;
  604. procedure DoDrawVertices(Buffer: TBitmap32; const R: TRect; var Handled: boolean); virtual;
  605. procedure DrawFrame(Buffer: TBitmap32; const R: TRect); virtual;
  606. procedure DoUpdateVertex(Buffer: TBitmap32; const R: TRect; VertexIndex: integer); virtual;
  607. procedure DoUpdateVertices(Buffer: TBitmap32; const R: TRect; var Handled: boolean); virtual;
  608. procedure DoUpdateFrame(Buffer: TBitmap32; const R: TRect); virtual;
  609. procedure DoDrawUpdate(Buffer: TBitmap32; FrameHandler: TRubberBandPaintFrameHandler;
  610. VerticesHandler: TRubberBandPaintHandlesHandler; VertexHandler: TRubberBandPaintHandleHandler);
  611. procedure UpdateFrame;
  612. procedure UpdateVertices;
  613. function ApplyOffset(const AHitTest: ILayerHitTest; AQuantize: boolean): boolean; virtual;
  614. function CanQuantize: boolean; virtual;
  615. function ShouldQuantize(const AHitTest: ILayerHitTest): boolean; virtual;
  616. property Vertices: TArrayOfFloatPoint read FVertices write SetVertices;
  617. public
  618. constructor Create(ALayerCollection: TLayerCollection); override;
  619. destructor Destroy; override;
  620. procedure Update; override;
  621. procedure Quantize;
  622. property ChildLayer: TPositionedLayer read FChildLayer write SetChildLayer;
  623. property Vertex[Index: integer]: TFloatPoint read GetVertex write SetVertex;
  624. property HandleStyle: TRubberBandHandleStyle read FHandleStyle write SetHandleStyle;
  625. // HandleSize: Radius of handle
  626. property HandleSize: TFloat read FHandleSize write SetHandleSize;
  627. // HandleHitZone: Width of extra "invisible" area around handle where the handle can be clicked
  628. property HandleHitZone: TFloat read FHandleHitZone write SetHandleHitZone;
  629. // HandleFill: Handle fill color
  630. property HandleFill: TColor32 read FHandleFill write SetHandleFill;
  631. // HandleFrame: Handle frame/outline color
  632. property HandleFrame: TColor32 read FHandleFrame write SetHandleFrame;
  633. // HandleFrameSize: Width of handle frame/outline
  634. property HandleFrameSize: TFloat read FHandleFrameSize write SetHandleFrameSize;
  635. property FrameStipple: TArrayOfColor32 read FFrameStipplePattern write SetFrameStipple;
  636. property FrameStippleStep: TFloat read FFrameStippleStep write SetFrameStippleStep;
  637. property FrameStippleCounter: TFloat read FFrameStippleCounter write SetFrameStippleCounter;
  638. property Quantized: Integer read FQuantized write SetQuantized default 1;
  639. property QuantizeShiftToggle: TLayerShiftState read FQuantizeShiftToggle write FQuantizeShiftToggle default [ssAlt];
  640. property PassMouseToChild: TRubberbandPassMouse read FPassMouse;
  641. property ActiveHitTest: ILayerHitTest read FHitTest;
  642. property OnUserChange: TNotifyEvent read FOnUserChange write FOnUserChange;
  643. property OnHandleClicked: TRubberBandHandleEvent read FOnHandleClicked write FOnHandleClicked;
  644. property OnHandleMove: TRubberBandHandleMoveEvent read FOnHandleMove write FOnHandleMove;
  645. property OnHandleMoved: TRubberBandHandleEvent read FOnHandleMoved write FOnHandleMoved;
  646. property OnPaintHandle: TRubberBandPaintHandleEvent read FOnPaintHandle write FOnPaintHandle;
  647. property OnUpdateHandle: TRubberBandUpdateHandleEvent read FOnUpdateHandle write FOnUpdateHandle;
  648. end;
  649. type
  650. // Compas directions, counter clockwise, from 0 degress to 360.
  651. // Each one direction covers 45 degrees.
  652. // Used inside TCustomRubberBandLayer.GetCursor instead of the poorly ordered TRBDragState enum.
  653. TResizeDirection = (ResizeDirectionE, ResizeDirectionNE, ResizeDirectionN, ResizeDirectionNW,
  654. ResizeDirectionW, ResizeDirectionSW, ResizeDirectionS, ResizeDirectionSE);
  655. var
  656. // The TCustomRubberBandLayer resize handle cursors.
  657. // These are the values returned by TCustomRubberBandLayer.GetCursor
  658. DirectionCursors: array[TResizeDirection] of TCursor = (crSizeWE, crSizeNESW, crSizeNS, crSizeNWSE, crSizeWE, crSizeNESW, crSizeNS, crSizeNWSE);
  659. type
  660. TPolygonRubberbandLayer = class(TCustomRubberBandLayer)
  661. public
  662. property Vertices;
  663. end;
  664. //------------------------------------------------------------------------------
  665. //
  666. // TRubberbandLayer
  667. //
  668. //------------------------------------------------------------------------------
  669. // Rectangular rubber band selection design layer.
  670. //------------------------------------------------------------------------------
  671. type
  672. TRBDragState = (dsNone, dsMove, dsSizeL, dsSizeT, dsSizeR, dsSizeB, dsSizeTL, dsSizeTR, dsSizeBL, dsSizeBR);
  673. TRBHandles = set of (rhCenter, rhSides, rhCorners, rhFrame,
  674. rhNotLeftSide, rhNotRightSide, rhNotTopSide, rhNotBottomSide,
  675. rhNotTLCorner, rhNotTRCorner, rhNotBLCorner, rhNotBRCorner);
  676. TRBOptions = set of (roProportional, roConstrained, roQuantized);
  677. TRBResizingEvent = procedure(
  678. Sender: TObject;
  679. const OldLocation: TFloatRect;
  680. var NewLocation: TFloatRect;
  681. DragState: TRBDragState;
  682. Shift: TShiftState) of object;
  683. TRBConstrainEvent = TRBResizingEvent;
  684. const
  685. VertexToDragState: array[0..7] of TRBDragState =
  686. // 0 1 2
  687. // 7 3
  688. // 6 5 4
  689. (dsSizeTL, dsSizeT, dsSizeTR, dsSizeR, dsSizeBR, dsSizeB, dsSizeBL, dsSizeL);
  690. DragStateToVertex: array[TRBDragState] of integer = (-1, -1, 7, 1, 3, 5, 0, 2, 6, 4);
  691. type
  692. TValidDragStates = set of TRBDragState;
  693. TRubberbandLayer = class(TCustomRubberBandLayer)
  694. strict private
  695. FHandles: TRBHandles;
  696. FOptions: TRBOptions;
  697. FMinWidth: TFloat;
  698. FMaxHeight: TFloat;
  699. FMinHeight: TFloat;
  700. FMaxWidth: TFloat;
  701. FOnResizing: TRBResizingEvent;
  702. FOnConstrain: TRBConstrainEvent;
  703. protected
  704. FDragState: TRBDragState;
  705. FValidDragStates: TValidDragStates;
  706. protected
  707. procedure SetHandles(Value: TRBHandles);
  708. procedure SetOptions(const Value: TRBOptions);
  709. function GetValidDragStates: TValidDragStates;
  710. function CanQuantize: boolean; override;
  711. procedure DoSetLocation(const NewLocation: TFloatRect); override;
  712. function GetHitTest(const APosition: TPoint; AShift: TShiftState = []): ILayerHitTest; override;
  713. function GetHitTestCursor(const AHitTest: ILayerHitTest): TCursor; override;
  714. function IsFrameVisible: boolean; override;
  715. function IsVertexVisible(VertexIndex: integer): boolean; override;
  716. function AllowMove: boolean; override;
  717. procedure DrawFrame(Buffer: TBitmap32; const R: TRect); override;
  718. procedure DoUpdateFrame(Buffer: TBitmap32; const R: TRect); override;
  719. function ApplyOffset(const AHitTest: ILayerHitTest; AQuantize: boolean): boolean; override;
  720. procedure DoResizing(const OldLocation: TFloatRect; var NewLocation: TFloatRect; DragState: TRBDragState; Shift: TShiftState); virtual;
  721. procedure DoConstrain(const OldLocation: TFloatRect; var NewLocation: TFloatRect; DragState: TRBDragState; Shift: TShiftState); virtual;
  722. // Backward compatibility
  723. function GetDragState(X, Y: Integer): TRBDragState; overload; virtual; deprecated 'Use GetHitTest';
  724. procedure DoSetDragState(const Value: TRBDragState; const X, Y: Integer); overload;
  725. procedure SetDragState(const Value: TRBDragState); overload; deprecated 'Use SetHitTest';
  726. procedure SetDragState(const Value: TRBDragState; const X, Y: Integer); overload; deprecated 'Use SetHitTest';
  727. function GetHandleCursor(DragState: TRBDragState; Angle: integer): TCursor; virtual; // Deprecated
  728. public
  729. constructor Create(ALayerCollection: TLayerCollection); override;
  730. property Options: TRBOptions read FOptions write SetOptions;
  731. property Handles: TRBHandles read FHandles write SetHandles;
  732. property MaxHeight: TFloat read FMaxHeight write FMaxHeight;
  733. property MaxWidth: TFloat read FMaxWidth write FMaxWidth;
  734. property MinHeight: TFloat read FMinHeight write FMinHeight;
  735. property MinWidth: TFloat read FMinWidth write FMinWidth;
  736. property OnConstrain: TRBConstrainEvent read FOnConstrain write FOnConstrain;
  737. property OnResizing: TRBResizingEvent read FOnResizing write FOnResizing;
  738. end;
  739. //------------------------------------------------------------------------------
  740. //------------------------------------------------------------------------------
  741. //------------------------------------------------------------------------------
  742. implementation
  743. uses
  744. TypInfo,
  745. Types,
  746. GR32_Image,
  747. GR32_LowLevel,
  748. GR32_Math,
  749. GR32_Geometry,
  750. GR32_VectorUtils,
  751. GR32_Polygons,
  752. GR32_Resamplers,
  753. GR32_RepaintOpt;
  754. { mouse state mapping }
  755. const
  756. CStateMap: array [TMouseButton] of TLayerState =
  757. (lsMouseLeft, lsMouseRight, lsMouseMiddle
  758. {$IFDEF FPC}, lsMouseMiddle, lsMouseMiddle{$ENDIF});
  759. type
  760. TImage32Access = class(TCustomImage32);
  761. //------------------------------------------------------------------------------
  762. //
  763. // TLayerCollection
  764. //
  765. //------------------------------------------------------------------------------
  766. constructor TLayerCollection.Create(AOwner: TPersistent);
  767. begin
  768. inherited Create;
  769. FOwner := AOwner;
  770. FItems := TObjectList<TCustomLayer>.Create;
  771. FMouseEvents := True;
  772. end;
  773. destructor TLayerCollection.Destroy;
  774. begin
  775. FUpdateCount := 1; // disable update notification
  776. Clear;
  777. FItems.Free;
  778. FSubscribers.Free;
  779. inherited;
  780. end;
  781. function TLayerCollection.Add(ItemClass: TLayerClass): TCustomLayer;
  782. begin
  783. Result := ItemClass.Create(Self);
  784. Assert(Result.LayerCollection = Self);
  785. Result.Index := FItems.Count - 1;
  786. Notify(lnLayerAdded, Result, Result.Index);
  787. end;
  788. {$if defined(FPC) or (CompilerVersion > 29.0)}
  789. function TLayerCollection.Add<T>: T;
  790. begin
  791. Result := T(Add(T));
  792. end;
  793. {$ifend}
  794. procedure TLayerCollection.Assign(Source: TPersistent);
  795. var
  796. I: Integer;
  797. Item: TCustomLayer;
  798. begin
  799. if Source is TLayerCollection then
  800. begin
  801. BeginUpdate;
  802. try
  803. FItems.Clear;
  804. for I := 0 to TLayerCollection(Source).Count - 1 do
  805. begin
  806. Item := TLayerCollection(Source).Items[I];
  807. Add(TLayerClass(Item.ClassType)).Assign(Item);
  808. end;
  809. Changed;
  810. finally
  811. EndUpdate;
  812. end;
  813. end else
  814. inherited Assign(Source);
  815. end;
  816. procedure TLayerCollection.BeginUpdate;
  817. begin
  818. if FUpdateCount = 0 then
  819. Changing;
  820. Inc(FUpdateCount);
  821. end;
  822. procedure TLayerCollection.EndUpdate;
  823. begin
  824. Assert(FUpdateCount > 0, 'Unpaired EndUpdate');
  825. if FUpdateCount = 1 then
  826. begin
  827. if (FModified) and (Assigned(FOnChange)) then
  828. FOnChange(Self);
  829. FModified := False;
  830. end;
  831. Dec(FUpdateCount);
  832. end;
  833. procedure TLayerCollection.BeginLockUpdate;
  834. begin
  835. Inc(FLockUpdateCount);
  836. end;
  837. procedure TLayerCollection.EndLockUpdate;
  838. begin
  839. Dec(FLockUpdateCount);
  840. end;
  841. procedure TLayerCollection.Changed;
  842. begin
  843. if (FLockUpdateCount > 0) then
  844. exit;
  845. BeginUpdate;
  846. FModified := True;
  847. EndUpdate;
  848. end;
  849. procedure TLayerCollection.Changing;
  850. begin
  851. if Assigned(FOnChanging) then
  852. FOnChanging(Self);
  853. end;
  854. procedure TLayerCollection.Clear;
  855. var
  856. Item: TCustomLayer;
  857. begin
  858. BeginUpdate;
  859. try
  860. for Item in FItems.ToArray do // ToArray for stability
  861. Item.Visible := False;
  862. FItems.Clear;
  863. Notify(lnCleared, nil, 0);
  864. Changed;
  865. finally
  866. EndUpdate;
  867. end;
  868. end;
  869. procedure TLayerCollection.Delete(Index: Integer);
  870. begin
  871. // Hide layer so the area covered by it will be invalidated
  872. FItems[Index].Visible := False;
  873. FItems.Delete(Index);
  874. end;
  875. function TLayerCollection.FindLayerAtPos(X, Y: Integer; OptionsMask: Cardinal): TCustomLayer;
  876. var
  877. i: Integer;
  878. begin
  879. for i := FItems.Count-1 downto 0 do
  880. begin
  881. Result := Items[i];
  882. if (Result.LayerOptions and OptionsMask) = 0 then
  883. Continue; // skip to the next one
  884. if Result.HitTest(X, Y) then
  885. Exit;
  886. end;
  887. Result := nil;
  888. end;
  889. procedure TLayerCollection.GDIUpdate;
  890. begin
  891. if (FUpdateCount = 0) and Assigned(FOnGDIUpdate) then
  892. FOnGDIUpdate(Self);
  893. end;
  894. function TLayerCollection.GetCount: Integer;
  895. begin
  896. Result := FItems.Count;
  897. end;
  898. function TLayerCollection.GetEnumerator: TEnumerator<TCustomLayer>;
  899. begin
  900. Result := FItems.GetEnumerator;
  901. end;
  902. function TLayerCollection.GetItem(Index: Integer): TCustomLayer;
  903. begin
  904. Result := FItems[Index];
  905. end;
  906. function TLayerCollection.GetOwner: TPersistent;
  907. begin
  908. Result := FOwner;
  909. end;
  910. function TLayerCollection.IndexOf(Item: TCustomLayer): integer;
  911. begin
  912. Result := FItems.IndexOf(Item);
  913. end;
  914. function TLayerCollection.Insert(Index: Integer; ItemClass: TLayerClass): TCustomLayer;
  915. begin
  916. BeginUpdate;
  917. try
  918. Result := Add(ItemClass);
  919. Result.Index := Index;
  920. Notify(lnLayerInserted, Result, Index);
  921. Changed;
  922. finally
  923. EndUpdate;
  924. end;
  925. end;
  926. {$if defined(FPC) or (CompilerVersion > 29.0)}
  927. function TLayerCollection.Insert<T>(Index: Integer): T;
  928. begin
  929. Result := T(Insert(Index, T));
  930. end;
  931. {$ifend}
  932. procedure TLayerCollection.InsertItem(Item: TCustomLayer);
  933. var
  934. Index: Integer;
  935. begin
  936. // We are called from TCustomLayer.SetLayerCollection which should have already
  937. // set its LayerCollection
  938. Assert(Item.LayerCollection = Self);
  939. BeginUpdate;
  940. try
  941. Index := FItems.Add(Item);
  942. Notify(lnLayerAdded, Item, Index);
  943. Changed;
  944. finally
  945. EndUpdate;
  946. end;
  947. end;
  948. procedure TLayerCollection.ExtractItem(Item: TCustomLayer);
  949. var
  950. Index: Integer;
  951. begin
  952. Index := FItems.IndexOf(Item);
  953. if (Index = -1) then
  954. exit;
  955. // We are called from TCustomLayer.SetLayerCollection which should have already
  956. // nilled its LayerCollection
  957. Assert(Item.LayerCollection = nil);
  958. BeginUpdate;
  959. try
  960. FItems.Extract(Item);
  961. Notify(lnLayerDeleted, Item, Index);
  962. Changed;
  963. finally
  964. EndUpdate;
  965. end;
  966. end;
  967. function TLayerCollection.LocalToViewport(const APoint: TFloatPoint; AScaled: Boolean): TFloatPoint;
  968. var
  969. ScaleX, ScaleY, ShiftX, ShiftY: TFloat;
  970. begin
  971. if AScaled then
  972. begin
  973. GetViewportShift(ShiftX, ShiftY);
  974. GetViewportScale(ScaleX, ScaleY);
  975. Result.X := APoint.X * ScaleX + ShiftX;
  976. Result.Y := APoint.Y * ScaleY + ShiftY;
  977. end else
  978. Result := APoint;
  979. end;
  980. function TLayerCollection.LocalToViewport(const APoint: TPoint; AScaled: Boolean): TFloatPoint;
  981. begin
  982. Result := LocalToViewport(FloatPoint(APoint), AScaled);
  983. end;
  984. function TLayerCollection.ViewportToLocal(const APoint: TFloatPoint; AScaled: Boolean): TFloatPoint;
  985. var
  986. ScaleX, ScaleY, ShiftX, ShiftY: TFloat;
  987. begin
  988. if AScaled then
  989. begin
  990. GetViewportShift(ShiftX, ShiftY);
  991. GetViewportScale(ScaleX, ScaleY);
  992. Result.X := (APoint.X - ShiftX) / ScaleX;
  993. Result.Y := (APoint.Y - ShiftY) / ScaleY;
  994. end else
  995. Result := APoint;
  996. end;
  997. function TLayerCollection.ViewportToLocal(const APoint: TPoint; AScaled: Boolean): TFloatPoint;
  998. begin
  999. Result := ViewportToLocal(FloatPoint(APoint), AScaled);
  1000. end;
  1001. function TLayerCollection.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer): TCustomLayer;
  1002. begin
  1003. if (MouseListener <> nil) then
  1004. Result := MouseListener
  1005. else
  1006. Result := FindLayerAtPos(X, Y, LOB_MOUSE_EVENTS);
  1007. if (Result <> MouseListener) and ((Result = nil) or (Result.LayerOptions and LOB_NO_CAPTURE = 0)) then
  1008. MouseListener := Result; // capture the mouse
  1009. if (MouseListener <> nil) then
  1010. begin
  1011. Include(MouseListener.FLayerStates, CStateMap[Button]);
  1012. MouseListener.MouseDown(Button, Shift, X, Y);
  1013. end;
  1014. end;
  1015. function TLayerCollection.MouseMove(Shift: TShiftState; X, Y: Integer): TCustomLayer;
  1016. begin
  1017. Result := MouseListener;
  1018. if (Result = nil) then
  1019. Result := FindLayerAtPos(X, Y, LOB_MOUSE_EVENTS);
  1020. if (Result <> nil) then
  1021. Result.MouseMove(Shift, X, Y);
  1022. end;
  1023. function TLayerCollection.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer): TCustomLayer;
  1024. begin
  1025. Result := MouseListener;
  1026. if (Result = nil) then
  1027. Result := FindLayerAtPos(X, Y, LOB_MOUSE_EVENTS);
  1028. if (Result <> nil) then
  1029. begin
  1030. Exclude(Result.FLayerStates, CStateMap[Button]);
  1031. Result.MouseUp(Button, Shift, X, Y);
  1032. end;
  1033. if (MouseListener <> nil) and
  1034. (MouseListener.FLayerStates * [lsMouseLeft, lsMouseRight, lsMouseMiddle] = []) then
  1035. MouseListener := nil; // reset mouse capture
  1036. end;
  1037. procedure TLayerCollection.MoveItem(Item: TCustomLayer; NewIndex: Integer);
  1038. var
  1039. CurrentIndex: integer;
  1040. begin
  1041. if NewIndex < 0 then
  1042. NewIndex := 0;
  1043. if NewIndex >= Count then
  1044. NewIndex := Count-1;
  1045. CurrentIndex := Item.Index;
  1046. if (CurrentIndex = NewIndex) then
  1047. exit;
  1048. BeginUpdate;
  1049. try
  1050. FItems.Move(CurrentIndex, NewIndex);
  1051. if Item.Visible then
  1052. Changed;
  1053. finally
  1054. EndUpdate;
  1055. end;
  1056. end;
  1057. procedure TLayerCollection.Notify(Action: TLayerListNotification; Layer: TCustomLayer; Index: Integer);
  1058. var
  1059. i: integer;
  1060. LayerListNotification: ILayerListNotification;
  1061. begin
  1062. if (FSubscribers <> nil) then
  1063. for i := FSubscribers.Count-1 downto 0 do
  1064. if (Supports(FSubscribers[i], ILayerListNotification, LayerListNotification)) then
  1065. LayerListNotification.LayerListNotify(Layer, Action, Index);
  1066. if Assigned(FOnListNotify) then
  1067. FOnListNotify(Self, Action, Layer, Index);
  1068. end;
  1069. procedure TLayerCollection.SetItem(Index: Integer; Value: TCustomLayer);
  1070. begin
  1071. FItems[Index].Assign(Value);
  1072. end;
  1073. procedure TLayerCollection.SetMouseEvents(Value: Boolean);
  1074. begin
  1075. FMouseEvents := Value;
  1076. MouseListener := nil;
  1077. end;
  1078. procedure TLayerCollection.SetMouseListener(Value: TCustomLayer);
  1079. begin
  1080. if Value <> FMouseListener then
  1081. begin
  1082. if (FMouseListener <> nil) then
  1083. FMouseListener.FLayerStates := FMouseListener.FLayerStates - [lsMouseLeft, lsMouseRight, lsMouseMiddle];
  1084. FMouseListener := Value;
  1085. end;
  1086. end;
  1087. procedure TLayerCollection.Subscribe(const ASubscriber: IInterface);
  1088. begin
  1089. if (FSubscribers = nil) then
  1090. FSubscribers := TList<IInterface>.Create;
  1091. FSubscribers.Add(ASubscriber);
  1092. end;
  1093. procedure TLayerCollection.Unsubscribe(const ASubscriber: IInterface);
  1094. begin
  1095. if (FSubscribers <> nil) then
  1096. FSubscribers.Remove(ASubscriber);
  1097. end;
  1098. procedure TLayerCollection.DoUpdateArea(const Rect: TRect; const Info: Cardinal);
  1099. var
  1100. i: integer;
  1101. UpdateRectNotification: IUpdateRectNotification;
  1102. begin
  1103. if (FSubscribers <> nil) then
  1104. for i := FSubscribers.Count-1 downto 0 do
  1105. if (Supports(FSubscribers[i], IUpdateRectNotification, UpdateRectNotification)) then
  1106. UpdateRectNotification.AreaUpdated(Rect, Info);
  1107. if Assigned(FOnAreaUpdated) then
  1108. FOnAreaUpdated(Self, Rect, Info);
  1109. Changed;
  1110. end;
  1111. procedure TLayerCollection.DoUpdateLayer(Layer: TCustomLayer);
  1112. var
  1113. i: integer;
  1114. LayerUpdateNotification: ILayerUpdateNotification;
  1115. begin
  1116. if (FSubscribers <> nil) then
  1117. for i := FSubscribers.Count-1 downto 0 do
  1118. if (Supports(FSubscribers[i], ILayerUpdateNotification, LayerUpdateNotification)) then
  1119. LayerUpdateNotification.LayerUpdated(Layer);
  1120. if Assigned(FOnLayerUpdated) then
  1121. FOnLayerUpdated(Self, Layer);
  1122. Changed;
  1123. end;
  1124. procedure TLayerCollection.GetViewportScale(out ScaleX, ScaleY: TFloat);
  1125. begin
  1126. if Assigned(FOnGetViewportScale) then
  1127. FOnGetViewportScale(Self, ScaleX, ScaleY)
  1128. else
  1129. begin
  1130. ScaleX := 1;
  1131. ScaleY := 1;
  1132. end;
  1133. end;
  1134. procedure TLayerCollection.GetViewportShift(out ShiftX, ShiftY: TFloat);
  1135. begin
  1136. if Assigned(FOnGetViewportShift) then
  1137. FOnGetViewportShift(Self, ShiftX, ShiftY)
  1138. else
  1139. begin
  1140. ShiftX := 0;
  1141. ShiftY := 0;
  1142. end;
  1143. end;
  1144. //------------------------------------------------------------------------------
  1145. //
  1146. // TCustomLayer
  1147. //
  1148. //------------------------------------------------------------------------------
  1149. constructor TCustomLayer.Create(ALayerCollection: TLayerCollection);
  1150. begin
  1151. LayerCollection := ALayerCollection;
  1152. FLayerOptions := LOB_VISIBLE;
  1153. end;
  1154. destructor TCustomLayer.Destroy;
  1155. var
  1156. Subscriber: TCustomLayer;
  1157. begin
  1158. if (FFreeNotifies <> nil) then
  1159. begin
  1160. for Subscriber in FFreeNotifies.ToArray do // ToArray for stability while items are removed from the list
  1161. Subscriber.FreeNotification(Self);
  1162. // List might have been freed while we looped but Free can handle that
  1163. FFreeNotifies.Free;
  1164. FFreeNotifies := nil;
  1165. end;
  1166. SetLayerCollection(nil);
  1167. inherited;
  1168. end;
  1169. //------------------------------------------------------------------------------
  1170. procedure TCustomLayer.BeforeDestruction;
  1171. begin
  1172. if Assigned(FOnDestroy) then
  1173. FOnDestroy(Self);
  1174. inherited;
  1175. end;
  1176. //------------------------------------------------------------------------------
  1177. procedure TCustomLayer.AddFreeNotification(ALayer: TCustomLayer);
  1178. begin
  1179. if (FFreeNotifies = nil) then
  1180. FFreeNotifies := TList<TCustomLayer>.Create;
  1181. if not FFreeNotifies.Contains(ALayer) then
  1182. FFreeNotifies.Add(ALayer);
  1183. end;
  1184. procedure TCustomLayer.RemoveFreeNotification(ALayer: TCustomLayer);
  1185. begin
  1186. if (FFreeNotifies = nil) then
  1187. exit;
  1188. FFreeNotifies.Remove(ALayer);
  1189. if FFreeNotifies.Count = 0 then
  1190. begin
  1191. FFreeNotifies.Free;
  1192. FFreeNotifies := nil;
  1193. end;
  1194. end;
  1195. procedure TCustomLayer.FreeNotification(ALayer: TCustomLayer);
  1196. begin
  1197. // do nothing by default
  1198. end;
  1199. procedure TCustomLayer.AddNotification(ALayer: TCustomLayer);
  1200. begin
  1201. AddFreeNotification(ALayer);
  1202. end;
  1203. procedure TCustomLayer.RemoveNotification(ALayer: TCustomLayer);
  1204. begin
  1205. RemoveFreeNotification(ALayer);
  1206. end;
  1207. //------------------------------------------------------------------------------
  1208. procedure TCustomLayer.Notification(ALayer: TCustomLayer);
  1209. begin
  1210. end;
  1211. //------------------------------------------------------------------------------
  1212. procedure TCustomLayer.DoChanged;
  1213. begin
  1214. if (FLayerCollection <> nil) and (FLayerOptions and LOB_NO_UPDATE = 0) then
  1215. begin
  1216. Update;
  1217. if Visible then
  1218. FLayerCollection.Changed
  1219. else
  1220. if (FLayerOptions and LOB_GDI_OVERLAY <> 0) then
  1221. FLayerCollection.GDIUpdate;
  1222. // We use FPendingForceUpdate to handle the situation where
  1223. // ForceUpdate is set during a batched update and thus suprepressed.
  1224. // When FPendingForceUpdate=True then ForceUpdate will return True
  1225. // until FPendingForceUpdate has been reset to False - which is what
  1226. // we do here once the updates have been processed.
  1227. FPendingForceUpdate := False;
  1228. inherited;
  1229. end;
  1230. end;
  1231. procedure TCustomLayer.Changed(const Rect: TRect; const Info: Cardinal);
  1232. begin
  1233. if (UpdateCount > 0) then
  1234. begin
  1235. Changed; // Ensure modified flag is set
  1236. Exit;
  1237. end;
  1238. if (FLayerCollection <> nil) and (FLayerOptions and LOB_NO_UPDATE = 0) then
  1239. begin
  1240. AreaUpdated(Rect, Info);
  1241. inherited DoChanged;
  1242. end;
  1243. end;
  1244. procedure TCustomLayer.Changing;
  1245. begin
  1246. if (LockUpdateCount > 0) then
  1247. Exit;
  1248. if (UpdateCount > 0) then
  1249. Exit;
  1250. if Visible and (FLayerCollection <> nil) and (FLayerOptions and LOB_NO_UPDATE = 0) then
  1251. FLayerCollection.Changing;
  1252. end;
  1253. //------------------------------------------------------------------------------
  1254. procedure TCustomLayer.BringToFront;
  1255. begin
  1256. Index := LayerCollection.Count;
  1257. end;
  1258. procedure TCustomLayer.SendToBack;
  1259. begin
  1260. Index := 0;
  1261. end;
  1262. //------------------------------------------------------------------------------
  1263. procedure TCustomLayer.Click;
  1264. begin
  1265. FClicked := False;
  1266. if Assigned(FOnClick) then
  1267. FOnClick(Self);
  1268. end;
  1269. procedure TCustomLayer.DblClick;
  1270. begin
  1271. FClicked := False;
  1272. if Assigned(FOnDblClick) then
  1273. FOnDblClick(Self);
  1274. end;
  1275. procedure TCustomLayer.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  1276. begin
  1277. if (Button = mbLeft) then
  1278. begin
  1279. if (ssDouble in Shift) then
  1280. DblClick
  1281. else
  1282. FClicked := True;
  1283. end;
  1284. if Assigned(FOnMouseDown) then
  1285. FOnMouseDown(Self, Button, Shift, X, Y);
  1286. end;
  1287. procedure TCustomLayer.MouseEnter;
  1288. begin
  1289. end;
  1290. procedure TCustomLayer.MouseLeave;
  1291. begin
  1292. end;
  1293. procedure TCustomLayer.MouseMove(Shift: TShiftState; X, Y: Integer);
  1294. begin
  1295. Screen.Cursor := Cursor;
  1296. if Assigned(FOnMouseMove) then
  1297. FOnMouseMove(Self, Shift, X, Y);
  1298. end;
  1299. procedure TCustomLayer.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  1300. begin
  1301. Screen.Cursor := crDefault;
  1302. if (Button = mbLeft) and FClicked then
  1303. Click;
  1304. if Assigned(FOnMouseUp) then
  1305. FOnMouseUp(Self, Button, Shift, X, Y);
  1306. end;
  1307. //------------------------------------------------------------------------------
  1308. procedure TCustomLayer.KeyDown(var Key: Word; Shift: TShiftState);
  1309. begin
  1310. if (Assigned(FOnKeyDown)) then
  1311. FOnKeyDown(Self, Key, Shift);
  1312. end;
  1313. procedure TCustomLayer.KeyUp(var Key: Word; Shift: TShiftState);
  1314. begin
  1315. if (Assigned(FOnKeyUp)) then
  1316. FOnKeyUp(Self, Key, Shift);
  1317. end;
  1318. //------------------------------------------------------------------------------
  1319. function TCustomLayer.DoHitTest(X, Y: Integer): Boolean;
  1320. begin
  1321. Result := Visible;
  1322. end;
  1323. procedure TCustomLayer.DoPaint(Buffer: TBitmap32);
  1324. begin
  1325. Paint(Buffer);
  1326. if Assigned(FOnPaint) then
  1327. FOnPaint(Self, Buffer);
  1328. end;
  1329. function TCustomLayer.GetIndex: Integer;
  1330. begin
  1331. if (FLayerCollection <> nil) then
  1332. Result := FLayerCollection.IndexOf(Self)
  1333. else
  1334. Result := -1;
  1335. end;
  1336. function TCustomLayer.GetMouseEvents: Boolean;
  1337. begin
  1338. Result := (FLayerOptions and LOB_MOUSE_EVENTS <> 0);
  1339. end;
  1340. function TCustomLayer.GetOwner: TPersistent;
  1341. begin
  1342. Result := FLayerCollection;
  1343. end;
  1344. function TCustomLayer.GetVisible: Boolean;
  1345. begin
  1346. Result := (FLayerOptions and LOB_VISIBLE <> 0);
  1347. end;
  1348. function TCustomLayer.HitTest(X, Y: Integer): Boolean;
  1349. begin
  1350. Result := DoHitTest(X, Y);
  1351. if Assigned(FOnHitTest) then
  1352. FOnHitTest(Self, X, Y, Result);
  1353. end;
  1354. //------------------------------------------------------------------------------
  1355. function TCustomLayer.ControlToLayer(const p: TPoint): TPoint;
  1356. begin
  1357. Result := p;
  1358. end;
  1359. function TCustomLayer.ControlToLayer(const r: TRect): TRect;
  1360. begin
  1361. Result := r;
  1362. end;
  1363. function TCustomLayer.ControlToLayer(const r: TFloatRect): TFloatRect;
  1364. begin
  1365. Result := r;
  1366. end;
  1367. function TCustomLayer.ControlToLayer(const p: TFloatPoint): TFloatPoint;
  1368. begin
  1369. Result := p;
  1370. end;
  1371. //------------------------------------------------------------------------------
  1372. function TCustomLayer.LayerToControl(const r: TRect): TRect;
  1373. begin
  1374. Result := r;
  1375. end;
  1376. function TCustomLayer.LayerToControl(const p: TPoint): TPoint;
  1377. begin
  1378. Result := p;
  1379. end;
  1380. function TCustomLayer.LayerToControl(const p: TFloatPoint): TFloatPoint;
  1381. begin
  1382. Result := p;
  1383. end;
  1384. function TCustomLayer.LayerToControl(const r: TFloatRect): TFloatRect;
  1385. begin
  1386. Result := r;
  1387. end;
  1388. //------------------------------------------------------------------------------
  1389. function TCustomLayer.ContentToLayer(const APoint: TPoint): TPoint;
  1390. begin
  1391. Result := APoint;
  1392. end;
  1393. function TCustomLayer.ContentToLayer(const APoint: TFloatPoint): TFloatPoint;
  1394. begin
  1395. Result := APoint;
  1396. end;
  1397. function TCustomLayer.LayerToContent(const APoint: TPoint): TPoint;
  1398. begin
  1399. Result := APoint;
  1400. end;
  1401. function TCustomLayer.LayerToContent(const APoint: TFloatPoint): TFloatPoint;
  1402. begin
  1403. Result := APoint;
  1404. end;
  1405. //------------------------------------------------------------------------------
  1406. procedure TCustomLayer.Paint(Buffer: TBitmap32);
  1407. begin
  1408. // descendants override this method
  1409. end;
  1410. procedure TCustomLayer.PaintGDI(Canvas: TCanvas);
  1411. begin
  1412. // descendants override this method
  1413. end;
  1414. procedure TCustomLayer.SetAsMouseListener;
  1415. begin
  1416. FLayerCollection.MouseListener := Self;
  1417. Screen.Cursor := Cursor;
  1418. end;
  1419. procedure TCustomLayer.SetCursor(Value: TCursor);
  1420. begin
  1421. if Value <> FCursor then
  1422. begin
  1423. FCursor := Value;
  1424. if FLayerCollection.MouseListener = Self then
  1425. Screen.Cursor := Value;
  1426. end;
  1427. end;
  1428. procedure TCustomLayer.SetIndex(Value: Integer);
  1429. begin
  1430. if (FLayerCollection = nil) then
  1431. exit;
  1432. FLayerCollection.MoveItem(Self, Value);
  1433. end;
  1434. procedure TCustomLayer.SetLayerCollection(Value: TLayerCollection);
  1435. var
  1436. OldLayerCollection: TLayerCollection;
  1437. begin
  1438. if (FLayerCollection = Value) then
  1439. exit;
  1440. OldLayerCollection := FLayerCollection;
  1441. FLayerCollection := nil; // Prevent recursion
  1442. if (OldLayerCollection <> nil) then
  1443. begin
  1444. if OldLayerCollection.MouseListener = Self then
  1445. OldLayerCollection.MouseListener := nil;
  1446. OldLayerCollection.ExtractItem(Self);
  1447. end;
  1448. FLayerCollection := Value;
  1449. if (FLayerCollection <> nil) then
  1450. FLayerCollection.InsertItem(Self);
  1451. end;
  1452. procedure TCustomLayer.SetLayerOptions(Value: Cardinal);
  1453. var
  1454. LayerHiding: boolean;
  1455. begin
  1456. if (FLayerOptions = Value) then
  1457. exit;
  1458. LayerHiding := (FLayerOptions and LOB_VISIBLE <> 0) and (Value and LOB_VISIBLE = 0);
  1459. if (LayerHiding) then
  1460. ForceUpdate := True;
  1461. Changing;
  1462. FLayerOptions := Value;
  1463. Changed;
  1464. if (LayerHiding) then
  1465. ForceUpdate := False;
  1466. end;
  1467. procedure TCustomLayer.SetMouseEvents(Value: Boolean);
  1468. begin
  1469. if Value then
  1470. LayerOptions := LayerOptions or LOB_MOUSE_EVENTS
  1471. else
  1472. LayerOptions := LayerOptions and not LOB_MOUSE_EVENTS;
  1473. end;
  1474. procedure TCustomLayer.SetVisible(Value: Boolean);
  1475. begin
  1476. if Value then
  1477. LayerOptions := LayerOptions or LOB_VISIBLE
  1478. else
  1479. LayerOptions := LayerOptions and not LOB_VISIBLE;
  1480. end;
  1481. procedure TCustomLayer.Update;
  1482. begin
  1483. if (FLayerCollection <> nil) and (Visible or ForceUpdate) then
  1484. FLayerCollection.DoUpdateLayer(Self);
  1485. end;
  1486. procedure TCustomLayer.Update(const ARect: TRect);
  1487. begin
  1488. UpdateRect(ARect);
  1489. end;
  1490. procedure TCustomLayer.UpdateRect(const ARect: TRect);
  1491. begin
  1492. AreaUpdated(ARect, AREAINFO_RECT);
  1493. end;
  1494. procedure TCustomLayer.AreaUpdated(const AArea: TRect; const AInfo: Cardinal);
  1495. begin
  1496. // Note: Rect is in ViewPort coordinates
  1497. if (FLayerCollection = nil) then
  1498. exit;
  1499. if (Visible or ForceUpdate) then
  1500. FLayerCollection.DoUpdateArea(AArea, AInfo)
  1501. else
  1502. if (FLayerOptions and LOB_GDI_OVERLAY) <> 0 then
  1503. FLayerCollection.GDIUpdate;
  1504. end;
  1505. function TCustomLayer.GetInvalid: Boolean;
  1506. begin
  1507. Result := (LayerOptions and LOB_INVALID <> 0);
  1508. end;
  1509. procedure TCustomLayer.SetInvalid(Value: Boolean);
  1510. begin
  1511. // don't use LayerOptions here since this is internal and we don't want to
  1512. // trigger Changing and Changed as this will definitely cause a stack overflow.
  1513. if Value then
  1514. FLayerOptions := FLayerOptions or LOB_INVALID
  1515. else
  1516. FLayerOptions := FLayerOptions and not LOB_INVALID;
  1517. end;
  1518. function TCustomLayer.GetForceUpdate: Boolean;
  1519. begin
  1520. Result := (LayerOptions and LOB_FORCE_UPDATE <> 0) or FPendingForceUpdate;
  1521. end;
  1522. procedure TCustomLayer.SetForceUpdate(Value: Boolean);
  1523. begin
  1524. // don't use LayerOptions here since this is internal and we don't want to
  1525. // trigger Changing and Changed as this will definitely cause a stack overflow.
  1526. if Value then
  1527. begin
  1528. FLayerOptions := FLayerOptions or LOB_FORCE_UPDATE;
  1529. FPendingForceUpdate := True;
  1530. end else
  1531. FLayerOptions := FLayerOptions and not LOB_FORCE_UPDATE;
  1532. end;
  1533. //------------------------------------------------------------------------------
  1534. //
  1535. // TPositionedLayer
  1536. //
  1537. //------------------------------------------------------------------------------
  1538. constructor TPositionedLayer.Create(ALayerCollection: TLayerCollection);
  1539. begin
  1540. inherited;
  1541. with FLocation do
  1542. begin
  1543. Left := 0;
  1544. Top := 0;
  1545. Right := 64;
  1546. Bottom := 64;
  1547. end;
  1548. FLayerOptions := LOB_VISIBLE or LOB_MOUSE_EVENTS;
  1549. end;
  1550. //------------------------------------------------------------------------------
  1551. function TPositionedLayer.DoHitTest(X, Y: Integer): Boolean;
  1552. var
  1553. r: TFLoatRect;
  1554. begin
  1555. r := GetAdjustedRect(FLocation);
  1556. Result := (X >= r.Left) and (X < r.Right) and (Y >= r.Top) and (Y < r.Bottom) and
  1557. inherited DoHitTest(X, Y);
  1558. end;
  1559. procedure TPositionedLayer.DoSetLocation(const NewLocation: TFloatRect);
  1560. begin
  1561. FLocation := NewLocation;
  1562. end;
  1563. //------------------------------------------------------------------------------
  1564. function TPositionedLayer.GetAdjustedLocation: TFloatRect;
  1565. begin
  1566. Result := GetAdjustedRect(FLocation);
  1567. end;
  1568. function TPositionedLayer.GetAdjustedRect(const R: TFloatRect): TFloatRect;
  1569. var
  1570. ScaleX, ScaleY, ShiftX, ShiftY: TFloat;
  1571. begin
  1572. if Scaled and (LayerCollection <> nil) then
  1573. begin
  1574. LayerCollection.GetViewportScale(ScaleX, ScaleY);
  1575. Result.Left := R.Left * ScaleX;
  1576. Result.Top := R.Top * ScaleY;
  1577. Result.Right := R.Right * ScaleX;
  1578. Result.Bottom := R.Bottom * ScaleY;
  1579. LayerCollection.GetViewportShift(ShiftX, ShiftY);
  1580. Result.Offset(ShiftX, ShiftY);
  1581. end else
  1582. Result := R;
  1583. end;
  1584. //------------------------------------------------------------------------------
  1585. function TPositionedLayer.GetContentSize: TPoint;
  1586. begin
  1587. Result.X := 0;
  1588. Result.Y := 0;
  1589. end;
  1590. //------------------------------------------------------------------------------
  1591. function TPositionedLayer.ControlToLayer(const APoint: TPoint): TPoint;
  1592. begin
  1593. Result := GR32.Point(ControlToLayer(FloatPoint(APoint)));
  1594. end;
  1595. function TPositionedLayer.ControlToLayer(const ARect: TRect): TRect;
  1596. begin
  1597. Result := MakeRect(ControlToLayer(FloatRect(ARect)), rrOutside);
  1598. end;
  1599. function TPositionedLayer.ControlToLayer(const APoint: TFloatPoint): TFloatPoint;
  1600. var
  1601. ScaleX, ScaleY, ShiftX, ShiftY: TFloat;
  1602. begin
  1603. // Scaled=True: Coordinates must be scaled and translated
  1604. // Scaled=False: Coordinates must be translated (layer has same scale as control; 1:1)
  1605. if Scaled and (LayerCollection <> nil) then
  1606. begin
  1607. LayerCollection.GetViewportShift(ShiftX, ShiftY);
  1608. LayerCollection.GetViewportScale(ScaleX, ScaleY);
  1609. // Translate from control/buffer/viewport coordinates...
  1610. // ...to bitmap coordinates...
  1611. // ...and unscale...
  1612. // ...and finally to layer coordinates
  1613. Result.X := (APoint.X - ShiftX) / ScaleX - Location.Left;
  1614. Result.Y := (APoint.Y - ShiftY) / ScaleY - Location.Top;
  1615. end else
  1616. begin
  1617. Result.X := APoint.X - Location.Left;
  1618. Result.Y := APoint.Y - Location.Top;
  1619. end;
  1620. end;
  1621. function TPositionedLayer.ControlToLayer(const ARect: TFloatRect): TFloatRect;
  1622. var
  1623. ScaleX, ScaleY, ShiftX, ShiftY: TFloat;
  1624. begin
  1625. // Scaled=True: Coordinates must be scaled and translated
  1626. // Scaled=False: Coordinates must be translated (layer has same scale as control; 1:1)
  1627. if Scaled and (LayerCollection <> nil) then
  1628. begin
  1629. LayerCollection.GetViewportShift(ShiftX, ShiftY);
  1630. LayerCollection.GetViewportScale(ScaleX, ScaleY);
  1631. // Translate from control/buffer/viewport coordinates...
  1632. // ...to bitmap coordinates...
  1633. // ...and unscale...
  1634. // ...and finally to layer coordinates
  1635. Result.Left := (ARect.Left - ShiftX) / ScaleX - Location.Left;
  1636. Result.Right := (ARect.Right - ShiftX) / ScaleX - Location.Left;
  1637. Result.Top := (ARect.Top - ShiftY) / ScaleY - Location.Top;
  1638. Result.Bottom := (ARect.Bottom - ShiftY) / ScaleY - Location.Top;
  1639. end else
  1640. begin
  1641. Result.Left := ARect.Left - Location.Left;
  1642. Result.Right := ARect.Right - Location.Left;
  1643. Result.Top := ARect.Top - Location.Top;
  1644. Result.Bottom := ARect.Bottom - Location.Top;
  1645. end;
  1646. end;
  1647. //------------------------------------------------------------------------------
  1648. function TPositionedLayer.LayerToControl(const ARect: TRect): TRect;
  1649. begin
  1650. Result := MakeRect(LayerToControl(FloatRect(ARect)), rrOutside);
  1651. end;
  1652. function TPositionedLayer.LayerToControl(const APoint: TPoint): TPoint;
  1653. begin
  1654. Result := GR32.Point(LayerToControl(FloatPoint(APoint)));
  1655. end;
  1656. function TPositionedLayer.LayerToControl(const APoint: TFloatPoint): TFloatPoint;
  1657. var
  1658. ScaleX, ScaleY, ShiftX, ShiftY: TFloat;
  1659. begin
  1660. // Scaled=True: Coordinates must be scaled and translated
  1661. // Scaled=False: Coordinates must be translated (layer has same scale as control; 1:1)
  1662. if Scaled and (LayerCollection <> nil) then
  1663. begin
  1664. LayerCollection.GetViewportShift(ShiftX, ShiftY);
  1665. LayerCollection.GetViewportScale(ScaleX, ScaleY);
  1666. // Translate from layer coordinates to control/buffer/viewport
  1667. Result.X := (APoint.X + Location.Left) * ScaleX + ShiftX;
  1668. Result.Y := (APoint.Y + Location.Top) * ScaleY + ShiftY;
  1669. end else
  1670. begin
  1671. Result.X := APoint.X + Location.Left;
  1672. Result.Y := APoint.Y + Location.Top;
  1673. end;
  1674. end;
  1675. function TPositionedLayer.LayerToControl(const ARect: TFloatRect): TFloatRect;
  1676. var
  1677. ScaleX, ScaleY, ShiftX, ShiftY: TFloat;
  1678. begin
  1679. // Scaled=True: Coordinates must be scaled and translated
  1680. // Scaled=False: Coordinates must be translated (layer has same scale as control; 1:1)
  1681. if Scaled and (LayerCollection <> nil) then
  1682. begin
  1683. LayerCollection.GetViewportShift(ShiftX, ShiftY);
  1684. LayerCollection.GetViewportScale(ScaleX, ScaleY);
  1685. // Translate from layer coordinates to control/buffer/viewport
  1686. Result.Left := (ARect.Left + Location.Left) * ScaleX + ShiftX;
  1687. Result.Right := (ARect.Right + Location.Left) * ScaleX + ShiftX;
  1688. Result.Top := (ARect.Top + Location.Top) * ScaleY + ShiftY;
  1689. Result.Bottom := (ARect.Bottom + Location.Top) * ScaleY + ShiftY;
  1690. end else
  1691. begin
  1692. Result.Left := ARect.Left + Location.Left;
  1693. Result.Right := ARect.Right + Location.Left;
  1694. Result.Top := ARect.Top + Location.Top;
  1695. Result.Bottom := ARect.Bottom + Location.Top;
  1696. end;
  1697. end;
  1698. //------------------------------------------------------------------------------
  1699. function TPositionedLayer.ContentToLayer(const APoint: TPoint): TPoint;
  1700. begin
  1701. Result := GR32.Point(ContentToLayer(FloatPoint(APoint)));
  1702. end;
  1703. function TPositionedLayer.ContentToLayer(const APoint: TFloatPoint): TFloatPoint;
  1704. var
  1705. Size: TPoint;
  1706. LayerWidth, LayerHeight: TFloat;
  1707. begin
  1708. Result := APoint;
  1709. Size := GetContentSize;
  1710. if (Size.IsZero) then
  1711. Exit;
  1712. LayerWidth := Location.Width;
  1713. LayerHeight := Location.Height;
  1714. if (LayerWidth > 0.5) and (LayerHeight > 0.5) and
  1715. ((Size.X <> LayerWidth) or (Size.Y <> LayerHeight)) then
  1716. begin
  1717. Result.X := Result.X * LayerWidth / Size.X;
  1718. Result.Y := Result.Y * LayerHeight / Size.Y;
  1719. end;
  1720. end;
  1721. function TPositionedLayer.LayerToContent(const APoint: TPoint): TPoint;
  1722. begin
  1723. Result := GR32.Point(LayerToContent(FloatPoint(APoint)));
  1724. end;
  1725. function TPositionedLayer.LayerToContent(const APoint: TFloatPoint): TFloatPoint;
  1726. var
  1727. Size: TPoint;
  1728. LayerWidth, LayerHeight: TFloat;
  1729. begin
  1730. Result := APoint;
  1731. Size := GetContentSize;
  1732. if (Size.IsZero) then
  1733. Exit;
  1734. LayerWidth := Location.Width;
  1735. LayerHeight := Location.Height;
  1736. if (LayerWidth > 0.5) and (LayerHeight > 0.5) and
  1737. ((Size.X <> LayerWidth) or (Size.Y <> LayerHeight)) then
  1738. begin
  1739. Result.X := Result.X * Size.X / LayerWidth;
  1740. Result.Y := Result.Y * Size.Y / LayerHeight;
  1741. end;
  1742. end;
  1743. //------------------------------------------------------------------------------
  1744. function TPositionedLayer.DoGetUpdateRect: TRect;
  1745. begin
  1746. // Note: Result is in ViewPort coordinates
  1747. Result := MakeRect(GetAdjustedLocation, rrOutside);
  1748. end;
  1749. function TPositionedLayer.GetUpdateRect: TRect;
  1750. begin
  1751. Result := DoGetUpdateRect;
  1752. if (Assigned(FOnGetUpdateRect)) then
  1753. FOnGetUpdateRect(Self, Result);
  1754. end;
  1755. procedure TPositionedLayer.SetLocation(const Value: TFloatRect);
  1756. begin
  1757. if (GR32.EqualRect(Value, FLocation)) then
  1758. exit;
  1759. Changing;
  1760. // Invalidate old location
  1761. if (LayerCollection <> nil) and (LayerOptions and LOB_NO_UPDATE = 0) then
  1762. Update;
  1763. DoSetLocation(Value);
  1764. // Invalidate new location
  1765. Changed;
  1766. end;
  1767. function TPositionedLayer.GetScaled: Boolean;
  1768. begin
  1769. Result := FScaled;
  1770. end;
  1771. procedure TPositionedLayer.SetScaled(Value: Boolean);
  1772. begin
  1773. if (Value = FScaled) then
  1774. exit;
  1775. // Changing Scaled can change size and position so treat it as if we did
  1776. Changing;
  1777. // Invalidate old location
  1778. if (LayerCollection <> nil) and (LayerOptions and LOB_NO_UPDATE = 0) then
  1779. Update;
  1780. FScaled := Value;
  1781. // Invalidate new location
  1782. Changed;
  1783. end;
  1784. procedure TPositionedLayer.Update;
  1785. begin
  1786. UpdateRect(GetUpdateRect);
  1787. end;
  1788. //------------------------------------------------------------------------------
  1789. //
  1790. // TCustomIndirectBitmapLayer
  1791. //
  1792. //------------------------------------------------------------------------------
  1793. constructor TCustomIndirectBitmapLayer.Create(ALayerCollection: TLayerCollection);
  1794. begin
  1795. inherited Create(ALayerCollection);
  1796. end;
  1797. constructor TCustomIndirectBitmapLayer.Create(ALayerCollection: TLayerCollection; ABitmap: TCustomBitmap32);
  1798. begin
  1799. inherited Create(ALayerCollection);
  1800. DoSetBitmap(ABitmap);
  1801. end;
  1802. destructor TCustomIndirectBitmapLayer.Destroy;
  1803. begin
  1804. if (OwnsBitmap) then
  1805. FreeAndNil(FBitmap)
  1806. else
  1807. DoSetBitmap(nil);
  1808. inherited;
  1809. end;
  1810. procedure TCustomIndirectBitmapLayer.BitmapAreaChanged(Sender: TObject; const Area: TRect; const Info: Cardinal);
  1811. var
  1812. T: TRect;
  1813. ScaleX, ScaleY: TFloat;
  1814. Width: Integer;
  1815. r: TFloatRect;
  1816. begin
  1817. if (FBitmap.Empty) then
  1818. Exit;
  1819. if (Area.Left = Area.Right) or (Area.Top = Area.Bottom) then // Don't use IsEmpty; Rect can be negative
  1820. Exit; // Empty area
  1821. if (LayerCollection = nil) or (LayerOptions and LOB_NO_UPDATE <> 0) then
  1822. exit;
  1823. // All the stuff below is in vain if updates are batched so bail early.
  1824. if (UpdateCount > 0) then
  1825. Exit;
  1826. r := GetAdjustedLocation;
  1827. ScaleX := r.Width / FBitmap.Width;
  1828. ScaleY := r.Height / FBitmap.Height;
  1829. // Common case: Positive rect
  1830. // More rare: Negative rect (e.g. line going from right to left)
  1831. if (Area.Left < Area.Right) then
  1832. begin
  1833. T.Left := Floor(r.Left + Area.Left * ScaleX);
  1834. T.Right := Ceil(r.Left + Area.Right * ScaleX);
  1835. end else
  1836. begin
  1837. T.Left := Ceil(r.Left + Area.Left * ScaleX);
  1838. T.Right := Floor(r.Left + Area.Right * ScaleX);
  1839. end;
  1840. if (Area.Top < Area.Bottom) then
  1841. begin
  1842. T.Top := Floor(r.Top + Area.Top * ScaleY);
  1843. T.Bottom := Ceil(r.Top + Area.Bottom * ScaleY);
  1844. end else
  1845. begin
  1846. T.Top := Ceil(r.Top + Area.Top * ScaleY);
  1847. T.Bottom := Floor(r.Top + Area.Bottom * ScaleY);
  1848. end;
  1849. // TODO : Possible scaling issue here; Should Width be scaled?
  1850. // See: TCustomImage32.BitmapAreaChangeHandler
  1851. Width := Ceil(FBitmap.Resampler.Width);
  1852. InflateArea(T, Width, Width);
  1853. Changed(T, Info);
  1854. end;
  1855. function TCustomIndirectBitmapLayer.DoHitTest(X, Y: Integer): Boolean;
  1856. var
  1857. BitmapX, BitmapY: Integer;
  1858. LayerWidth, LayerHeight: TFloat;
  1859. r: TFloatRect;
  1860. begin
  1861. Result := inherited DoHitTest(X, Y);
  1862. if (Result) and (AlphaHit) and (FBitmap <> nil) then
  1863. begin
  1864. r := GetAdjustedLocation;
  1865. LayerWidth := r.Width;
  1866. LayerHeight := r.Height;
  1867. if (LayerWidth < 0.5) or (LayerHeight < 0.5) then
  1868. Result := False
  1869. else
  1870. begin
  1871. // check the pixel alpha at (X, Y) position
  1872. BitmapX := Round((X - r.Left) * FBitmap.Width / LayerWidth);
  1873. BitmapY := Round((Y - r.Top) * FBitmap.Height / LayerHeight);
  1874. if (FBitmap.PixelS[BitmapX, BitmapY] and $FF000000 = 0) then
  1875. Result := False;
  1876. end;
  1877. end;
  1878. end;
  1879. procedure TCustomIndirectBitmapLayer.Paint(Buffer: TBitmap32);
  1880. var
  1881. SrcRect, DstRect, ClipRect, TempRect: TRect;
  1882. ImageRect: TRect;
  1883. begin
  1884. if (FBitmap = nil) or (FBitmap.Empty) then
  1885. Exit;
  1886. DstRect := MakeRect(GetAdjustedLocation);
  1887. ClipRect := Buffer.ClipRect;
  1888. GR32.IntersectRect(TempRect, ClipRect, DstRect);
  1889. if GR32.IsRectEmpty(TempRect) then
  1890. Exit;
  1891. SrcRect := MakeRect(0, 0, FBitmap.Width, FBitmap.Height);
  1892. if Cropped and (LayerCollection.Owner is TCustomImage32) and
  1893. not (TImage32Access(LayerCollection.Owner).PaintToMode) then
  1894. begin
  1895. if (DstRect.Width < 0.5) or (DstRect.Height < 0.5) then
  1896. Exit;
  1897. ImageRect := TCustomImage32(LayerCollection.Owner).GetBitmapRect;
  1898. GR32.IntersectRect(ClipRect, ClipRect, ImageRect);
  1899. end;
  1900. StretchTransfer(Buffer, DstRect, ClipRect, FBitmap, SrcRect, FBitmap.Resampler, FBitmap.DrawMode, FBitmap.OnPixelCombine);
  1901. end;
  1902. procedure TCustomIndirectBitmapLayer.DoSetBitmap(Value: TCustomBitmap32);
  1903. begin
  1904. if (Value = FBitmap) then
  1905. exit;
  1906. if (FBitmap <> nil) then
  1907. FBitmap.OnAreaChanged := nil;
  1908. FBitmap := Value;
  1909. if (FBitmap <> nil) then
  1910. FBitmap.OnAreaChanged := BitmapAreaChanged;
  1911. end;
  1912. function TCustomIndirectBitmapLayer.GetContentSize: TPoint;
  1913. begin
  1914. Result.X := Bitmap.Width;
  1915. Result.Y := Bitmap.Height;
  1916. end;
  1917. function TCustomIndirectBitmapLayer.OwnsBitmap: boolean;
  1918. begin
  1919. Result := False;
  1920. end;
  1921. procedure TCustomIndirectBitmapLayer.SetBitmap(Value: TCustomBitmap32);
  1922. begin
  1923. DoSetBitmap(Value);
  1924. Changed;
  1925. end;
  1926. procedure TCustomIndirectBitmapLayer.SetCropped(Value: Boolean);
  1927. begin
  1928. if (Value <> FCropped) then
  1929. begin
  1930. FCropped := Value;
  1931. Changed;
  1932. end;
  1933. end;
  1934. //------------------------------------------------------------------------------
  1935. //
  1936. // TCustomBitmapLayer
  1937. //
  1938. //------------------------------------------------------------------------------
  1939. constructor TCustomBitmapLayer.Create(ALayerCollection: TLayerCollection);
  1940. var
  1941. LayerBitmap: TCustomBitmap32;
  1942. begin
  1943. LayerBitmap := CreateBitmap;
  1944. try
  1945. inherited Create(ALayerCollection, LayerBitmap);
  1946. except
  1947. if (Bitmap = nil) then
  1948. LayerBitmap.Free; // Free if we didn't take ownership of the bitmap
  1949. raise;
  1950. end;
  1951. end;
  1952. function TCustomBitmapLayer.OwnsBitmap: boolean;
  1953. begin
  1954. Result := True;
  1955. end;
  1956. function TCustomBitmapLayer.CreateBitmap: TCustomBitmap32;
  1957. begin
  1958. Result := GetBitmapClass.Create;
  1959. end;
  1960. procedure TCustomBitmapLayer.SetBitmap(Value: TCustomBitmap32);
  1961. begin
  1962. Bitmap.Assign(Value);
  1963. end;
  1964. //------------------------------------------------------------------------------
  1965. //
  1966. // TBitmapLayer
  1967. //
  1968. //------------------------------------------------------------------------------
  1969. function TBitmapLayer.GetBitmap: TBitmap32;
  1970. begin
  1971. Result := TBitmap32(inherited Bitmap);
  1972. end;
  1973. procedure TBitmapLayer.SetBitmap(Value: TBitmap32);
  1974. begin
  1975. inherited SetBitmap(Value);
  1976. end;
  1977. function TBitmapLayer.GetBitmapClass: TCustomBitmap32Class;
  1978. begin
  1979. Result := TBitmap32;
  1980. end;
  1981. //------------------------------------------------------------------------------
  1982. // TRubberbandPassMouse
  1983. //------------------------------------------------------------------------------
  1984. constructor TRubberbandPassMouse.Create(AOwner: TCustomRubberBandLayer);
  1985. begin
  1986. FOwner := AOwner;
  1987. FEnabled := False;
  1988. FToChild := False;
  1989. FLayerUnderCursor := False;
  1990. FCancelIfPassed := False;
  1991. end;
  1992. function TRubberbandPassMouse.GetChildUnderCursor(X, Y: Integer; Exclude: TPositionedLayer): TPositionedLayer;
  1993. var
  1994. Layer: TCustomLayer;
  1995. Index: Integer;
  1996. begin
  1997. Result := nil;
  1998. for Index := FOwner.LayerCollection.Count - 1 downto 0 do
  1999. begin
  2000. Layer := FOwner.LayerCollection[Index];
  2001. if (Layer <> Exclude) and
  2002. (Layer.LayerOptions and LOB_MOUSE_EVENTS <> 0) and
  2003. (Layer is TPositionedLayer) and Layer.HitTest(X, Y) then
  2004. begin
  2005. Result := TPositionedLayer(Layer);
  2006. Exit;
  2007. end;
  2008. end;
  2009. end;
  2010. //------------------------------------------------------------------------------
  2011. // ILayerHitTest and friends
  2012. //------------------------------------------------------------------------------
  2013. type
  2014. TLayerHitTest = class(TInterfacedObject, ILayerHitTest)
  2015. private
  2016. FStartLocation: TFloatRect;
  2017. FStartPosition: TPoint;
  2018. FCurrentPosition: TPoint;
  2019. FShift: TShiftState;
  2020. FCursor: integer;
  2021. private
  2022. // ILayerHitTest
  2023. function GetStartLocation: TFloatRect;
  2024. procedure SetStartLocation(const Value: TFloatRect);
  2025. function GetStartPosition: TPoint;
  2026. procedure SetCurrentPosition(const Value: TPoint);
  2027. function GetCurrentPosition: TPoint;
  2028. function GetShift: TShiftState;
  2029. procedure SetShift(Value: TShiftState);
  2030. function GetCursor: integer; virtual;
  2031. procedure SetCursor(Value: integer);
  2032. public
  2033. constructor Create(const AMousePosition: TPoint);
  2034. end;
  2035. constructor TLayerHitTest.Create(const AMousePosition: TPoint);
  2036. begin
  2037. inherited Create;
  2038. FStartPosition := AMousePosition;
  2039. FCurrentPosition := FStartPosition;
  2040. FCursor := crDefault;
  2041. end;
  2042. function TLayerHitTest.GetCursor: integer;
  2043. begin
  2044. Result := FCursor;
  2045. end;
  2046. function TLayerHitTest.GetCurrentPosition: TPoint;
  2047. begin
  2048. Result := FCurrentPosition;
  2049. end;
  2050. procedure TLayerHitTest.SetCursor(Value: integer);
  2051. begin
  2052. FCursor := Value;
  2053. end;
  2054. procedure TLayerHitTest.SetCurrentPosition(const Value: TPoint);
  2055. begin
  2056. FCurrentPosition := Value;
  2057. end;
  2058. procedure TLayerHitTest.SetShift(Value: TShiftState);
  2059. begin
  2060. FShift := Value;
  2061. end;
  2062. procedure TLayerHitTest.SetStartLocation(const Value: TFloatRect);
  2063. begin
  2064. FStartLocation := Value;
  2065. end;
  2066. function TLayerHitTest.GetStartLocation: TFloatRect;
  2067. begin
  2068. Result := FStartLocation;
  2069. end;
  2070. function TLayerHitTest.GetStartPosition: TPoint;
  2071. begin
  2072. Result := FStartPosition;
  2073. end;
  2074. function TLayerHitTest.GetShift: TShiftState;
  2075. begin
  2076. Result := FShift;
  2077. end;
  2078. type
  2079. TLayerHitTestVertex = class(TLayerHitTest, ILayerHitTestVertex)
  2080. private
  2081. FVertex: integer;
  2082. FStartValue: TFloatPoint;
  2083. private
  2084. // ILayerHitTestVertex
  2085. function GetVertex: integer;
  2086. procedure SetVertex(Value: integer);
  2087. function GetStartValue: TFloatPoint;
  2088. procedure SetStartValue(const Value: TFloatPoint);
  2089. public
  2090. constructor Create(const AMousePosition: TPoint; AVertex: integer; const AStartValue: TFloatPoint);
  2091. end;
  2092. constructor TLayerHitTestVertex.Create(const AMousePosition: TPoint; AVertex: integer; const AStartValue: TFloatPoint);
  2093. begin
  2094. inherited Create(AMousePosition);
  2095. FVertex := AVertex;
  2096. FStartValue := AStartValue;
  2097. end;
  2098. function TLayerHitTestVertex.GetStartValue: TFloatPoint;
  2099. begin
  2100. Result := FStartValue;
  2101. end;
  2102. function TLayerHitTestVertex.GetVertex: integer;
  2103. begin
  2104. Result := FVertex;
  2105. end;
  2106. procedure TLayerHitTestVertex.SetStartValue(const Value: TFloatPoint);
  2107. begin
  2108. FStartValue := Value;
  2109. end;
  2110. procedure TLayerHitTestVertex.SetVertex(Value: integer);
  2111. begin
  2112. FVertex := Value;
  2113. end;
  2114. type
  2115. TLayerHitTestMove = class(TLayerHitTest, ILayerHitTestMove)
  2116. end;
  2117. //------------------------------------------------------------------------------
  2118. //
  2119. // TCustomRubberBandLayer
  2120. //
  2121. //------------------------------------------------------------------------------
  2122. constructor TCustomRubberBandLayer.Create(ALayerCollection: TLayerCollection);
  2123. begin
  2124. inherited;
  2125. FHandleFrame := clBlack32;
  2126. FHandleFill := clWhite32;
  2127. FHandleSize := 3;
  2128. FHandleHitZone := 1; // Just a tiny bit to make it easier to hit the handle
  2129. FHandleFrameSize := 1;
  2130. FQuantized := 1;
  2131. FQuantizeShiftToggle := [ssAlt];
  2132. FLayerOptions := LOB_VISIBLE or LOB_MOUSE_EVENTS;
  2133. SetFrameStipple([clWhite32, clWhite32, clBlack32, clBlack32]);
  2134. FPassMouse := TRubberbandPassMouse.Create(Self);
  2135. FFrameStippleStep := 1;
  2136. FFrameStippleCounter := 0;
  2137. end;
  2138. destructor TCustomRubberBandLayer.Destroy;
  2139. begin
  2140. ChildLayer := nil;
  2141. FPassMouse.Free;
  2142. inherited;
  2143. end;
  2144. procedure TCustomRubberBandLayer.FreeNotification(ALayer: TCustomLayer);
  2145. begin
  2146. if ALayer = FChildLayer then
  2147. ChildLayer := nil;
  2148. end;
  2149. function TCustomRubberBandLayer.DoHitTest(X, Y: Integer): Boolean;
  2150. begin
  2151. if (Visible) then
  2152. Result := (GetHitTest(GR32.Point(X, Y)) <> nil)
  2153. else
  2154. Result := False;
  2155. end;
  2156. function TCustomRubberBandLayer.IsFrameVisible: boolean;
  2157. begin
  2158. Result := (Length(FFrameStipplePattern) > 0);
  2159. end;
  2160. function TCustomRubberBandLayer.CanQuantize: boolean;
  2161. begin
  2162. Result := (FQuantized > 0);
  2163. end;
  2164. function TCustomRubberBandLayer.ShouldQuantize(const AHitTest: ILayerHitTest): boolean;
  2165. begin
  2166. Result := (CanQuantize) and ((QuantizeShiftToggle = []) or (AHitTest.Shift * [ssShift, ssAlt, ssCtrl] <> QuantizeShiftToggle));
  2167. end;
  2168. function TCustomRubberBandLayer.IsVertexVisible(VertexIndex: integer): boolean;
  2169. begin
  2170. Result := (VertexIndex >= 0) and (VertexIndex <= High(Vertices));
  2171. end;
  2172. procedure TCustomRubberBandLayer.DoSetLocation(const NewLocation: TFloatRect);
  2173. var
  2174. i: integer;
  2175. Delta: TFloatPoint;
  2176. begin
  2177. // Save current location
  2178. Delta := Location.TopLeft;
  2179. // Set new location
  2180. inherited;
  2181. UpdateChildLayer;
  2182. // If the layer was moved...
  2183. if (Delta <> Location.TopLeft) then
  2184. begin
  2185. // Calculate how much we moved the layer
  2186. Delta := Location.TopLeft - Delta;
  2187. // Move all vertices along with layer
  2188. for i := 0 to High(FVertices) do
  2189. FVertices[i] := FVertices[i] + Delta;
  2190. Update;
  2191. end;
  2192. end;
  2193. function TCustomRubberBandLayer.GetScaled: Boolean;
  2194. begin
  2195. if (FChildLayer <> nil) then
  2196. Result := FChildLayer.Scaled
  2197. else
  2198. Result := inherited GetScaled;
  2199. end;
  2200. procedure TCustomRubberBandLayer.SetScaled(Value: Boolean);
  2201. begin
  2202. if (FChildLayer <> nil) then
  2203. FChildLayer.Scaled := Value
  2204. else
  2205. inherited SetScaled(Value);
  2206. end;
  2207. function TCustomRubberBandLayer.FindVertex(const APosition: TPoint): integer;
  2208. var
  2209. i: integer;
  2210. Pos: TFloatPoint;
  2211. HitZone: TFloatPoint;
  2212. ScaleX, ScaleY: TFloat;
  2213. begin
  2214. // If layer has Scaled=True then vertices are relative to bitmap,
  2215. // otherwise they are relative to control.
  2216. Pos := LayerCollection.ViewportToLocal(APosition, Scaled);
  2217. HitZone.X := FHandleSize + FHandleHitZone;
  2218. HitZone.Y := HitZone.X;
  2219. if (Scaled) and (LayerCollection <> nil) then
  2220. begin
  2221. LayerCollection.GetViewportScale(ScaleX, ScaleY);
  2222. HitZone.X := HitZone.X / ScaleX;
  2223. HitZone.Y := HitZone.Y / ScaleY;
  2224. end;
  2225. for i := 0 to High(Vertices) do
  2226. if (IsVertexVisible(i)) then
  2227. begin
  2228. if (Abs(Vertices[i].X - Pos.X) <= HitZone.X) and (Abs(Vertices[i].Y - Pos.Y) <= HitZone.Y) then
  2229. Exit(i);
  2230. end;
  2231. Result := -1;
  2232. end;
  2233. function TCustomRubberBandLayer.GetHitTest(const APosition: TPoint; AShift: TShiftState): ILayerHitTest;
  2234. var
  2235. Vertex: integer;
  2236. p: TFloatPoint;
  2237. begin
  2238. // APosition is in control coordinates
  2239. Result := nil;
  2240. Vertex := FindVertex(APosition);
  2241. if (Vertex <> -1) then
  2242. begin
  2243. Result := TLayerHitTestVertex.Create(APosition, Vertex, Vertices[Vertex]);
  2244. Result.Shift := AShift;
  2245. Result.Cursor := GetHitTestCursor(Result);
  2246. Result.StartLocation := Location;
  2247. end else
  2248. if AllowMove then
  2249. begin
  2250. // If layer has Scaled=True then vertices are relative to bitmap,
  2251. // otherwise they are relative to control.
  2252. p := LayerCollection.ViewportToLocal(APosition, Scaled);
  2253. if PointInPolygon(p, FVertices) then
  2254. begin
  2255. Result := TLayerHitTestMove.Create(APosition);
  2256. Result.Shift := AShift;
  2257. Result.Cursor := GetHitTestCursor(Result);
  2258. Result.StartLocation := Location;
  2259. end;
  2260. end;
  2261. end;
  2262. procedure TCustomRubberBandLayer.SetHitTest(const AHitTest: ILayerHitTest);
  2263. begin
  2264. FHitTest := AHitTest;
  2265. FIsDragging := (FHitTest <> nil); // For backward compatibility
  2266. end;
  2267. function TCustomRubberBandLayer.AllowMove: boolean;
  2268. begin
  2269. Result := True;
  2270. end;
  2271. procedure TCustomRubberBandLayer.ApplyHitTestCursor(const AHitTest: ILayerHitTest);
  2272. var
  2273. NewCursor: TCursor;
  2274. begin
  2275. NewCursor := crDefault;
  2276. if (AHitTest <> nil) then
  2277. NewCursor := AHitTest.Cursor;
  2278. if (NewCursor = crDefault) then
  2279. NewCursor := Cursor;
  2280. Screen.Cursor := NewCursor;
  2281. end;
  2282. function TCustomRubberBandLayer.GetHitTestCursor(const AHitTest: ILayerHitTest): TCursor;
  2283. var
  2284. HitTestVertex: ILayerHitTestVertex;
  2285. begin
  2286. Result := crDefault;
  2287. if (AHitTest <> nil) then
  2288. begin
  2289. if Supports(AHitTest, ILayerHitTestVertex, HitTestVertex) then
  2290. begin
  2291. if (IsVertexVisible(HitTestVertex.Vertex)) then
  2292. Result := crHandPoint;
  2293. end else
  2294. if Supports(AHitTest, ILayerHitTestMove) then
  2295. begin
  2296. if (AllowMove) then
  2297. Result := crSizeAll;
  2298. end;
  2299. end;
  2300. end;
  2301. function TCustomRubberBandLayer.ApplyOffset(const AHitTest: ILayerHitTest; AQuantize: boolean): boolean;
  2302. var
  2303. Delta: TFloatPoint;
  2304. ScaleX, ScaleY: TFloat;
  2305. NewLocation: TFloatRect;
  2306. HitTestVertex: ILayerHitTestVertex;
  2307. NewVertex: TFloatPoint;
  2308. begin
  2309. Result := False;
  2310. Delta := FloatPoint(AHitTest.CurrentPosition - AHitTest.StartPosition);
  2311. if Scaled then
  2312. begin
  2313. LayerCollection.GetViewportScale(ScaleX, ScaleY);
  2314. Delta.X := Delta.X / ScaleX;
  2315. Delta.Y := Delta.Y / ScaleY;
  2316. end;
  2317. (*
  2318. ** Move layer
  2319. *)
  2320. if Supports(AHitTest, ILayerHitTestMove) then
  2321. begin
  2322. // Apply delta/offset relative to start location
  2323. NewLocation := AHitTest.StartLocation;
  2324. if AQuantize then
  2325. begin
  2326. NewLocation.Left := Round((NewLocation.Left + Delta.X) / Quantized) * Quantized;
  2327. NewLocation.Top := Round((NewLocation.Top + Delta.Y) / Quantized) * Quantized;
  2328. end else
  2329. NewLocation.TopLeft := NewLocation.TopLeft + Delta;
  2330. DoHandleMove(-1, NewLocation.TopLeft);
  2331. // Set new loaction but keep old width/height
  2332. NewLocation.Right := NewLocation.Left + NewLocation.Width;
  2333. NewLocation.Bottom := NewLocation.Top + NewLocation.Height;
  2334. if (NewLocation <> Location) then
  2335. begin
  2336. Location := NewLocation;
  2337. Result := True;
  2338. end;
  2339. end else
  2340. (*
  2341. ** Move handle
  2342. *)
  2343. if Supports(AHitTest, ILayerHitTestVertex, HitTestVertex) then
  2344. begin
  2345. // Apply delta/offset relative to start vertex position
  2346. NewVertex := HitTestVertex.StartValue;
  2347. if AQuantize then
  2348. begin
  2349. // Quantize top/left and...
  2350. NewVertex.X := Round((NewVertex.X + Delta.X) / Quantized) * Quantized;
  2351. NewVertex.Y := Round((NewVertex.Y + Delta.Y) / Quantized) * Quantized;
  2352. end else
  2353. NewVertex := NewVertex + Delta;
  2354. DoHandleMove(HitTestVertex.Vertex, NewVertex);
  2355. if (NewVertex <> Vertices[HitTestVertex.Vertex]) then
  2356. begin
  2357. // Erase old, update, paint new
  2358. Vertex[HitTestVertex.Vertex] := NewVertex;
  2359. Result := True;
  2360. end;
  2361. end;
  2362. end;
  2363. procedure TCustomRubberBandLayer.DoHandleClicked(VertexIndex: integer);
  2364. begin
  2365. if (Assigned(FOnHandleClicked)) then
  2366. FOnHandleClicked(Self, VertexIndex);
  2367. end;
  2368. procedure TCustomRubberBandLayer.DoHandleMove(VertexIndex: integer; var APos: TFloatPoint);
  2369. begin
  2370. if (Assigned(FOnHandleMove)) then
  2371. FOnHandleMove(Self, VertexIndex, APos);
  2372. end;
  2373. procedure TCustomRubberBandLayer.DoHandleMoved(VertexIndex: integer);
  2374. begin
  2375. if (Assigned(FOnHandleMoved)) then
  2376. FOnHandleMoved(Self, VertexIndex);
  2377. end;
  2378. procedure TCustomRubberBandLayer.KeyDown(var Key: Word; Shift: TShiftState);
  2379. begin
  2380. inherited;
  2381. // Update hittest shift state
  2382. if (ActiveHitTest <> nil) and (ActiveHitTest.Shift <> Shift) and (LayerCollection.MouseListener = Self) then
  2383. // Generate mouse move
  2384. MouseMove(Shift, ActiveHitTest.CurrentPosition.X, ActiveHitTest.CurrentPosition.Y);
  2385. end;
  2386. procedure TCustomRubberBandLayer.KeyUp(var Key: Word; Shift: TShiftState);
  2387. begin
  2388. inherited;
  2389. // Update hittest shift state
  2390. if (ActiveHitTest <> nil) and (ActiveHitTest.Shift <> Shift) and (LayerCollection.MouseListener = Self) then
  2391. // Generate mouse move
  2392. MouseMove(Shift, ActiveHitTest.CurrentPosition.X, ActiveHitTest.CurrentPosition.Y);
  2393. end;
  2394. procedure TCustomRubberBandLayer.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  2395. var
  2396. PositionedLayer: TPositionedLayer;
  2397. HitTestVertex: ILayerHitTestVertex;
  2398. VertexIndex: integer;
  2399. NewHitTest: ILayerHitTest;
  2400. begin
  2401. // Pass mouse event to other layers...
  2402. if FPassMouse.Enabled then
  2403. begin
  2404. // First pass to child layer
  2405. if FPassMouse.ToChild and (ChildLayer <> nil) then
  2406. begin
  2407. ChildLayer.MouseDown(Button, Shift, X, Y);
  2408. if FPassMouse.CancelIfPassed then
  2409. Exit;
  2410. end;
  2411. // Then pass to layer under mouse cursor
  2412. if FPassMouse.ToLayerUnderCursor then
  2413. begin
  2414. PositionedLayer := FPassMouse.GetChildUnderCursor(X, Y, Self);
  2415. // ...unless it's the same as the child layer and we handled the child layer above
  2416. if (PositionedLayer <> nil) and ((not FPassMouse.ToChild) or (PositionedLayer <> ChildLayer)) then
  2417. begin
  2418. PositionedLayer.MouseDown(Button, Shift, X, Y);
  2419. if FPassMouse.CancelIfPassed then
  2420. Exit;
  2421. end;
  2422. end;
  2423. end;
  2424. if (ActiveHitTest <> nil) then
  2425. Exit;
  2426. // Create a new HitTest context
  2427. NewHitTest := GetHitTest(GR32.Point(X, Y), Shift);
  2428. SetHitTest(NewHitTest);
  2429. if (ActiveHitTest <> nil) then
  2430. begin
  2431. // Did we click a vertex/handle?
  2432. if (Supports(ActiveHitTest, ILayerHitTestVertex, HitTestVertex)) then
  2433. VertexIndex := HitTestVertex.Vertex
  2434. else
  2435. VertexIndex := -1;
  2436. // Generate an OnHandleClicked event
  2437. DoHandleClicked(VertexIndex);
  2438. end;
  2439. inherited;
  2440. end;
  2441. procedure TCustomRubberBandLayer.MouseMove(Shift: TShiftState; X, Y: Integer);
  2442. var
  2443. MoveHitTest: ILayerHitTest;
  2444. DoQuantize: Boolean;
  2445. HitTestVertex: ILayerHitTestVertex;
  2446. VertexIndex: integer;
  2447. begin
  2448. // If there's no active HitTest context then we're just moving the mouse, otherwise
  2449. // a drag is in progress.
  2450. if (ActiveHitTest = nil) then
  2451. begin
  2452. // Create a temporary HitTest context
  2453. MoveHitTest := GetHitTest(GR32.Point(X, Y), Shift);
  2454. // Use the HitTest context to update the cursor
  2455. ApplyHitTestCursor(MoveHitTest);
  2456. exit;
  2457. end;
  2458. // We are dragging; Update the HitTest context with the current state
  2459. ActiveHitTest.Shift := Shift;
  2460. ActiveHitTest.CurrentPosition := GR32.Point(X, Y);
  2461. // Use the HitTest context to update the cursor
  2462. ApplyHitTestCursor(ActiveHitTest);
  2463. // Determine if we should quantize the coordinates.
  2464. DoQuantize := ShouldQuantize(ActiveHitTest);
  2465. if ApplyOffset(ActiveHitTest, DoQuantize) then
  2466. begin
  2467. if (ActiveHitTest <> nil) then
  2468. begin
  2469. // Are we dragging a vertex/handle?
  2470. if (Supports(ActiveHitTest, ILayerHitTestVertex, HitTestVertex)) then
  2471. VertexIndex := HitTestVertex.Vertex
  2472. else
  2473. VertexIndex := -1;
  2474. // Generate an OnHandleMoved event
  2475. DoHandleMoved(VertexIndex);
  2476. end;
  2477. // Generate an OnUserChange event (backward compatibility)
  2478. if Assigned(FOnUserChange) then
  2479. FOnUserChange(Self);
  2480. end;
  2481. end;
  2482. procedure TCustomRubberBandLayer.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  2483. var
  2484. PositionedLayer: TPositionedLayer;
  2485. begin
  2486. // Pass mouse event to other layers...
  2487. if FPassMouse.Enabled then
  2488. begin
  2489. // First pass to child layer
  2490. if FPassMouse.ToChild and (ChildLayer <> nil) then
  2491. begin
  2492. ChildLayer.MouseUp(Button, Shift, X, Y);
  2493. if FPassMouse.CancelIfPassed then
  2494. Exit;
  2495. end;
  2496. // Then pass to layer under mouse cursor
  2497. if FPassMouse.ToLayerUnderCursor then
  2498. begin
  2499. PositionedLayer := FPassMouse.GetChildUnderCursor(X, Y, Self);
  2500. // ...unless it's the same as the child layer and we handled the child layer above
  2501. if (PositionedLayer <> nil) and ((not FPassMouse.ToChild) or (PositionedLayer <> ChildLayer)) then
  2502. begin
  2503. PositionedLayer.MouseUp(Button, Shift, X, Y);
  2504. if FPassMouse.CancelIfPassed then
  2505. Exit;
  2506. end;
  2507. end;
  2508. end;
  2509. SetHitTest(nil);
  2510. inherited;
  2511. end;
  2512. procedure TCustomRubberBandLayer.DrawHandle(Buffer: TBitmap32; const p: TFloatPoint; AIndex: integer; const DrawParams: TRubberBandHandleDrawParams);
  2513. function Diamond(const p: TFloatPoint; const Radius: TFloat): TArrayOfFloatPoint; {$IFDEF USEINLINING} inline; {$ENDIF}
  2514. begin
  2515. SetLength(Result, 4);
  2516. Result[0] := FloatPoint(p.X, p.Y - Radius);
  2517. Result[1] := FloatPoint(p.X + Radius, p.Y);
  2518. Result[2] := FloatPoint(p.X, p.Y + Radius);
  2519. Result[3] := FloatPoint(p.X - Radius, p.Y);
  2520. end;
  2521. var
  2522. Handle: TFloatRect;
  2523. HandleRect: TRect;
  2524. Shape: TArrayOfArrayOfFloatPoint;
  2525. Colors: array[0..1] of TColor32;
  2526. Renderer: TPolygonRenderer32VPR;
  2527. begin
  2528. if (DrawParams.HandleStyle = hsSquare) and (DrawParams.HandleFrameSize = 1.0) and (Frac(DrawParams.HandleSize) = 0.0) then
  2529. begin
  2530. // Simple 1px framed square
  2531. Handle := FloatRect(p, p);
  2532. GR32.InflateRect(Handle, DrawParams.HandleSize, DrawParams.HandleSize);
  2533. HandleRect := MakeRect(Handle, rrClosest);
  2534. if (AlphaComponent(DrawParams.HandleFrame) > 0) then
  2535. begin
  2536. Buffer.FrameRectTS(HandleRect, DrawParams.HandleFrame);
  2537. GR32.InflateRect(HandleRect, -1, -1);
  2538. end;
  2539. if (AlphaComponent(DrawParams.HandleFill) > 0) then
  2540. Buffer.FillRectTS(HandleRect, DrawParams.HandleFill);
  2541. exit;
  2542. end;
  2543. // Outer: Shape[0]
  2544. // Inner: Shape[1]
  2545. // Stroke: Shape[0]+Shape[1]
  2546. // Fill: Shape[1]
  2547. SetLength(Shape, 2);
  2548. case DrawParams.HandleStyle of
  2549. hsSquare:
  2550. begin
  2551. Handle := FloatRect(p, p);
  2552. GR32.InflateRect(Handle, DrawParams.HandleSize, DrawParams.HandleSize);
  2553. Shape[0] := Rectangle(Handle);
  2554. end;
  2555. hsCircle:
  2556. Shape[0] := Circle(p, DrawParams.HandleSize);
  2557. hsDiamond:
  2558. Shape[0] := Diamond(p, DrawParams.HandleSize);
  2559. end;
  2560. if (DrawParams.HandleFrameSize = DrawParams.HandleSize) then
  2561. begin
  2562. // Frame completely covers area
  2563. Shape[1] := Shape[0];
  2564. Shape[0] := nil;
  2565. Colors[1] := DrawParams.HandleFrame;
  2566. end else
  2567. if (DrawParams.HandleFrameSize > 0) then
  2568. begin
  2569. Shape[1] := ReversePolygon(Grow(Shape[0], -DrawParams.HandleFrameSize, jsBevel));
  2570. Colors[0] := DrawParams.HandleFrame;
  2571. Colors[1] := DrawParams.HandleFill;
  2572. end else
  2573. begin
  2574. // No frame
  2575. Shape[1] := Shape[0];
  2576. Shape[0] := nil;
  2577. Colors[1] := DrawParams.HandleFill;
  2578. end;
  2579. Renderer := TPolygonRenderer32VPR.Create(Buffer);
  2580. try
  2581. // Fill
  2582. if (Shape[1] <> nil) and (AlphaComponent(Colors[1]) > 0) then
  2583. begin
  2584. Renderer.Color := Colors[1];
  2585. Renderer.PolygonFS(Shape[1]);
  2586. end;
  2587. // Stroke
  2588. if (Shape[0] <> nil) and (AlphaComponent(Colors[0]) > 0) then
  2589. begin
  2590. Renderer.Color := Colors[0];
  2591. Renderer.PolyPolygonFS(Shape);
  2592. end;
  2593. finally
  2594. Renderer.Free;
  2595. end;
  2596. end;
  2597. procedure TCustomRubberBandLayer.DoDrawVertex(Buffer: TBitmap32; const R: TRect; VertexIndex: integer);
  2598. var
  2599. p: TFloatPoint;
  2600. DrawParams: TRubberBandHandleDrawParams;
  2601. Handled: boolean;
  2602. begin
  2603. // Coordinate specifies exact center of handle. I.e. center of
  2604. // pixel if handle is odd number of pixels wide.
  2605. p := LayerCollection.LocalToViewport(FVertices[VertexIndex], Scaled);
  2606. DrawParams.HandleStyle := HandleStyle;
  2607. DrawParams.HandleSize := HandleSize;
  2608. DrawParams.HandleFill := HandleFill;
  2609. DrawParams.HandleFrame := HandleFrame;
  2610. DrawParams.HandleFrameSize := HandleFrameSize;
  2611. Handled := False;
  2612. if Assigned(FOnPaintHandle) then
  2613. FOnPaintHandle(Self, Buffer, p, VertexIndex, DrawParams, Handled);
  2614. if (not Handled) then
  2615. DrawHandle(Buffer, p, VertexIndex, DrawParams);
  2616. end;
  2617. procedure TCustomRubberBandLayer.DoDrawVertices(Buffer: TBitmap32; const R: TRect; var Handled: boolean);
  2618. var
  2619. i: integer;
  2620. begin
  2621. for i := 0 to High(FVertices) do
  2622. if (IsVertexVisible(i)) then
  2623. DoDrawVertex(Buffer, R, i);
  2624. Handled := True;
  2625. end;
  2626. procedure TCustomRubberBandLayer.DrawFrame(Buffer: TBitmap32; const R: TRect);
  2627. var
  2628. i: integer;
  2629. p: TFloatPoint;
  2630. begin
  2631. if (Length(FVertices) = 0) then
  2632. exit;
  2633. Buffer.SetStipple(FrameStipple);
  2634. Buffer.StippleStep := FrameStippleStep;
  2635. Buffer.StippleCounter := FrameStippleCounter;
  2636. p := LayerCollection.LocalToViewport(FVertices[High(FVertices)], Scaled);
  2637. Buffer.MoveToF(p.X, p.Y);
  2638. for i := 0 to High(FVertices) do
  2639. begin
  2640. p := LayerCollection.LocalToViewport(FVertices[i], Scaled);
  2641. Buffer.LineToFSP(p.X, p.Y);
  2642. end;
  2643. end;
  2644. procedure TCustomRubberBandLayer.DoUpdateFrame(Buffer: TBitmap32; const R: TRect);
  2645. var
  2646. ScaleX, ScaleY, ShiftX, ShiftY: TFloat;
  2647. DoScale: boolean;
  2648. i: integer;
  2649. Index: integer;
  2650. Segment: TFloatRect;
  2651. LineRect: TRect;
  2652. begin
  2653. if (Length(FVertices) = 0) then
  2654. exit;
  2655. if (Scaled) and (LayerCollection <> nil) then
  2656. begin
  2657. LayerCollection.GetViewportShift(ShiftX, ShiftY);
  2658. LayerCollection.GetViewportScale(ScaleX, ScaleY);
  2659. DoScale := True;
  2660. end else
  2661. DoScale := False;
  2662. for i := 0 to Length(FVertices) do // Note: Upper bound is Length(FVertices) on purpose
  2663. begin
  2664. Index := i mod Length(FVertices);
  2665. // Same as: LayerCollection.LocalToViewport(FVertices[i], Scaled)
  2666. if (DoScale) then
  2667. begin
  2668. Segment.Right := FVertices[Index].X * ScaleX + ShiftX;
  2669. Segment.Bottom := FVertices[Index].Y * ScaleY + ShiftY;
  2670. end else
  2671. Segment.BottomRight := FVertices[Index];
  2672. if (i > 0) then
  2673. begin
  2674. // Invalidate segment
  2675. LineRect := MakeRect(Segment, rrOutside);
  2676. Changed(LineRect, AREAINFO_LINE + 1);
  2677. end;
  2678. Segment.TopLeft := Segment.BottomRight;
  2679. end;
  2680. end;
  2681. procedure TCustomRubberBandLayer.DoUpdateVertex(Buffer: TBitmap32; const R: TRect; VertexIndex: integer);
  2682. var
  2683. p: TFloatPoint;
  2684. Handle: TFloatRect;
  2685. HandleRect: TRect;
  2686. Handled: boolean;
  2687. begin
  2688. p := LayerCollection.LocalToViewport(FVertices[VertexIndex], Scaled);
  2689. Handle.TopLeft := p;
  2690. Handle.BottomRight := Handle.TopLeft;
  2691. Handle.Inflate(FHandleSize, FHandleSize);
  2692. HandleRect := MakeRect(Handle, rrOutside);
  2693. Handled := False;
  2694. if Assigned(FOnUpdateHandle) then
  2695. FOnUpdateHandle(Self, Buffer, p, VertexIndex, HandleRect, Handled);
  2696. if (not Handled) then
  2697. UpdateRect(HandleRect);
  2698. end;
  2699. procedure TCustomRubberBandLayer.DoUpdateVertices(Buffer: TBitmap32; const R: TRect; var Handled: boolean);
  2700. var
  2701. ScaleX, ScaleY, ShiftX, ShiftY: TFloat;
  2702. DoScale: boolean;
  2703. i: integer;
  2704. Handle: TFloatRect;
  2705. HandleRect: TRect;
  2706. begin
  2707. if (Length(FVertices) = 0) then
  2708. exit;
  2709. if (Scaled) and (LayerCollection <> nil) then
  2710. begin
  2711. LayerCollection.GetViewportShift(ShiftX, ShiftY);
  2712. LayerCollection.GetViewportScale(ScaleX, ScaleY);
  2713. DoScale := True;
  2714. end else
  2715. DoScale := False;
  2716. if Assigned(FOnUpdateHandle) then
  2717. begin
  2718. for i := 0 to High(FVertices) do
  2719. if (IsVertexVisible(i)) then
  2720. DoUpdateVertex(Buffer, R, i);
  2721. end else
  2722. begin
  2723. for i := 0 to High(FVertices) do
  2724. if (IsVertexVisible(i)) then
  2725. begin
  2726. // Same as: LayerCollection.LocalToViewport(FVertices[i], Scaled)
  2727. if (DoScale) then
  2728. begin
  2729. Handle.Left := FVertices[i].X * ScaleX + ShiftX;
  2730. Handle.Top := FVertices[i].Y * ScaleY + ShiftY;
  2731. end else
  2732. Handle.TopLeft := FVertices[i];
  2733. Handle.BottomRight := Handle.TopLeft;
  2734. GR32.InflateRect(Handle, FHandleSize, FHandleSize);
  2735. HandleRect := MakeRect(Handle, rrOutside);
  2736. UpdateRect(HandleRect);
  2737. end;
  2738. end;
  2739. Handled := True;
  2740. end;
  2741. procedure TCustomRubberBandLayer.DoDrawUpdate(Buffer: TBitmap32;
  2742. FrameHandler: TRubberBandPaintFrameHandler;
  2743. VerticesHandler: TRubberBandPaintHandlesHandler;
  2744. VertexHandler: TRubberBandPaintHandleHandler);
  2745. var
  2746. R: TRect;
  2747. i: integer;
  2748. Handled: boolean;
  2749. begin
  2750. R := MakeRect(GetAdjustedLocation);
  2751. if (Assigned(FrameHandler)) and (IsFrameVisible) then
  2752. FrameHandler(Buffer, R);
  2753. Handled := False;
  2754. if (Assigned(VerticesHandler)) then
  2755. VerticesHandler(Buffer, R, Handled);
  2756. if (not Handled) and (Assigned(VertexHandler)) then
  2757. for i := 0 to High(Vertices) do
  2758. if (IsVertexVisible(i)) then
  2759. VertexHandler(Buffer, R, i);
  2760. end;
  2761. procedure TCustomRubberBandLayer.Paint(Buffer: TBitmap32);
  2762. begin
  2763. DoDrawUpdate(Buffer, DrawFrame, DoDrawVertices, DoDrawVertex);
  2764. end;
  2765. procedure TCustomRubberBandLayer.Quantize;
  2766. begin
  2767. if (Quantized <> 0) then
  2768. Location := FloatRect(
  2769. Round(Location.Left / Quantized) * Quantized,
  2770. Round(Location.Top / Quantized) * Quantized,
  2771. Round(Location.Right / Quantized) * Quantized,
  2772. Round(Location.Bottom / Quantized) * Quantized);
  2773. end;
  2774. procedure TCustomRubberBandLayer.SetChildLayer(Value: TPositionedLayer);
  2775. begin
  2776. if (FChildLayer <> nil) then
  2777. FChildLayer.RemoveFreeNotification(Self);
  2778. FChildLayer := Value;
  2779. if (FChildLayer <> nil) then
  2780. begin
  2781. BeginUpdate;
  2782. try
  2783. Location := FChildLayer.Location;
  2784. inherited SetScaled(FChildLayer.Scaled); // Not really necessary
  2785. finally
  2786. EndUpdate;
  2787. end;
  2788. FChildLayer.AddFreeNotification(Self);
  2789. end;
  2790. end;
  2791. procedure TCustomRubberBandLayer.SetHandleFrameSize(Value: TFloat);
  2792. begin
  2793. if Value < 0.0 then
  2794. Value := 0
  2795. else
  2796. if Value > FHandleSize then
  2797. Value := FHandleSize;
  2798. if Value <> FHandleFrameSize then
  2799. begin
  2800. // Size doesn't change; No need to erase old
  2801. FHandleFrameSize := Value;
  2802. UpdateVertices;
  2803. end;
  2804. end;
  2805. procedure TCustomRubberBandLayer.SetHandleHitZone(const Value: TFloat);
  2806. begin
  2807. if (Value >= 0) then
  2808. FHandleHitZone := Value;
  2809. end;
  2810. procedure TCustomRubberBandLayer.SetHandleFill(Value: TColor32);
  2811. begin
  2812. if Value <> FHandleFill then
  2813. begin
  2814. // Size doesn't change; No need to erase old
  2815. FHandleFill := Value;
  2816. UpdateVertices;
  2817. end;
  2818. end;
  2819. procedure TCustomRubberBandLayer.SetHandleFrame(Value: TColor32);
  2820. begin
  2821. if Value <> FHandleFrame then
  2822. begin
  2823. // Size doesn't change; No need to erase old
  2824. FHandleFrame := Value;
  2825. UpdateVertices;
  2826. end;
  2827. end;
  2828. procedure TCustomRubberBandLayer.SetHandleSize(Value: TFloat);
  2829. begin
  2830. if Value < 1 then
  2831. Value := 1;
  2832. if Value <> FHandleSize then
  2833. begin
  2834. // Erase old
  2835. UpdateVertices;
  2836. FHandleSize := Value;
  2837. if FHandleSize < FHandleFrameSize then
  2838. FHandleFrameSize := FHandleSize;
  2839. // Paint new
  2840. UpdateVertices;
  2841. end;
  2842. end;
  2843. procedure TCustomRubberBandLayer.SetHandleStyle(const Value: TRubberBandHandleStyle);
  2844. begin
  2845. if (FHandleStyle <> Value) then
  2846. begin
  2847. // Erase old
  2848. UpdateVertices;
  2849. FHandleStyle := Value;
  2850. // Paint new
  2851. UpdateVertices;
  2852. end;
  2853. end;
  2854. procedure TCustomRubberBandLayer.SetFrameStipple(const Value: TArrayOfColor32);
  2855. begin
  2856. FFrameStipplePattern := Copy(Value);
  2857. FFrameStippleCounter := Wrap(FFrameStippleCounter, Length(FFrameStipplePattern));
  2858. UpdateFrame;
  2859. end;
  2860. procedure TCustomRubberBandLayer.SetFrameStippleStep(const Value: TFloat);
  2861. begin
  2862. if Value <> FFrameStippleStep then
  2863. begin
  2864. FFrameStippleStep := Value;
  2865. UpdateFrame;;
  2866. end;
  2867. end;
  2868. procedure TCustomRubberBandLayer.UpdateFrame;
  2869. begin
  2870. DoDrawUpdate(nil, DoUpdateFrame, nil, nil);
  2871. end;
  2872. procedure TCustomRubberBandLayer.UpdateVertices;
  2873. begin
  2874. DoDrawUpdate(nil, nil, DoUpdateVertices, DoUpdateVertex);
  2875. end;
  2876. procedure TCustomRubberBandLayer.Update;
  2877. begin
  2878. // Since the handles are partially outside the layer rect we need to
  2879. // invalidate the area covered by those.
  2880. // We could just inflate the rect being invalidated by the size of the handles
  2881. //
  2882. // InflateRect(R, Ceil(FHandleSize), Ceil(FHandleSize));
  2883. // Update(R);
  2884. //
  2885. // ...but instead we go for the "slightly" more complex and correct solution
  2886. // of only invalidating the area actually covered by the frame and the handles.
  2887. DoDrawUpdate(nil, DoUpdateFrame, DoUpdateVertices, DoUpdateVertex);
  2888. end;
  2889. procedure TCustomRubberBandLayer.UpdateChildLayer;
  2890. begin
  2891. if (FChildLayer <> nil) then
  2892. FChildLayer.Location := Location;
  2893. end;
  2894. procedure TCustomRubberBandLayer.SetFrameStippleCounter(const Value: TFloat);
  2895. begin
  2896. if Value <> FFrameStippleCounter then
  2897. begin
  2898. FFrameStippleCounter := Wrap(Value, Length(FFrameStipplePattern));
  2899. UpdateFrame;
  2900. end;
  2901. end;
  2902. procedure TCustomRubberBandLayer.SetLayerOptions(Value: Cardinal);
  2903. begin
  2904. inherited SetLayerOptions(Value and not LOB_NO_UPDATE); // workaround for changed behaviour
  2905. end;
  2906. procedure TCustomRubberBandLayer.SetQuantized(const Value: Integer);
  2907. begin
  2908. if Value < 1 then
  2909. raise Exception.Create('Value must be larger than zero!');
  2910. FQuantized := Value;
  2911. end;
  2912. function TCustomRubberBandLayer.GetVertex(Index: integer): TFloatPoint;
  2913. begin
  2914. Result := FVertices[Index];
  2915. end;
  2916. procedure TCustomRubberBandLayer.SetVertex(Index: integer; const Value: TFloatPoint);
  2917. begin
  2918. if (FVertices[Index] = Value) then
  2919. exit;
  2920. // Erase old
  2921. Update;
  2922. FVertices[Index] := Value;
  2923. // Paint new
  2924. Update;
  2925. end;
  2926. procedure TCustomRubberBandLayer.SetVertices(const Value: TArrayOfFloatPoint);
  2927. begin
  2928. // Erase old
  2929. Update;
  2930. FVertices := Copy(Value);
  2931. // Paint new
  2932. Update;
  2933. end;
  2934. //------------------------------------------------------------------------------
  2935. //
  2936. // TRubberbandLayer
  2937. //
  2938. //------------------------------------------------------------------------------
  2939. constructor TRubberbandLayer.Create(ALayerCollection: TLayerCollection);
  2940. begin
  2941. inherited;
  2942. FHandles := [rhCenter, rhSides, rhCorners, rhFrame];
  2943. FValidDragStates := GetValidDragStates;
  2944. FMinWidth := 10;
  2945. FMinHeight := 10;
  2946. Quantized := 8;
  2947. end;
  2948. function TRubberbandLayer.GetHitTest(const APosition: TPoint; AShift: TShiftState): ILayerHitTest;
  2949. var
  2950. R: TRect;
  2951. begin
  2952. // APosition is in control coordinates
  2953. Result := inherited;
  2954. // Hit test against the layer bounding rectangle.
  2955. // This is only kept for backward compatibility as the base class
  2956. // already does hit testing against the vertex polygon.
  2957. if (Result = nil) and AllowMove then
  2958. begin
  2959. R := MakeRect(GetAdjustedLocation);
  2960. if (GR32.PtInRect(R, APosition)) then
  2961. begin
  2962. Result := TLayerHitTestMove.Create(APosition);
  2963. Result.Shift := AShift;
  2964. Result.Cursor := GetHitTestCursor(Result);
  2965. end;
  2966. end;
  2967. end;
  2968. function TRubberbandLayer.GetHitTestCursor(const AHitTest: ILayerHitTest): TCursor;
  2969. function SnapAngleTo45(Angle: integer): integer;
  2970. begin
  2971. Result := (((Angle + 45 div 2) div 45) * 45 + 360) mod 360;
  2972. end;
  2973. function AngleToDirection(Angle: integer): TResizeDirection;
  2974. begin
  2975. Result := TResizeDirection(SnapAngleTo45(Angle) div 45);
  2976. end;
  2977. var
  2978. HitTestVertex: ILayerHitTestVertex;
  2979. var
  2980. Angle: integer;
  2981. Direction: TResizeDirection;
  2982. NewCursor: TCursor;
  2983. const
  2984. VertexToAngle: array[0..7] of integer =
  2985. //
  2986. // 0 1 2
  2987. //
  2988. // 7 3
  2989. //
  2990. // 6 5 4
  2991. //
  2992. (135, 90, 45, 0, 315, 270, 225, 180);
  2993. begin
  2994. Result := inherited GetHitTestCursor(AHitTest);
  2995. if (AHitTest <> nil) then
  2996. begin
  2997. if Supports(AHitTest, ILayerHitTestVertex, HitTestVertex) then
  2998. begin
  2999. Angle := VertexToAngle[HitTestVertex.Vertex];
  3000. // Call GetHandleCursor for backward compatibility in case a
  3001. // derived class has overridden it. It will return Low(TCursor)
  3002. // if GetHandleCursor has not been overridden.
  3003. Result := GetHandleCursor(VertexToDragState[HitTestVertex.Vertex], Angle);
  3004. if (Result = Low(TCursor)) then
  3005. begin
  3006. Direction := AngleToDirection(Angle);
  3007. Result := DirectionCursors[Direction];
  3008. end;
  3009. end else
  3010. if (Supports(AHitTest, ILayerHitTestMove)) then
  3011. begin
  3012. NewCursor := GetHandleCursor(dsMove, 0);
  3013. if (NewCursor <> Low(TCursor)) then
  3014. Result := NewCursor;
  3015. end;
  3016. end;
  3017. end;
  3018. function TRubberbandLayer.GetValidDragStates: TValidDragStates;
  3019. begin
  3020. Result := [];
  3021. if (rhCenter in FHandles) then
  3022. Include(Result, dsMove);
  3023. if (rhSides in FHandles) then
  3024. begin
  3025. if not(rhNotRightSide in FHandles) then
  3026. Include(Result, dsSizeR);
  3027. if not(rhNotBottomSide in FHandles) then
  3028. Include(Result, dsSizeB);
  3029. if not(rhNotLeftSide in FHandles) then
  3030. Include(Result, dsSizeL);
  3031. if not(rhNotTopSide in FHandles) then
  3032. Include(Result, dsSizeT);
  3033. end;
  3034. if (rhCorners in FHandles) then
  3035. begin
  3036. if not(rhNotBRCorner in FHandles) then
  3037. Include(Result, dsSizeBR);
  3038. if not(rhNotBLCorner in FHandles) then
  3039. Include(Result, dsSizeBL);
  3040. if not(rhNotTRCorner in FHandles) then
  3041. Include(Result, dsSizeTR);
  3042. if not(rhNotTLCorner in FHandles) then
  3043. Include(Result, dsSizeTL);
  3044. end;
  3045. end;
  3046. function TRubberbandLayer.GetHandleCursor(DragState: TRBDragState; Angle: integer): TCursor;
  3047. (*
  3048. var
  3049. Vertex: integer;
  3050. *)
  3051. begin
  3052. Result := Low(TCursor);
  3053. (*
  3054. if (DragState in [dsNone, dsMove]) then
  3055. Vertex := -1
  3056. else
  3057. begin
  3058. case Angle of
  3059. 0 .. 22: Vertex := 3;
  3060. 23 .. 57: Vertex := 2;
  3061. 58 ..112: Vertex := 1;
  3062. 113 ..157: Vertex := 0;
  3063. 158 ..202: Vertex := 7;
  3064. 203 ..247: Vertex := 6;
  3065. 248 ..292: Vertex := 5;
  3066. 293 ..337: Vertex := 4;
  3067. 338 ..360: Vertex := 3;
  3068. else
  3069. Vertex := -1
  3070. end;
  3071. end;
  3072. Result := GetVertexCursor(Vertex);
  3073. *)
  3074. end;
  3075. function TRubberbandLayer.AllowMove: boolean;
  3076. begin
  3077. Result := (dsMove in FValidDragStates);
  3078. end;
  3079. function TRubberbandLayer.ApplyOffset(const AHitTest: ILayerHitTest; AQuantize: boolean): boolean;
  3080. // Move Left/Top relative to Right/Bottom
  3081. procedure OffsetLeftTop(var LT: TFloat; RB: TFloat; Delta, MinSize, MaxSize: TFloat);
  3082. begin
  3083. LT := LT + Delta;
  3084. if (RB - LT < MinSize) then
  3085. LT := RB - MinSize;
  3086. if (MaxSize >= MinSize) and (RB - LT > MaxSize) then
  3087. LT := RB - MaxSize;
  3088. if AQuantize then
  3089. LT := Round(LT / Quantized) * Quantized;
  3090. end;
  3091. // Move Right/Bottom relative to Left/Top
  3092. procedure OffsetRightBottom(LT: TFloat; var RB: TFloat; Delta, MinSize, MaxSize: TFloat);
  3093. begin
  3094. RB := RB + Delta;
  3095. if (RB - LT < MinSize) then
  3096. RB := LT + MinSize;
  3097. if (MaxSize >= MinSize) and (RB - LT > MaxSize) then
  3098. RB := LT + MaxSize;
  3099. if AQuantize then
  3100. RB := Round(RB / Quantized) * Quantized;
  3101. end;
  3102. var
  3103. Delta: TFloatPoint;
  3104. ScaleX, ScaleY: TFloat;
  3105. StartLocation: TFloatRect;
  3106. NewLocation: TFloatRect;
  3107. HitTestVertex: ILayerHitTestVertex;
  3108. DragState: TRBDragState;
  3109. begin
  3110. Result := False;
  3111. Delta := FloatPoint(AHitTest.CurrentPosition - AHitTest.StartPosition);
  3112. if Scaled then
  3113. begin
  3114. LayerCollection.GetViewportScale(ScaleX, ScaleY);
  3115. Delta.X := Delta.X / ScaleX;
  3116. Delta.Y := Delta.Y / ScaleY;
  3117. end;
  3118. // Apply delta/offset relative to start location
  3119. StartLocation := AHitTest.StartLocation;
  3120. (*
  3121. ** Move layer
  3122. *)
  3123. if Supports(AHitTest, ILayerHitTestMove) then
  3124. begin
  3125. DragState := dsMove;
  3126. if AQuantize then
  3127. begin
  3128. NewLocation.Left := Round((StartLocation.Left + Delta.X) / Quantized) * Quantized;
  3129. NewLocation.Top := Round((StartLocation.Top + Delta.Y) / Quantized) * Quantized;
  3130. end else
  3131. NewLocation.TopLeft := StartLocation.TopLeft + Delta;
  3132. // Set new loaction but keep old width/height
  3133. NewLocation.Right := NewLocation.Left + StartLocation.Width;
  3134. NewLocation.Bottom := NewLocation.Top + StartLocation.Height;
  3135. end else
  3136. (*
  3137. ** Move handle
  3138. *)
  3139. if Supports(AHitTest, ILayerHitTestVertex, HitTestVertex) then
  3140. begin
  3141. DragState := VertexToDragState[HitTestVertex.Vertex];
  3142. NewLocation := StartLocation;
  3143. // Left handles
  3144. if DragState in [dsSizeL, dsSizeTL, dsSizeBL] then
  3145. OffsetLeftTop(NewLocation.Left, NewLocation.Right, Delta.X, MinWidth, MaxWidth)
  3146. else
  3147. // Right handles
  3148. if DragState in [dsSizeR, dsSizeTR, dsSizeBR] then
  3149. OffsetRightBottom(NewLocation.Left, NewLocation.Right, Delta.X, MinWidth, MaxWidth);
  3150. // Top handles
  3151. if DragState in [dsSizeT, dsSizeTL, dsSizeTR] then
  3152. OffsetLeftTop(NewLocation.Top, NewLocation.Bottom, Delta.Y, MinHeight, MaxHeight)
  3153. else
  3154. // Bottom handles
  3155. if DragState in [dsSizeB, dsSizeBL, dsSizeBR] then
  3156. OffsetRightBottom(NewLocation.Top, NewLocation.Bottom, Delta.Y, MinHeight, MaxHeight);
  3157. end else
  3158. exit;
  3159. if (roConstrained in FOptions) then
  3160. DoConstrain(StartLocation, NewLocation, DragState, AHitTest.Shift);
  3161. if (roProportional in FOptions) then
  3162. begin
  3163. case DragState of
  3164. dsSizeB, dsSizeBR:
  3165. NewLocation.Right := StartLocation.Left + StartLocation.Width * NewLocation.Height / StartLocation.Height;
  3166. dsSizeT, dsSizeTL:
  3167. NewLocation.Left := StartLocation.Right - StartLocation.Width * NewLocation.Height / StartLocation.Height;
  3168. dsSizeR, dsSizeBL:
  3169. NewLocation.Bottom := StartLocation.Top + StartLocation.Height * NewLocation.Width / StartLocation.Width;
  3170. dsSizeL, dsSizeTR:
  3171. NewLocation.Top := StartLocation.Bottom - StartLocation.Height * NewLocation.Width / StartLocation.Width;
  3172. end;
  3173. end;
  3174. DoResizing(StartLocation, NewLocation, DragState, AHitTest.Shift);
  3175. if (NewLocation <> Location) then
  3176. begin
  3177. Location := NewLocation;
  3178. Result := True;
  3179. end;
  3180. end;
  3181. procedure TRubberbandLayer.DoSetDragState(const Value: TRBDragState; const X, Y: Integer);
  3182. var
  3183. HitTest: ILayerHitTest;
  3184. Vertex: integer;
  3185. begin
  3186. HitTest := nil;
  3187. FDragState := Value;
  3188. if (FDragState <> dsNone) then
  3189. begin
  3190. Vertex := DragStateToVertex[FDragState];
  3191. if (Vertex <> -1) then
  3192. HitTest := TLayerHitTestVertex.Create(GR32.Point(X, Y), Vertex, Vertices[Vertex])
  3193. else
  3194. if (FDragState = dsMove) then
  3195. HitTest := TLayerHitTestMove.Create(GR32.Point(X, Y));
  3196. end;
  3197. inherited SetHitTest(HitTest);
  3198. end;
  3199. procedure TRubberbandLayer.SetDragState(const Value: TRBDragState; const X, Y: Integer);
  3200. begin
  3201. // Indirection to avoid internal deprecated warnings
  3202. DoSetDragState(Value, X, Y);
  3203. end;
  3204. procedure TRubberbandLayer.SetDragState(const Value: TRBDragState);
  3205. begin
  3206. // Indirection to avoid internal deprecated warnings
  3207. DoSetDragState(Value, 0, 0);
  3208. end;
  3209. function TRubberbandLayer.GetDragState(X, Y: Integer): TRBDragState;
  3210. var
  3211. HitTest: ILayerHitTest;
  3212. HitTestVertex: ILayerHitTestVertex;
  3213. begin
  3214. HitTest := GetHitTest(GR32.Point(X, Y));
  3215. if (HitTest = nil) then
  3216. Result := dsNone
  3217. else
  3218. if (Supports(HitTest, ILayerHitTestVertex, HitTestVertex)) then
  3219. Result := VertexToDragState[HitTestVertex.Vertex]
  3220. else
  3221. if (Supports(HitTest, ILayerHitTestMove)) then
  3222. Result := dsMove
  3223. else
  3224. Result := dsNone
  3225. end;
  3226. function TRubberbandLayer.IsFrameVisible: boolean;
  3227. begin
  3228. Result := (inherited IsFrameVisible) and (rhFrame in FHandles);
  3229. end;
  3230. function TRubberbandLayer.CanQuantize: boolean;
  3231. begin
  3232. Result := (inherited CanQuantize) and (roQuantized in FOptions);
  3233. end;
  3234. function TRubberbandLayer.IsVertexVisible(VertexIndex: integer): boolean;
  3235. begin
  3236. Result := (inherited IsVertexVisible(VertexIndex)) and (VertexToDragState[VertexIndex] in FValidDragStates);
  3237. end;
  3238. procedure TRubberbandLayer.DoSetLocation(const NewLocation: TFloatRect);
  3239. var
  3240. Handles: TArrayOfFloatPoint;
  3241. begin
  3242. inherited;
  3243. SetLength(Handles, 8);
  3244. Handles[0].X := Location.Left;
  3245. Handles[0].Y := Location.Top;
  3246. Handles[2].X := Location.Right;
  3247. Handles[2].Y := Handles[0].Y;
  3248. Handles[4].X := Handles[2].X;
  3249. Handles[4].Y := Location.Bottom;
  3250. Handles[6].X := Handles[0].X;
  3251. Handles[6].Y := Handles[4].Y;
  3252. Handles[1].X := (Handles[0].X + Handles[2].X) / 2;
  3253. Handles[1].Y := Handles[0].Y;
  3254. Handles[3].X := Handles[2].X;
  3255. Handles[3].Y := (Handles[0].Y + Handles[4].Y) / 2;
  3256. Handles[5].X := Handles[1].X;
  3257. Handles[5].Y := Handles[4].Y;
  3258. Handles[7].X := Handles[0].X;
  3259. Handles[7].Y := Handles[3].Y;
  3260. Vertices := Handles;
  3261. end;
  3262. procedure TRubberbandLayer.DoResizing(const OldLocation: TFloatRect; var NewLocation: TFloatRect; DragState: TRBDragState; Shift: TShiftState);
  3263. begin
  3264. if Assigned(FOnResizing) then
  3265. FOnResizing(Self, OldLocation, NewLocation, DragState, Shift);
  3266. end;
  3267. procedure TRubberbandLayer.DoConstrain(const OldLocation: TFloatRect; var NewLocation: TFloatRect; DragState: TRBDragState; Shift: TShiftState);
  3268. begin
  3269. if Assigned(FOnConstrain) then
  3270. FOnConstrain(Self, OldLocation, NewLocation, DragState, Shift);
  3271. end;
  3272. procedure TRubberbandLayer.SetHandles(Value: TRBHandles);
  3273. begin
  3274. if Value <> FHandles then
  3275. begin
  3276. // Erase old
  3277. UpdateVertices;
  3278. FHandles := Value;
  3279. FValidDragStates := GetValidDragStates;
  3280. // Paint new
  3281. UpdateVertices;
  3282. end;
  3283. end;
  3284. procedure TRubberbandLayer.SetOptions(const Value: TRBOptions);
  3285. begin
  3286. FOptions := Value;
  3287. end;
  3288. procedure TRubberbandLayer.DrawFrame(Buffer: TBitmap32; const R: TRect);
  3289. begin
  3290. Buffer.SetStipple(FrameStipple);
  3291. Buffer.StippleCounter := 0;
  3292. Buffer.StippleStep := FrameStippleStep;
  3293. Buffer.StippleCounter := FrameStippleCounter;
  3294. Buffer.FrameRectTSP(R.Left, R.Top, R.Right, R.Bottom);
  3295. end;
  3296. procedure TRubberbandLayer.DoUpdateFrame(Buffer: TBitmap32; const R: TRect);
  3297. begin
  3298. // Left
  3299. UpdateRect(Rect(R.Left, R.Top, R.Left+1, R.Bottom));
  3300. // Right
  3301. UpdateRect(Rect(R.Right-1, R.Top, R.Right, R.Bottom));
  3302. // Top
  3303. UpdateRect(Rect(R.Left+1, R.Top, R.Right-1, R.Top+1));
  3304. // Bottom
  3305. UpdateRect(Rect(R.Left+1, R.Bottom-1, R.Right-1, R.Bottom));
  3306. end;
  3307. end.