BCExpandPanels.pas 74 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631
  1. {
  2. ********************************************************************************
  3. * BGRAExpandPanels Version 1.0 *
  4. * *
  5. * *
  6. * (c) Massimo Magnano, Alexander Roth *
  7. * *
  8. * *
  9. ********************************************************************************
  10. See BcExpandPanels.txt for changelog and to-do
  11. }
  12. unit BCExpandPanels;
  13. {$mode objfpc}{$H+}
  14. // for debugging purposes
  15. //{$DEFINE DEBUG_PAINT}
  16. interface
  17. uses
  18. Controls, Classes, ExtCtrls, Graphics, Math, LResources, Dialogs, SysUtils,
  19. Buttons, Themes, Types, Menus, BCPanel;
  20. type
  21. TBCExpandPanelsBehaviour = (EPHotMouse, EPMultipanel, EPSinglePanel);
  22. // TBoundEvent=procedure(sender:TObject; ALeft, ATop, AWidth, AHeight: integer) of object;
  23. TAnimationEvent = procedure(Sender: TObject; deltaLeft, deltaTop, deltaWidth, deltaHeight: integer) of object;
  24. TNormalProcedure = procedure of object;
  25. { TBCBoundButton }
  26. TGlyphLayout =
  27. (
  28. glLeft,
  29. glRight,
  30. glNone
  31. );
  32. TGlyphKind =
  33. (
  34. gkArrows,
  35. gkClose,
  36. gkMinMax
  37. );
  38. TTextLayout =
  39. (
  40. tlLeft,
  41. tlRight,
  42. tlCenter,
  43. tlNone
  44. );
  45. TBCBoundButtonStyle = (bbsButton, bbsTab, bbsLine, bbsLineDouble,
  46. bbsLineTop, bbsLineBottom, bbsLineDoubleTop, bbsLineDoubleBottom);
  47. TBCBoundButton = class(TCustomSpeedButton)
  48. private
  49. rColorExpanded: TColor;
  50. rColorHighlight: TColor;
  51. rColorShadow: TColor;
  52. rGlyphKind: TGlyphKind;
  53. rGlyphLayout: TGlyphLayout;
  54. rStyle: TBCBoundButtonStyle;
  55. rTabWidth: Integer;
  56. rTextLayout: TTextLayout;
  57. procedure setColorExpanded(AValue: TColor);
  58. procedure SetColorHighlight(AValue: TColor);
  59. procedure SetColorShadow(AValue: TColor);
  60. procedure SetGlyphKind(AValue: TGlyphKind);
  61. procedure SetGlyphLayout(AValue: TGlyphLayout);
  62. procedure SetStyle(AValue: TBCBoundButtonStyle);
  63. procedure SetTabWidth(AValue: Integer);
  64. procedure SetTextLayout(AValue: TTextLayout);
  65. protected
  66. rGlyph :TButtonGlyph;
  67. rUserGlyphExpanded,
  68. rUserGlyphCollapsed,
  69. rGlyphExpanded,
  70. rGlyphCollapsed :TBitmap;
  71. procedure SetGlyphCollapsed(AValue: TBitmap);
  72. procedure SetGlyphExpanded(AValue: TBitmap);
  73. procedure LoadGlyph(GlyphDST :TBitmap; ResName :String);
  74. procedure BuildGlyphs;
  75. procedure Paint; override;
  76. procedure Loaded; override;
  77. (* property AllowAllUp;
  78. property Down;
  79. property Glyph;
  80. property GroupIndex;
  81. property Height; //Don't Decrease visibility :-O
  82. property HelpContext;
  83. property HelpKeyword;
  84. property HelpType;
  85. property Layout;
  86. property Left;
  87. property Margin;
  88. property Name;
  89. property NumGlyphs;
  90. property Spacing;
  91. property ShowCaption;
  92. property Tag;
  93. property Top;
  94. property Width;
  95. property Transparent;
  96. *)
  97. public
  98. constructor Create(AOwner: TComponent); override;
  99. destructor Destroy; override;
  100. published
  101. property Caption;
  102. property Color nodefault;
  103. property ColorExpanded: TColor read rColorExpanded write setColorExpanded;
  104. property ColorHighlight: TColor read rColorHighlight write SetColorHighlight default clDefault;
  105. property ColorShadow: TColor read rColorShadow write SetColorShadow default clDefault;
  106. property Font;
  107. property Flat;
  108. property GlyphExpanded: TBitmap read rUserGlyphExpanded write SetGlyphExpanded;
  109. property GlyphCollapsed: TBitmap read rUserGlyphCollapsed write SetGlyphCollapsed;
  110. property GlyphLayout: TGlyphLayout read rGlyphLayout write SetGlyphLayout default glNone;
  111. property GlyphKind: TGlyphKind read rGlyphKind write SetGlyphKind default gkArrows;
  112. property ShowAccelChar;
  113. property TextLayout: TTextLayout read rTextLayout write SetTextLayout default tlLeft;
  114. property Style: TBCBoundButtonStyle read rStyle write SetStyle default bbsButton;
  115. //Negative Values is the % of Total Width, Positive is a Fixed Width
  116. property TabWidth: Integer read rTabWidth write SetTabWidth default -50;
  117. end;
  118. { TBCExpandPanel }
  119. TBCExpandPanel = class(TBCPanel)
  120. private
  121. FEPManagesCollapsing: TNotifyEvent;
  122. FButton: TBCBoundButton;
  123. FButtonSize: integer;
  124. FCollapseKind: TAnchorKind;
  125. FCollapsed: boolean;
  126. FAnimated: boolean;
  127. FOnExpand: TNotifyEvent;
  128. FOnPreExpand: TNotifyEvent;
  129. FOnAnimate: TAnimationEvent;
  130. FOnCollapse: TNotifyEvent;
  131. FOnPreCollapse: TNotifyEvent;
  132. FOnButtonClick: TNotifyEvent;
  133. FInternalOnAnimate: TAnimationEvent;
  134. FButtonPosition: TAnchorKind;
  135. FExpandedButtonColor: TColor;
  136. FCollapsedButtonColor: TColor;
  137. FExpandedSize: integer;
  138. FAnimationSpeed: real;
  139. FTextAlignment: TAlignment;
  140. rBevelColorHighlight: TColor;
  141. rBevelColorShadow: TColor;
  142. rBevelRounded: Boolean;
  143. StopCircleActions: boolean;
  144. FAnimating: boolean;
  145. FVisibleTotal: boolean;
  146. TargetAnimationSize: integer;
  147. EndProcedureOfAnimation: TNormalProcedure;
  148. Timer: TTimer;
  149. function GetEnabled: Boolean;
  150. procedure SetBevelColorHighlight(AValue: TColor);
  151. procedure SetBevelColorShadow(AValue: TColor);
  152. procedure SetBevelRounded(AValue: Boolean);
  153. procedure SetEnabled(AValue: Boolean);
  154. procedure setExpandedSize(Value: integer);
  155. procedure setButtonSize(Value: integer);
  156. procedure setButtonPosition(Value: TAnchorKind);
  157. procedure setCollapseKind(Value: TAnchorKind);
  158. procedure setAnimationSpeed(Value: real);
  159. procedure setCollapsed(Value: boolean);
  160. procedure PositionButton;
  161. procedure SetRelevantSize(comp: TControl; AKind: TAnchorKind; ASize: Integer);
  162. function RelevantSize(comp: TControl; akind: TAnchorKind): integer;
  163. function RelevantOrthogonalSize(comp: TControl; akind: TAnchorKind): integer;
  164. function DeltaCoordinates(deltaMove, deltaSize: integer): TRect; // the outpot (left,top right, bottom) has all the information: left and top encode the movement. rigth and bottom the size changes
  165. procedure Animate(aTargetSize: integer);
  166. procedure SetTextAlignment(AValue: TAlignment);
  167. procedure TimerAnimateSize(Sender: TObject);
  168. procedure EndTimerCollapse;
  169. procedure EndTimerExpand;
  170. procedure UpdateAll;
  171. procedure ButtonClick(Sender: TObject);
  172. procedure DoCollapse;
  173. procedure DoExpand;
  174. procedure AdjustClientRect(var ARect: TRect); override;
  175. property InternalOnAnimate: TAnimationEvent read FInternalOnAnimate write FInternalOnAnimate;
  176. property EPManagesCollapsing: TNotifyEvent read FEPManagesCollapsing write FEPManagesCollapsing;
  177. protected
  178. procedure Loaded; override;
  179. procedure CreateWnd; override;
  180. procedure Paint; override;
  181. public
  182. property Animating: boolean read FAnimating;
  183. constructor Create(TheOwner: TComponent); override;
  184. destructor Destroy; override;
  185. procedure SetBounds(ALeft, ATop, AWidth, AHeight: integer); override;
  186. published
  187. property TextAlignment: TAlignment read FTextAlignment write SetTextAlignment;
  188. property Enabled: Boolean read GetEnabled write SetEnabled;
  189. property CollapseKind: TAnchorKind read FCollapseKind write setCollapseKind; //To where should it collapse?
  190. property ExpandedSize: integer read FExpandedSize write setExpandedSize;
  191. property ButtonPosition: TAnchorKind read FButtonPosition write setButtonPosition;
  192. property ButtonSize: integer read FButtonSize write setButtonSize;
  193. property Button: TBCBoundButton read FButton;
  194. property AnimationSpeed: real read FAnimationSpeed write setAnimationSpeed;
  195. property Animated: boolean read FAnimated write FAnimated default True;
  196. property Collapsed: boolean read FCollapsed write setCollapsed default False;
  197. property BevelColorHighlight: TColor read rBevelColorHighlight write SetBevelColorHighlight default clBtnHighlight;
  198. property BevelColorShadow: TColor read rBevelColorShadow write SetBevelColorShadow default clBtnShadow;
  199. property BevelRounded: Boolean read rBevelRounded write SetBevelRounded default True;
  200. property OnAnimate: TAnimationEvent read FOnAnimate write FOnAnimate;
  201. property OnButtonClick: TNotifyEvent read FOnButtonClick write FOnButtonClick;
  202. property OnPreExpand: TNotifyEvent read FOnPreExpand write FOnPreExpand;
  203. property OnExpand: TNotifyEvent read FOnExpand write FOnExpand;
  204. property OnCollapse: TNotifyEvent read FOnCollapse write FOnCollapse;
  205. property OnPreCollapse: TNotifyEvent read FOnPreCollapse write FOnPreCollapse;
  206. end;
  207. {==============================================================================
  208. Class: TBCExpandPanels
  209. Description:
  210. ==============================================================================}
  211. { TBCExpandPanels }
  212. TBCExpandPanels = class(TComponent)
  213. private
  214. { Private-Deklarationen }
  215. PanelArray: TList;
  216. // Properties
  217. FArrangeKind: TAnchorKind;
  218. FButtonPosition, FCollapseKind: TAnchorKind;
  219. FButtonGlyphKind: TGlyphKind;
  220. FButtonGlyphLayout: TGlyphLayout;
  221. FButtonStyle: TBCBoundButtonStyle;
  222. FButtonTabWidth: Integer;
  223. FButtonTextLayout: TTextLayout;
  224. FOrthogonalAbove: integer;
  225. FAbove: integer;
  226. FOrthogonalSize: integer;
  227. FBehaviour: TBCExpandPanelsBehaviour;
  228. FOnArrangePanels: TNotifyEvent;
  229. FFixedSize: integer;
  230. FUseFixedSize: boolean;
  231. FAutoCollapseIfTooHigh: boolean;
  232. FUseClientSize: boolean;
  233. function RelevantAbove(comp: TControl): integer;
  234. function RelevantOrthogonalAbove(comp: TControl): integer;
  235. function RelevantSize(comp: TControl): integer;
  236. function RelevantOrthogonalSize(comp: TControl): integer;
  237. procedure setButtonGlyphKind(AValue: TGlyphKind);
  238. procedure setButtonGlyphLayout(AValue: TGlyphLayout);
  239. procedure setButtonStyle(AValue: TBCBoundButtonStyle);
  240. procedure SetButtonTabWidth(AValue: Integer);
  241. procedure setButtonTextLayout(AValue: TTextLayout);
  242. procedure WriteRelevantAbove(comp: TBCExpandPanel; above: integer);
  243. procedure WriteRelevantSize(comp: TBCExpandPanel; size: integer);
  244. procedure WriteRelevantOrthogonalSize(comp: TBCExpandPanel; size: integer);
  245. procedure WriteRelevantOrthogonalAbove(comp: TBCExpandPanel; size: integer);
  246. procedure setArrangeKind(Value: TAnchorKind);
  247. procedure setButtonPosition(Value: TAnchorKind);
  248. procedure setCollapseKind(Value: TAnchorKind);
  249. procedure setUseClientSize(Value: boolean);
  250. procedure setUseFixedSize(Value: boolean);
  251. procedure setAutoCollapseIfTooHigh(Value: boolean);
  252. procedure setFixedSize(Value: integer);
  253. procedure setOrthogonalAbove(Value: integer);
  254. procedure setAbove(Value: integer);
  255. procedure setOrthogonalSize(Value: integer);
  256. procedure setBehaviour(Value: TBCExpandPanelsBehaviour);
  257. procedure MakeCorrectButtonClickPointers;
  258. procedure RollOutOnAnimate(Sender: TObject; deltaLeft, deltaTop, deltaWidth, deltaHeight: integer);
  259. procedure RollOutClick(Sender: TObject);
  260. procedure HotTrackSetActivePanel(Value: integer);
  261. procedure DelLastPanel;
  262. procedure RollOut1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: integer);
  263. protected
  264. { Protected-Deklarationen }
  265. public
  266. { Public-Deklarationen }
  267. property OrthogonalAbove: integer read FOrthogonalAbove write setOrthogonalAbove;
  268. property Above: integer read FAbove write setAbove;
  269. property OrthogonalSize: integer read FOrthogonalSize write setOrthogonalSize;
  270. function IdxOfPanel(aname: string): integer; overload;
  271. procedure CollapseIfTooHigh;
  272. // procedure SetCorrectSize;
  273. procedure AddPanel(rollout: TBCExpandPanel);
  274. procedure InsertPanel(idx: integer; rollout: TBCExpandPanel);
  275. function DeltePanel(aname: string): boolean; overload;
  276. function DeltePanel(idx: integer): boolean; overload;
  277. procedure DelteLastPanel;
  278. procedure ArrangePanels;
  279. function Count: integer;
  280. function Panel(idx: integer): TBCExpandPanel;
  281. property CollapseKind: TAnchorKind read FCollapseKind write setCollapseKind;
  282. property ButtonPosition: TAnchorKind read FButtonPosition write setButtonPosition;
  283. property ButtonGlyphLayout: TGlyphLayout read FButtonGlyphLayout write setButtonGlyphLayout;
  284. property ButtonGlyphKind: TGlyphKind read FButtonGlyphKind write setButtonGlyphKind;
  285. property ButtonStyle: TBCBoundButtonStyle read FButtonStyle write setButtonStyle;
  286. property ButtonTabWidth: Integer read FButtonTabWidth write SetButtonTabWidth;
  287. property ButtonTextLayout: TTextLayout read FButtonTextLayout write setButtonTextLayout;
  288. constructor Create(AOwner: TComponent); override;
  289. destructor Destroy; override;
  290. published
  291. { Published-Deklarationen }
  292. // property FixedHeight:integer read FFixedHeight write setFixedSize;
  293. // property UseFixedHeight:boolean read FUseFixedHeight write setUseFixedSize;
  294. // property UseClientHeight:boolean read FUseClientHeight write setUseClientSize;
  295. // property AutoCollapseIfTooHigh:boolean read FAutoCollapseIfTooHigh write setAutoCollapseIfTooHigh;
  296. property ArrangeKind: TAnchorKind read FArrangeKind write setArrangeKind;
  297. property OnArrangePanels: TNotifyEvent read FOnArrangePanels write FOnArrangePanels;
  298. property Behaviour: TBCExpandPanelsBehaviour read FBehaviour write setBehaviour;
  299. end;
  300. procedure Register;
  301. implementation
  302. uses GraphType, LCLProc;
  303. const
  304. //GrayScale a Color : Taken from BGRABitmap package
  305. redWeightShl10 = 306; // = 0.299
  306. greenWeightShl10 = 601; // = 0.587
  307. blueWeightShl10 = 117; // = 0.114
  308. procedure korrigiere(var w: real; min, max: real);
  309. var
  310. temp: real;
  311. begin
  312. if max < min then
  313. begin
  314. temp := min;
  315. min := max;
  316. max := temp;
  317. end;
  318. if w < min then
  319. w := min;
  320. if w > max then
  321. w := max;
  322. end;
  323. //Function copied from BGRABitmap package may work ;-)
  324. function Grayscale(AColor :TColor):TColor;
  325. Var
  326. rColor, gray :Integer;
  327. begin
  328. rColor :=ColorToRGB(AColor);
  329. gray := (Red(rColor) * redWeightShl10 + Green(rColor) * greenWeightShl10 + Blue(rColor) * blueWeightShl10 + 512) shr 10;
  330. Result :=RGBToColor(gray, gray, gray);
  331. end;
  332. function GetHighlightColor(BaseColor: TColor; Value:Integer): TColor;
  333. Var
  334. rColor :Integer;
  335. begin
  336. rColor :=ColorToRGB(BaseColor);
  337. Result := RGBToColor(
  338. Min(Red(rColor) + Value, $FF),
  339. Min(Green(rColor) + Value, $FF),
  340. Min(Blue(rColor) + Value, $FF));
  341. end;
  342. function GetShadowColor(BaseColor: TColor; Value:Integer): TColor;
  343. Var
  344. rColor :Integer;
  345. begin
  346. rColor :=ColorToRGB(BaseColor);
  347. Result := RGBToColor(
  348. Max(Red(rColor) - Value, $22),
  349. Max(Green(rColor) - Value, $22),
  350. Max(Blue(rColor) - Value, $22));
  351. end;
  352. //Canvas Draw Functions
  353. procedure Frame3d_Rounded(Canvas: TCanvas;
  354. var ARect: TRect; const FrameWidth : integer; RX, RY:Integer;
  355. const Style : TGraphicsBevelCut;
  356. ShadowColor, HighlightColor, InternalColor: TColor);
  357. var
  358. DRect: TRect;
  359. procedure drawUP;
  360. begin
  361. inc(DRect.Left,1); inc(DRect.Top,1);
  362. //is outside the Rect but in this way we don't have a hole of 1 px
  363. inc(DRect.Right,1); inc(DRect.Bottom,1);
  364. Canvas.Brush.Color :=ShadowColor;
  365. Canvas.Brush.Style :=bsSolid;
  366. Canvas.Pen.Color := clNone;
  367. Canvas.Pen.Width := 1; //The Shadow is always 1 Pixel
  368. Canvas.Pen.Style := psClear;
  369. Canvas.RoundRect(DRect, RX,RY);
  370. dec(DRect.Left,1); dec(DRect.Top,1);
  371. dec(DRect.Right,2); dec(DRect.Bottom,2);
  372. Canvas.Brush.Color :=InternalColor;
  373. if (InternalColor = clNone)
  374. then Canvas.Brush.Style :=bsClear
  375. else Canvas.Brush.Style :=bsSolid;
  376. Canvas.Pen.Color :=HighlightColor;
  377. Canvas.Pen.Width := FrameWidth;
  378. Canvas.Pen.Style := psSolid;
  379. Canvas.RoundRect(DRect, RX,RY);
  380. Inc(ARect.Top, FrameWidth);
  381. Inc(ARect.Left, FrameWidth);
  382. Dec(ARect.Right, FrameWidth+1); //+The Shadow (1 Pixel) +1?
  383. Dec(ARect.Bottom, FrameWidth+1);
  384. end;
  385. procedure drawFLAT;
  386. begin
  387. Canvas.Brush.Color := InternalColor;
  388. if (InternalColor = clNone)
  389. then Canvas.Brush.Style :=bsClear
  390. else Canvas.Brush.Style :=bsSolid;
  391. Canvas.Pen.Color := clNone;
  392. Canvas.Pen.Width := FrameWidth;
  393. Canvas.Pen.Style := psClear;
  394. Canvas.RoundRect(DRect, RX,RY);
  395. end;
  396. procedure drawDOWN;
  397. begin
  398. Canvas.Brush.Color :=ShadowColor;
  399. Canvas.Brush.Style :=bsSolid;
  400. Canvas.Pen.Color := clNone;
  401. Canvas.Pen.Width := 1;
  402. Canvas.Pen.Style := psClear;
  403. Canvas.RoundRect(DRect, RX,RY);
  404. inc(DRect.Left,1); inc(DRect.Top,1);
  405. Canvas.Brush.Color :=InternalColor;
  406. if (InternalColor = clNone)
  407. then Canvas.Brush.Style :=bsClear
  408. else Canvas.Brush.Style :=bsSolid;
  409. Canvas.Pen.Color :=HighlightColor;
  410. Canvas.Pen.Width := FrameWidth;
  411. Canvas.Pen.Style := psSolid;
  412. Canvas.RoundRect(DRect, RX,RY);
  413. Inc(ARect.Top, FrameWidth+1); //+The Shadow (1 Pixel)
  414. Inc(ARect.Left, FrameWidth+1);
  415. Dec(ARect.Right, FrameWidth);
  416. Dec(ARect.Bottom, FrameWidth);
  417. end;
  418. begin
  419. DRect :=ARect;
  420. Case Style of
  421. bvNone: drawFLAT;
  422. bvSpace: begin
  423. drawFLAT;
  424. InflateRect(ARect, -FrameWidth, -FrameWidth);
  425. end;
  426. bvRaised: drawUP;
  427. bvLowered: drawDOWN;
  428. end;
  429. end;
  430. procedure TBCBoundButton.SetColorHighlight(AValue: TColor);
  431. begin
  432. if (rColorHighlight <> AValue) then
  433. begin
  434. rColorHighlight := AValue;
  435. if not(csLoading in ComponentState)
  436. then Invalidate;
  437. end;
  438. end;
  439. procedure TBCBoundButton.setColorExpanded(AValue: TColor);
  440. begin
  441. if (rColorExpanded <> AValue) then
  442. begin
  443. rColorExpanded := AValue;
  444. if not(csLoading in ComponentState)
  445. then Invalidate;
  446. end;
  447. end;
  448. procedure TBCBoundButton.SetColorShadow(AValue: TColor);
  449. begin
  450. if (rColorShadow <> AValue) then
  451. begin
  452. rColorShadow := AValue;
  453. if not(csLoading in ComponentState)
  454. then Invalidate;
  455. end;
  456. end;
  457. procedure TBCBoundButton.SetGlyphKind(AValue: TGlyphKind);
  458. begin
  459. if (rGlyphKind <> AValue) then
  460. begin
  461. rGlyphKind:=AValue;
  462. if not(csLoading in ComponentState) then
  463. begin
  464. BuildGlyphs;
  465. Invalidate;
  466. end;
  467. end;
  468. end;
  469. procedure TBCBoundButton.SetGlyphLayout(AValue: TGlyphLayout);
  470. begin
  471. if (rGlyphLayout <> AValue) then
  472. begin
  473. rGlyphLayout := AValue;
  474. if not(csLoading in ComponentState) then
  475. begin
  476. BuildGlyphs;
  477. Invalidate;
  478. end;
  479. end;
  480. end;
  481. procedure TBCBoundButton.SetStyle(AValue: TBCBoundButtonStyle);
  482. begin
  483. if (rStyle <> AValue) then
  484. begin
  485. rStyle:=AValue;
  486. if not(csLoading in ComponentState)
  487. then Invalidate;
  488. end;
  489. end;
  490. procedure TBCBoundButton.SetTabWidth(AValue: Integer);
  491. begin
  492. if (rTabWidth <> AValue) then
  493. begin
  494. rTabWidth:=AValue;
  495. if not(csLoading in ComponentState) and (rStyle = bbsTab)
  496. then Invalidate;
  497. end;
  498. end;
  499. procedure TBCBoundButton.SetTextLayout(AValue: TTextLayout);
  500. begin
  501. if (rTextLayout <> AValue) then
  502. begin
  503. rTextLayout := AValue;
  504. if not(csLoading in ComponentState)
  505. then Invalidate;
  506. end;
  507. end;
  508. procedure TBCBoundButton.SetGlyphCollapsed(AValue: TBitmap);
  509. begin
  510. rUserGlyphCollapsed.Assign(AValue);
  511. if not(csLoading in ComponentState) then
  512. begin
  513. BuildGlyphs;
  514. Invalidate;
  515. end;
  516. end;
  517. procedure TBCBoundButton.SetGlyphExpanded(AValue: TBitmap);
  518. begin
  519. rUserGlyphExpanded.Assign(AValue);
  520. if not(csLoading in ComponentState) then
  521. begin
  522. BuildGlyphs;
  523. Invalidate;
  524. end;
  525. end;
  526. procedure TBCBoundButton.LoadGlyph(GlyphDST: TBitmap; ResName: String);
  527. Var
  528. rGlyphO: TPortableNetworkGraphic;
  529. begin
  530. rGlyphO :=TPortableNetworkGraphic.Create;
  531. rGlyphO.LoadFromLazarusResource(ResName);
  532. GlyphDST.Assign(rGlyphO);
  533. FreeAndNil(rGlyphO);
  534. end;
  535. procedure TBCBoundButton.BuildGlyphs;
  536. begin
  537. if (rGlyphLayout <> glNone) then
  538. begin
  539. if (rUserGlyphCollapsed.Empty)
  540. then Case rGlyphKind of
  541. gkArrows: case TBCExpandPanel(Owner).CollapseKind of
  542. akTop: LoadGlyph(rGlyphCollapsed, 'BCEXP_PANEL_BOTTOM');
  543. akLeft: LoadGlyph(rGlyphCollapsed, 'BCEXP_PANEL_RIGHT');
  544. akRight: LoadGlyph(rGlyphCollapsed, 'BCEXP_PANEL_LEFT');
  545. akBottom: LoadGlyph(rGlyphCollapsed, 'BCEXP_PANEL_TOP');
  546. end;
  547. gkClose: LoadGlyph(rGlyphCollapsed, 'BCEXP_PANEL_CLOSE');
  548. gkMinMax: if (TBCExpandPanel(Owner).CollapseKind in [akTop, akBottom])
  549. then LoadGlyph(rGlyphCollapsed, 'BCEXP_PANEL_MAX_H')
  550. else LoadGlyph(rGlyphCollapsed, 'BCEXP_PANEL_MAX_V');
  551. end
  552. else rGlyphCollapsed.Assign(rUserGlyphCollapsed);
  553. if (rUserGlyphExpanded.Empty)
  554. then Case rGlyphKind of
  555. gkArrows: case TBCExpandPanel(Owner).CollapseKind of
  556. akTop: LoadGlyph(rGlyphExpanded, 'BCEXP_PANEL_TOP');
  557. akLeft: LoadGlyph(rGlyphExpanded, 'BCEXP_PANEL_LEFT');
  558. akRight: LoadGlyph(rGlyphExpanded, 'BCEXP_PANEL_RIGHT');
  559. akBottom: LoadGlyph(rGlyphExpanded, 'BCEXP_PANEL_BOTTOM');
  560. end;
  561. gkClose: LoadGlyph(rGlyphExpanded, 'BCEXP_PANEL_CLOSE');
  562. gkMinMax: if (TBCExpandPanel(Owner).CollapseKind in [akTop, akBottom])
  563. then LoadGlyph(rGlyphExpanded, 'BCEXP_PANEL_MIN_H')
  564. else LoadGlyph(rGlyphExpanded, 'BCEXP_PANEL_MIN_V');
  565. end
  566. else rGlyphExpanded.Assign(rUserGlyphExpanded);
  567. end;
  568. end;
  569. procedure TBCBoundButton.Paint;
  570. var
  571. paintRect, fRect :TRect;
  572. xColor,
  573. xHColor,
  574. xSColor :TColor;
  575. middleX,
  576. middleY,
  577. txtWidth,
  578. txtLeft,
  579. txtTop,
  580. glyphLeft,
  581. glyphTop :Integer;
  582. xCaption :String;
  583. FButtonPosition :TAnchorKind;
  584. FCollapsed, Rounded :Boolean;
  585. procedure drawGlyph(var ATop, ALeft :Integer);
  586. var
  587. AWidth, AHeight :Integer;
  588. begin
  589. AWidth :=paintRect.Right-paintRect.Left-2;
  590. AHeight :=paintRect.Bottom-paintRect.Top-2;
  591. if FCollapsed
  592. then rGlyph.Glyph.Assign(rGlyphCollapsed)
  593. else rGlyph.Glyph.Assign(rGlyphExpanded);
  594. //We must Calculate the Real Position of the Glyph
  595. Case FButtonPosition of
  596. akTop,
  597. akBottom : begin
  598. if (rGlyphLayout = glLeft)
  599. then begin
  600. ALeft :=2;
  601. ATop :=middleY-(rGlyph.Glyph.Height div 2);
  602. end
  603. else begin
  604. ALeft :=AWidth-rGlyph.Glyph.Width;
  605. ATop :=middleY-(rGlyph.Glyph.Height div 2);
  606. end;
  607. end;
  608. akLeft :begin
  609. if (rGlyphLayout = glLeft)
  610. then begin //Really on Bottom of paintRect
  611. ALeft :=middleX-(rGlyph.Glyph.Width div 2);
  612. ATop :=AHeight-rGlyph.Glyph.Height;
  613. end
  614. else begin //Really on Top of paintRect
  615. ALeft :=middleX-(rGlyph.Glyph.Width div 2);
  616. ATop :=2;
  617. end;
  618. end;
  619. akRight :begin
  620. if (rGlyphLayout = glLeft)
  621. then begin //Really on Top of paintRect
  622. ALeft :=middleX-(rGlyph.Glyph.Width div 2);
  623. ATop :=2;
  624. end
  625. else begin //Really on Bottom of paintRect
  626. ALeft :=middleX-(rGlyph.Glyph.Width div 2);
  627. ATop :=AHeight-rGlyph.Glyph.Height;
  628. end;
  629. end;
  630. end;
  631. rGlyph.Draw(Canvas, paintRect, point(ALeft, ATop), FState, true, 0);
  632. end;
  633. procedure drawBtn(const ABorderStyle : TGraphicsBevelCut);
  634. var
  635. xTabWidth,
  636. tY, tX: Integer;
  637. begin
  638. Case rStyle of
  639. bbsButton: Frame3d_Rounded(Canvas, paintRect, 1, 5, 5, ABorderStyle, xSColor, xHColor, xColor);
  640. bbsTab: begin
  641. fRect :=paintRect;
  642. Case FButtonPosition of
  643. akTop : begin
  644. //If rTabWidth is Negative Calculate the Tab Width
  645. if (rTabWidth < 0)
  646. then xTabWidth :=(fRect.Right-fRect.Left)*-rTabWidth div 100
  647. else xTabWidth :=rTabWidth;
  648. inc(paintRect.Left, middleX-(xTabWidth div 2));
  649. paintRect.Right:=paintRect.Left+xTabWidth;
  650. Frame3d_Rounded(Canvas, paintRect, 1, 5, 5, ABorderStyle, xSColor, xHColor, xColor);
  651. tY :=fRect.Bottom-2;
  652. Canvas.Pen.Style:=psSolid;
  653. Canvas.Pen.Width:=1;
  654. Canvas.Pen.Color :=xHColor;
  655. if Rounded
  656. then Canvas.MoveTo(2, tY)
  657. else Canvas.MoveTo(0, tY);
  658. Canvas.LineTo(paintRect.Left-3, tY);
  659. Canvas.LineTo(paintRect.Left, tY-3);
  660. if Rounded
  661. then Canvas.MoveTo(fRect.Right-4, tY)
  662. else Canvas.MoveTo(fRect.Right, tY);
  663. Canvas.LineTo(paintRect.Right+2, tY);
  664. Canvas.LineTo(paintRect.Right-1, tY-3);
  665. Canvas.Pen.Color :=xColor;
  666. Canvas.MoveTo(paintRect.Left-2, tY);
  667. Canvas.LineTo(paintRect.Right+2, tY);
  668. dec(tY);
  669. Canvas.MoveTo(paintRect.Left-1, tY);
  670. Canvas.LineTo(paintRect.Right+1, tY);
  671. tY :=fRect.Bottom-1;
  672. if FCollapsed then Canvas.Pen.Color :=xSColor;
  673. if Rounded
  674. then begin
  675. Canvas.MoveTo(fRect.Left+2, tY);
  676. Canvas.LineTo(fRect.Right-3, tY);
  677. end
  678. else begin
  679. Canvas.MoveTo(fRect.Left, tY);
  680. Canvas.LineTo(fRect.Right, tY);
  681. end;
  682. end;
  683. akBottom : begin
  684. if (rTabWidth < 0)
  685. then xTabWidth :=(fRect.Right-fRect.Left)*-rTabWidth div 100
  686. else xTabWidth :=rTabWidth;
  687. inc(paintRect.Left, middleX-(xTabWidth div 2));
  688. paintRect.Right:=paintRect.Left+xTabWidth;
  689. dec(paintRect.Top);
  690. Frame3d_Rounded(Canvas, paintRect, 1, 5, 5, ABorderStyle, xSColor, xHColor, xColor);
  691. Canvas.Pen.Style:=psSolid;
  692. Canvas.Pen.Width:=1;
  693. Canvas.Pen.Color :=xHColor;
  694. if Rounded
  695. then Canvas.MoveTo(2, 1)
  696. else Canvas.MoveTo(0, 1);
  697. Canvas.LineTo(paintRect.Left-3, 1);
  698. Canvas.LineTo(paintRect.Left, 4);
  699. if Rounded
  700. then Canvas.MoveTo(fRect.Right-4, 1)
  701. else Canvas.MoveTo(fRect.Right, 1);
  702. Canvas.LineTo(paintRect.Right+2, 1);
  703. Canvas.LineTo(paintRect.Right-1, 4);
  704. Canvas.Pen.Color :=xColor;
  705. Canvas.MoveTo(paintRect.Left-2, 1);
  706. Canvas.LineTo(paintRect.Right+2, 1);
  707. Canvas.MoveTo(paintRect.Left-1, 2);
  708. Canvas.LineTo(paintRect.Right+1, 2);
  709. if FCollapsed then Canvas.Pen.Color :=xSColor;
  710. if Rounded
  711. then begin
  712. Canvas.MoveTo(fRect.Left+2, 0);
  713. Canvas.LineTo(fRect.Right-3, 0);
  714. end
  715. else begin
  716. Canvas.MoveTo(fRect.Left, 0);
  717. Canvas.LineTo(fRect.Right, 0);
  718. end;
  719. end;
  720. akLeft : begin
  721. if (rTabWidth < 0)
  722. then xTabWidth :=(fRect.Bottom-fRect.Top)*-rTabWidth div 100
  723. else xTabWidth :=rTabWidth;
  724. inc(paintRect.Top, middleY-(xTabWidth div 2));
  725. paintRect.Bottom:=paintRect.Top+xTabWidth;
  726. Frame3d_Rounded(Canvas, paintRect, 1, 5, 5, ABorderStyle, xSColor, xHColor, xColor);
  727. tX :=fRect.Right-2;
  728. Canvas.Pen.Style:=psSolid;
  729. Canvas.Pen.Width:=1;
  730. Canvas.Pen.Color :=xHColor;
  731. if Rounded
  732. then Canvas.MoveTo(tX, 2)
  733. else Canvas.MoveTo(tX, 0);
  734. Canvas.LineTo(tX, paintRect.Top-3);
  735. Canvas.LineTo(tX-3, paintRect.Top);
  736. if Rounded
  737. then Canvas.MoveTo(tX, fRect.Bottom-4)
  738. else Canvas.MoveTo(tX, fRect.Bottom);
  739. Canvas.LineTo(tX, paintRect.Bottom+2);
  740. Canvas.LineTo(tX-3, paintRect.Bottom-1);
  741. Canvas.Pen.Color :=xColor;
  742. Canvas.MoveTo(tX, paintRect.Top-2);
  743. Canvas.LineTo(tX, paintRect.Bottom+2);
  744. dec(tX);
  745. Canvas.MoveTo(tX, paintRect.Top-1);
  746. Canvas.LineTo(tX, paintRect.Bottom+1);
  747. tX :=fRect.Right-1;
  748. if FCollapsed then Canvas.Pen.Color :=xSColor;
  749. if Rounded
  750. then begin
  751. Canvas.MoveTo(tX, fRect.Top+2);
  752. Canvas.LineTo(tX, fRect.Bottom-3);
  753. end
  754. else begin
  755. Canvas.MoveTo(tX, fRect.Top);
  756. Canvas.LineTo(tX, fRect.Bottom);
  757. end;
  758. end;
  759. akRight : begin
  760. if (rTabWidth < 0)
  761. then xTabWidth :=(fRect.Bottom-fRect.Top)*-rTabWidth div 100
  762. else xTabWidth :=rTabWidth;
  763. inc(paintRect.Top, middleY-(xTabWidth div 2));
  764. paintRect.Bottom:=paintRect.Top+xTabWidth;
  765. dec(paintRect.Left);
  766. Frame3d_Rounded(Canvas, paintRect, 1, 5, 5, ABorderStyle, xSColor, xHColor, xColor);
  767. Canvas.Pen.Style:=psSolid;
  768. Canvas.Pen.Width:=1;
  769. Canvas.Pen.Color :=xHColor;
  770. if Rounded
  771. then Canvas.MoveTo(1, 2)
  772. else Canvas.MoveTo(1, 0);
  773. Canvas.LineTo(1, paintRect.Top-3);
  774. Canvas.LineTo(4, paintRect.Top);
  775. if Rounded
  776. then Canvas.MoveTo(1, fRect.Bottom-4)
  777. else Canvas.MoveTo(1, fRect.Bottom);
  778. Canvas.LineTo(1, paintRect.Bottom+2);
  779. Canvas.LineTo(4, paintRect.Bottom-1);
  780. Canvas.Pen.Color :=xColor;
  781. Canvas.MoveTo(1, paintRect.Top-2);
  782. Canvas.LineTo(1, paintRect.Bottom+2);
  783. Canvas.MoveTo(2, paintRect.Top-1);
  784. Canvas.LineTo(2, paintRect.Bottom+1);
  785. if FCollapsed then Canvas.Pen.Color :=xSColor;
  786. if Rounded
  787. then begin
  788. Canvas.MoveTo(0, fRect.Top+2);
  789. Canvas.LineTo(0, fRect.Bottom-3);
  790. end
  791. else begin
  792. Canvas.MoveTo(0, fRect.Top);
  793. Canvas.LineTo(0, fRect.Bottom);
  794. end;
  795. end;
  796. end;
  797. end;
  798. end;
  799. end;
  800. procedure drawText;
  801. Var
  802. DTop, DLeft,
  803. AWidth, AHeight,
  804. txtH :Integer;
  805. procedure CalcCuttedCaption(MaxWidth :Integer);
  806. Var
  807. txtMaxChars :Integer;
  808. begin
  809. txtWidth :=0;
  810. if (MaxWidth < Canvas.TextWidth('...'))
  811. then xCaption :=''
  812. else begin
  813. txtMaxChars :=Canvas.TextFitInfo(xCaption, MaxWidth);
  814. txtWidth :=Canvas.TextWidth(xCaption);
  815. while (txtWidth > MaxWidth) do
  816. begin
  817. dec(txtMaxChars, 3); //-1 Chars fit better, -3 Chars for more speed
  818. xCaption :=Copy(xCaption, 0, txtMaxChars)+'...';
  819. txtWidth :=Canvas.TextWidth(xCaption);
  820. end;
  821. end;
  822. (* Original Code, Test Speed
  823. if (txtW > AWidth)
  824. then begin
  825. txtMaxChars :=Canvas.TextFitInfo(xCaption, AWidth);
  826. xCaption :=Copy(xCaption, 0, txtMaxChars-3)+'...';
  827. txtW :=Canvas.TextWidth(xCaption);
  828. if (txtW > AWidth)
  829. then xCaption :='';
  830. end;
  831. *)
  832. end;
  833. begin
  834. txtH :=Canvas.TextHeight(xCaption);
  835. AWidth :=paintRect.Right-paintRect.Left-2;
  836. AHeight :=paintRect.Bottom-paintRect.Top-2;
  837. Case FButtonPosition of
  838. akTop,
  839. akBottom : begin
  840. Canvas.Font.Orientation := 0;
  841. txtTop :=middleY-(txtH div 2);
  842. if (rGlyphLayout <> glNone) then
  843. begin
  844. if (rTextLayout = tlCenter)
  845. then dec(AWidth, rGlyph.Glyph.Width*2+4)
  846. else dec(AWidth, rGlyph.Glyph.Width+2)
  847. end;
  848. CalcCuttedCaption(AWidth);
  849. Case rTextLayout of
  850. tlLeft :begin
  851. txtLeft :=paintRect.Left+4;
  852. if (rGlyphLayout = glLeft)
  853. then inc(txtLeft, rGlyph.Glyph.Width+2);
  854. end;
  855. tlRight:begin
  856. txtLeft :=paintRect.Left+AWidth-txtWidth;
  857. if (rGlyphLayout = glLeft)
  858. then inc(txtLeft, rGlyph.Glyph.Width+2);
  859. end;
  860. tlCenter:begin
  861. txtLeft :=middleX-(txtWidth div 2);
  862. end;
  863. end;
  864. //Disabled Position
  865. DTop :=txtTop+1;
  866. DLeft :=txtLeft+1;
  867. end;
  868. akLeft : begin
  869. //Vertically from Bottom to Top
  870. Canvas.Font.Orientation := 900;
  871. txtLeft:=middleX-(txtH div 2);
  872. if (rGlyphLayout <> glNone) then
  873. begin
  874. if (rTextLayout = tlCenter)
  875. then dec(AHeight, rGlyph.Glyph.Height*2+4)
  876. else dec(AHeight, rGlyph.Glyph.Height+2)
  877. end;
  878. //Vertically the Max Width is Height
  879. CalcCuttedCaption(AHeight);
  880. Case rTextLayout of
  881. tlLeft :begin //To Bottom of the ClientRect
  882. txtTop :=paintRect.Top+AHeight-2;
  883. if (rGlyphLayout = glRight)
  884. then inc(txtTop, rGlyph.Glyph.Height+2);
  885. end;
  886. tlRight:begin //To Top of the ClientRect
  887. txtTop :=paintRect.Top+txtWidth+2;
  888. if (rGlyphLayout = glRight)
  889. then inc(txtTop, rGlyph.Glyph.Height+2);
  890. end;
  891. tlCenter:begin
  892. txtTop :=middleY+(txtWidth div 2);
  893. end;
  894. end;
  895. //Disabled Position
  896. DTop :=txtTop-1;
  897. DLeft :=txtLeft+1;
  898. end;
  899. akRight : begin
  900. //Vertically from Top to Bottom
  901. Canvas.Font.Orientation := -900;
  902. txtLeft:=middleX+(txtH div 2)+1; //+1 because is better centered
  903. if (rGlyphLayout <> glNone) then
  904. begin
  905. if (rTextLayout = tlCenter)
  906. then dec(AHeight, rGlyph.Glyph.Height*2+4)
  907. else dec(AHeight, rGlyph.Glyph.Height+2)
  908. end;
  909. CalcCuttedCaption(AHeight);
  910. Case rTextLayout of
  911. tlLeft :begin //To Top of the ClientRect
  912. txtTop :=paintRect.Top+4;
  913. if (rGlyphLayout = glLeft)
  914. then inc(txtTop, rGlyph.Glyph.Height+2);
  915. end;
  916. tlRight:begin //To Bottom of the ClientRect
  917. txtTop :=paintRect.Top+AHeight-txtWidth;
  918. if (rGlyphLayout = glLeft)
  919. then inc(txtTop, rGlyph.Glyph.Height+2);
  920. end;
  921. tlCenter:begin
  922. txtTop :=middleY-(txtWidth div 2);
  923. end;
  924. end;
  925. //Disabled Position
  926. DTop :=txtTop+1;
  927. DLeft :=txtLeft-1;
  928. end;
  929. end;
  930. //Re Test here because we may not have space to draw the text, so now can be empty
  931. if (xCaption <> '') then
  932. begin
  933. if (FState = bsDisabled)
  934. then begin
  935. Canvas.Font.Color := clBtnHighlight;
  936. Canvas.TextOut(DLeft, DTop, xCaption);
  937. Canvas.Font.Color := clBtnShadow;
  938. end
  939. else Canvas.Font.Color := Font.Color;
  940. Canvas.Brush.Style:=bsClear;
  941. Canvas.TextOut(txtLeft, txtTop, xCaption);
  942. end
  943. else txtWidth:=0;
  944. end;
  945. procedure DrawLines;
  946. var
  947. d1, d2, d3, d4, dx :Integer;
  948. isVertical :Boolean;
  949. procedure calc_d(txtL, txtR, glyphL, glyphR :Integer);
  950. begin
  951. if (txtWidth > 0)
  952. then Case rTextLayout of
  953. tlLeft: begin
  954. d1 :=txtR;
  955. if (rGlyphLayout = glRight)
  956. then d2 :=glyphL;
  957. end;
  958. tlCenter:begin
  959. d2 :=txtL;
  960. d3 :=txtR;
  961. if (rGlyphLayout = glLeft)
  962. then d1 :=glyphR
  963. else if (rGlyphLayout = glRight)
  964. then d4 :=glyphL;
  965. end;
  966. tlRight:begin
  967. d2 :=txtL;
  968. if (rGlyphLayout = glLeft)
  969. then d1 :=glyphR;
  970. end;
  971. end
  972. else if (rGlyphLayout = glLeft)
  973. then d1 :=glyphR
  974. else if (rGlyphLayout = glRight)
  975. then d2 :=glyphL;
  976. end;
  977. procedure DrawALine(pCenterX, pCenterY :Integer);
  978. begin
  979. inc(d2); inc(d4); //LineTo don't paint the last Pixel
  980. if isVertical
  981. then begin
  982. //Avoid go outside the Box
  983. pCenterX :=EnsureRange(pCenterX, 0, paintRect.Right-2);
  984. Canvas.Pen.Color := {$ifdef DEBUG_PAINT} clLime {$else} xHColor {$endif};
  985. Canvas.MoveTo(pCenterX, d1);
  986. Canvas.LineTo(pCenterX, d2);
  987. if (d3 > -1) then
  988. begin
  989. Canvas.MoveTo(pCenterX, d3);
  990. Canvas.LineTo(pCenterX, d4);
  991. end;
  992. Canvas.Pen.Color := {$ifdef DEBUG_PAINT} clGreen {$else} xSColor {$endif};
  993. Canvas.MoveTo(pCenterX+1, d1+1);
  994. Canvas.LineTo(pCenterX+1, d2);
  995. if (d3 > -1) then
  996. begin
  997. Canvas.MoveTo(pCenterX+1, d3+1);
  998. Canvas.LineTo(pCenterX+1, d4);
  999. end;
  1000. end
  1001. else begin
  1002. pCenterY :=EnsureRange(pCenterY, 0, paintRect.Bottom-2);
  1003. Canvas.Pen.Color :={$ifdef DEBUG_PAINT} clLime {$else} xHColor {$endif};
  1004. Canvas.MoveTo(d1, pCenterY);
  1005. Canvas.LineTo(d2, pCenterY);
  1006. if (d3 > -1) then
  1007. begin
  1008. Canvas.MoveTo(d3, pCenterY);
  1009. Canvas.LineTo(d4, pCenterY);
  1010. end;
  1011. Canvas.Pen.Color :={$ifdef DEBUG_PAINT} clGreen {$else} xSColor {$endif};
  1012. Canvas.MoveTo(d1+1, pCenterY+1);
  1013. Canvas.LineTo(d2, pCenterY+1);
  1014. if (d3 > -1) then
  1015. begin
  1016. Canvas.MoveTo(d3+1, pCenterY+1);
  1017. Canvas.LineTo(d4, pCenterY+1);
  1018. end;
  1019. end;
  1020. dec(d2); dec(d4); //return to the real Pixels
  1021. end;
  1022. begin
  1023. d3 :=-1;
  1024. isVertical :=(FButtonPosition in [akLeft, akRight]);
  1025. //Assign to (d1-d2) Line All the space
  1026. if isVertical
  1027. then begin
  1028. d1 :=paintRect.Top;
  1029. d2 :=paintRect.Bottom-1;
  1030. end
  1031. else begin
  1032. d1 :=paintRect.Left;
  1033. d2 :=paintRect.Right-1;
  1034. end;
  1035. //Calculate the (d1-d2) (d3-d4) Lines between the Glyph and the Text elements
  1036. if (rStyle in [bbsLine, bbsLineDouble]) then
  1037. begin
  1038. d4 :=d2;
  1039. if isVertical
  1040. then begin
  1041. if (FButtonPosition = akRight)
  1042. then calc_d(txtTop-3, txtTop+txtWidth+2, glyphTop-3, glyphTop+rGlyph.Glyph.Height+2)
  1043. else begin
  1044. //Only in this case (akLeft) the point coordinate is from bottom to top
  1045. d1 :=paintRect.Bottom-1;
  1046. d2 :=paintRect.Top;
  1047. d4 :=d2;
  1048. calc_d(txtTop+2, txtTop-txtWidth-3, glyphTop+rGlyph.Glyph.Height+2, glyphTop-3);
  1049. //Exchange the values for Shadow coerence
  1050. dx :=d1; d1 :=d2; d2 :=dx;
  1051. if (d3 > -1) then begin dx :=d3; d3 :=d4; d4 :=dx; end;
  1052. end;
  1053. end
  1054. else calc_d(txtLeft-3, txtLeft+txtWidth+2, glyphLeft-3, glyphLeft+rGlyph.Glyph.Width+2);
  1055. end;
  1056. //Draw the Lines
  1057. Canvas.Pen.Style:=psSolid;
  1058. Canvas.Pen.Width:=1;
  1059. Case rStyle of
  1060. bbsLine: DrawALine(middleX, middleY);
  1061. bbsLineDouble: begin
  1062. DrawALine(middleX-2, middleY-2);
  1063. DrawALine(middleX+2, middleY+2);
  1064. end;
  1065. bbsLineTop: DrawALine(paintRect.Left, paintRect.Top);
  1066. bbsLineBottom: DrawALine(paintRect.Right-2, paintRect.Bottom-2);
  1067. bbsLineDoubleTop: begin
  1068. DrawALine(paintRect.Left, paintRect.Top);
  1069. DrawALine(paintRect.Left+3, paintRect.Top+3);
  1070. end;
  1071. bbsLineDoubleBottom: begin
  1072. DrawALine(paintRect.Right-5, paintRect.Bottom-5);
  1073. DrawALine(paintRect.Right-2, paintRect.Bottom-2);
  1074. end;
  1075. end;
  1076. end;
  1077. begin
  1078. paintRect :=GetClientRect;
  1079. {$ifdef DEBUG_PAINT}
  1080. Canvas.Brush.Color:=clYellow;
  1081. Canvas.Brush.Style:=bsSolid;
  1082. Canvas.FillRect(paintRect);
  1083. {$endif}
  1084. middleY :=paintRect.Top+((paintRect.Bottom-paintRect.Top) div 2);
  1085. middleX :=paintRect.Left+((paintRect.Right-paintRect.Left) div 2);
  1086. FButtonPosition :=TBCExpandPanel(Owner).FButtonPosition;
  1087. FCollapsed :=TBCExpandPanel(Owner).FCollapsed;
  1088. Rounded :=not(FCollapsed) and TBCExpandPanel(Owner).rBevelRounded;
  1089. if FCollapsed
  1090. then xColor :=Self.Color
  1091. else xColor :=rColorExpanded;
  1092. xCaption :=Caption;
  1093. Case FState of
  1094. Buttons.bsHot:begin
  1095. if (rColorHighlight = clDefault)
  1096. then xHColor :=GetHighlightColor(xColor, 120)
  1097. else xHColor :=rColorHighlight;
  1098. if (rColorShadow = clDefault)
  1099. then xSColor :=GetShadowColor(xColor, 40)
  1100. else xSColor :=rColorShadow;
  1101. xColor :=GetHighlightColor(xColor, 20);
  1102. drawBtn(bvRaised);
  1103. end;
  1104. Buttons.bsDown:begin
  1105. if (rColorHighlight = clDefault)
  1106. then xHColor :=GetHighlightColor(xColor, 60)
  1107. else xHColor :=rColorHighlight;
  1108. if (rColorShadow = clDefault)
  1109. then xSColor :=GetShadowColor(xColor, 60)
  1110. else xSColor :=rColorShadow;
  1111. xColor :=GetHighlightColor(xColor, 20);
  1112. drawBtn(bvLowered);
  1113. end;
  1114. else begin
  1115. if (FState = bsDisabled)
  1116. then xColor :=GrayScale(xColor);
  1117. if Flat
  1118. then xHColor :=xColor
  1119. else if (rColorHighlight = clDefault)
  1120. then xHColor :=GetHighlightColor(xColor, 60)
  1121. else xHColor :=rColorHighlight;
  1122. if (rColorShadow = clDefault)
  1123. then xSColor :=GetShadowColor(xColor, 60)
  1124. else xSColor :=rColorShadow;
  1125. if Flat
  1126. then drawBtn(bvSpace)
  1127. else drawBtn(bvRaised);
  1128. end;
  1129. end;
  1130. if (rGlyphLayout <> glNone)
  1131. then drawGlyph(glyphTop, glyphLeft)
  1132. else begin
  1133. glyphTop :=0;
  1134. glyphLeft:=0;
  1135. end;
  1136. if (rTextLayout <> tlNone) and (xCaption <> '')
  1137. then drawText
  1138. else txtWidth:=0;
  1139. if (rStyle in [bbsLine..bbsLineDoubleBottom])
  1140. then DrawLines;
  1141. end;
  1142. procedure TBCBoundButton.Loaded;
  1143. begin
  1144. inherited Loaded;
  1145. if not(csDesigning in ComponentState) then
  1146. begin
  1147. //IF Used Outside TBCExpandPanel
  1148. if not(Owner is TBCExpandPanel)
  1149. then BuildGlyphs;
  1150. end;
  1151. end;
  1152. constructor TBCBoundButton.Create(AOwner: TComponent);
  1153. begin
  1154. inherited Create(AOwner);
  1155. Color :=clSkyBlue;
  1156. rColorExpanded := RGBToColor(23, 136, 248);
  1157. rColorHighlight :=clDefault;
  1158. rColorShadow :=clDefault;
  1159. rGlyphLayout :=glNone;
  1160. rGlyphKind :=gkArrows;
  1161. rTextLayout :=tlLeft;
  1162. Flat :=False;
  1163. rStyle :=bbsButton;
  1164. rTabWidth :=-50;
  1165. //Why FGlyph is Private in ancestor?????
  1166. rGlyph := TButtonGlyph.Create;
  1167. rGlyph.IsDesigning := csDesigning in ComponentState;
  1168. rGlyph.ShowMode := gsmAlways;
  1169. rGlyphExpanded :=TBitmap.Create;
  1170. rGlyphExpanded.Transparent := True;
  1171. rGlyphCollapsed :=TBitmap.Create;
  1172. rGlyphCollapsed.Transparent := True;
  1173. rUserGlyphExpanded :=TBitmap.Create;
  1174. rUserGlyphExpanded.Transparent := True;
  1175. rUserGlyphCollapsed :=TBitmap.Create;
  1176. rUserGlyphCollapsed.Transparent := True;
  1177. SetSubComponent((Owner is TBCExpandPanel));
  1178. // ControlStyle := ControlStyle + [csNoFocus, csNoDesignSelectable];
  1179. end;
  1180. destructor TBCBoundButton.Destroy;
  1181. begin
  1182. FreeAndNil(rGlyphExpanded);
  1183. FreeAndNil(rGlyphCollapsed);
  1184. FreeAndNil(rUserGlyphExpanded);
  1185. FreeAndNil(rUserGlyphCollapsed);
  1186. FreeAndNil(rGlyph);
  1187. inherited Destroy;
  1188. end;
  1189. {TBCExpandPanels}
  1190. constructor TBCExpandPanels.Create(AOwner: TComponent);
  1191. begin
  1192. inherited Create(AOwner);
  1193. PanelArray := TList.Create;
  1194. FCollapseKind := akTop;
  1195. FButtonPosition := akTop;
  1196. FButtonGlyphKind :=gkArrows;
  1197. FButtonGlyphLayout :=glNone;
  1198. FButtonStyle :=bbsButton;
  1199. FButtonTabWidth :=-50;
  1200. FButtonTextLayout :=tlLeft;
  1201. FArrangeKind := akTop;
  1202. FUseFixedSize := False;
  1203. FUseClientSize := False;
  1204. FFixedSize := 400;
  1205. FAutoCollapseIfTooHigh := False;
  1206. FAbove := 10;
  1207. FOrthogonalAbove := 10;
  1208. FOrthogonalSize := 200;
  1209. end;
  1210. destructor TBCExpandPanels.Destroy;
  1211. var
  1212. i: integer;
  1213. begin
  1214. for I := PanelArray.Count - 1 downto 0 do
  1215. PanelArray.Delete(i);
  1216. PanelArray.Free;
  1217. PanelArray := nil;
  1218. inherited Destroy;
  1219. end;
  1220. procedure TBCExpandPanels.AddPanel(rollout: TBCExpandPanel);
  1221. begin
  1222. InsertPanel(PanelArray.Count, rollout);
  1223. end;
  1224. procedure TBCExpandPanels.InsertPanel(idx: integer; rollout: TBCExpandPanel);
  1225. begin
  1226. if Count <= 0 then
  1227. begin
  1228. FAbove := RelevantAbove(rollout);
  1229. FOrthogonalAbove := RelevantOrthogonalAbove(rollout);
  1230. FOrthogonalSize := RelevantOrthogonalSize(rollout);
  1231. end
  1232. else
  1233. begin
  1234. WriteRelevantAbove(rollout, FAbove);
  1235. WriteRelevantOrthogonalAbove(rollout, FOrthogonalAbove);
  1236. WriteRelevantOrthogonalSize(rollout, FOrthogonalSize);
  1237. end;
  1238. with rollout do
  1239. begin
  1240. Tag := Idx;
  1241. FButton.Tag := Idx;
  1242. FButton.OnMouseMove := @RollOut1MouseMove;
  1243. InternalOnAnimate := @RollOutOnAnimate;
  1244. end;
  1245. PanelArray.Insert(idx, rollout);
  1246. if FBehaviour <> EPMultipanel then
  1247. HotTrackSetActivePanel(0); //damit das erste ausgeklappt ist
  1248. ArrangePanels;
  1249. MakeCorrectButtonClickPointers;
  1250. end;
  1251. function TBCExpandPanels.DeltePanel(aname: string): boolean;
  1252. var
  1253. i: integer;
  1254. begin
  1255. Result := False;
  1256. for i := 0 to PanelArray.Count - 1 do
  1257. if TBCExpandPanel(PanelArray[i]).Name = aname then
  1258. begin
  1259. PanelArray.Delete(i);
  1260. Result := True;
  1261. break;
  1262. end;
  1263. ArrangePanels;
  1264. end;
  1265. function TBCExpandPanels.DeltePanel(idx: integer): boolean;
  1266. begin
  1267. Result := False;
  1268. if (idx >= 0) and (idx <= PanelArray.Count - 1) then
  1269. begin
  1270. PanelArray.Delete(idx);
  1271. Result := True;
  1272. end;
  1273. ArrangePanels;
  1274. end;
  1275. procedure TBCExpandPanels.DelteLastPanel;
  1276. begin
  1277. if (PanelArray.Count >= 1) then
  1278. PanelArray.Delete(PanelArray.Count - 1);
  1279. ArrangePanels;
  1280. end;
  1281. procedure TBCExpandPanels.DelLastPanel;
  1282. begin
  1283. PanelArray.Delete(PanelArray.Count - 1);
  1284. end;
  1285. function TBCExpandPanels.RelevantAbove(comp: TControl): integer;
  1286. begin
  1287. case FArrangeKind of
  1288. akLeft: Result := comp.Left;
  1289. akTop: Result := comp.Top;
  1290. end;
  1291. end;
  1292. function TBCExpandPanels.RelevantOrthogonalAbove(comp: TControl): integer;
  1293. begin
  1294. case FArrangeKind of
  1295. akTop: Result := comp.Left;
  1296. akLeft: Result := comp.Top;
  1297. end;
  1298. end;
  1299. function TBCExpandPanels.RelevantSize(comp: TControl): integer;
  1300. begin
  1301. case FArrangeKind of
  1302. akLeft: Result := comp.Width;
  1303. akTop: Result := comp.Height;
  1304. end;
  1305. end;
  1306. function TBCExpandPanels.RelevantOrthogonalSize(comp: TControl): integer;
  1307. begin
  1308. case FArrangeKind of
  1309. akLeft: Result := comp.Height;
  1310. akTop: Result := comp.Width;
  1311. end;
  1312. end;
  1313. procedure TBCExpandPanels.setButtonGlyphKind(AValue: TGlyphKind);
  1314. var
  1315. i: Integer;
  1316. begin
  1317. if (FButtonGlyphKind <> AValue) then
  1318. begin
  1319. FButtonGlyphKind:=AValue;
  1320. for i := 0 to PanelArray.Count - 1 do
  1321. Panel(i).Button.GlyphKind := AValue;
  1322. end;
  1323. end;
  1324. procedure TBCExpandPanels.setButtonGlyphLayout(AValue: TGlyphLayout);
  1325. var
  1326. i: Integer;
  1327. begin
  1328. if (FButtonGlyphLayout <> AValue) then
  1329. begin
  1330. FButtonGlyphLayout:=AValue;
  1331. for i := 0 to PanelArray.Count - 1 do
  1332. Panel(i).Button.GlyphLayout := AValue;
  1333. end;
  1334. end;
  1335. procedure TBCExpandPanels.setButtonStyle(AValue: TBCBoundButtonStyle);
  1336. var
  1337. i: Integer;
  1338. begin
  1339. if (FButtonStyle <> AValue) then
  1340. begin
  1341. FButtonStyle:=AValue;
  1342. for i := 0 to PanelArray.Count - 1 do
  1343. Panel(i).Button.Style := AValue;
  1344. end;
  1345. end;
  1346. procedure TBCExpandPanels.SetButtonTabWidth(AValue: Integer);
  1347. var
  1348. i: Integer;
  1349. begin
  1350. if (FButtonTabWidth <> AValue) then
  1351. begin
  1352. FButtonTabWidth:=AValue;
  1353. for i := 0 to PanelArray.Count - 1 do
  1354. Panel(i).Button.TabWidth := AValue;
  1355. end;
  1356. end;
  1357. procedure TBCExpandPanels.setButtonTextLayout(AValue: TTextLayout);
  1358. var
  1359. i: Integer;
  1360. begin
  1361. if (FButtonTextLayout <> AValue) then
  1362. begin
  1363. FButtonTextLayout:=AValue;
  1364. for i := 0 to PanelArray.Count - 1 do
  1365. Panel(i).Button.TextLayout := AValue;
  1366. end;
  1367. end;
  1368. procedure TBCExpandPanels.WriteRelevantAbove(comp: TBCExpandPanel; above: integer);
  1369. begin
  1370. case FArrangeKind of
  1371. akLeft: comp.Left := above;
  1372. akTop: comp.Top := above;
  1373. end;
  1374. end;
  1375. procedure TBCExpandPanels.WriteRelevantSize(comp: TBCExpandPanel; size: integer);
  1376. begin
  1377. case FArrangeKind of
  1378. akLeft: comp.Width := size;
  1379. akTop: comp.Height := size;
  1380. end;
  1381. end;
  1382. procedure TBCExpandPanels.WriteRelevantOrthogonalSize(comp: TBCExpandPanel; size: integer);
  1383. begin
  1384. case FArrangeKind of
  1385. akLeft: comp.Height := size;
  1386. akTop: comp.Width := size;
  1387. end;
  1388. end;
  1389. procedure TBCExpandPanels.WriteRelevantOrthogonalAbove(comp: TBCExpandPanel; size: integer);
  1390. begin
  1391. case FArrangeKind of
  1392. akLeft: comp.Top := size;
  1393. akTop: comp.Left := size;
  1394. end;
  1395. end;
  1396. procedure TBCExpandPanels.setArrangeKind(Value: TAnchorKind);
  1397. begin
  1398. case Value of //that is mean, but I haven't implemented the bottom and right yet....
  1399. akRight: Value := akLeft;
  1400. akBottom: Value := akTop;
  1401. end;
  1402. if FArrangeKind = Value then
  1403. exit;
  1404. FArrangeKind := Value;
  1405. ArrangePanels;
  1406. end;
  1407. procedure TBCExpandPanels.setButtonPosition(Value: TAnchorKind);
  1408. var
  1409. i: integer;
  1410. begin
  1411. if FButtonPosition = Value then
  1412. exit;
  1413. FButtonPosition := Value;
  1414. for i := 0 to PanelArray.Count - 1 do
  1415. Panel(i).ButtonPosition := Value;
  1416. end;
  1417. procedure TBCExpandPanels.setCollapseKind(Value: TAnchorKind);
  1418. var
  1419. i: integer;
  1420. begin
  1421. if FCollapseKind = Value then
  1422. exit;
  1423. FCollapseKind := Value;
  1424. for i := 0 to PanelArray.Count - 1 do
  1425. Panel(i).CollapseKind := Value;
  1426. end;
  1427. procedure TBCExpandPanels.setUseClientSize(Value: boolean);
  1428. begin
  1429. FUseClientSize := Value;
  1430. ArrangePanels;
  1431. end;
  1432. procedure TBCExpandPanels.setUseFixedSize(Value: boolean);
  1433. begin
  1434. if FUseFixedSize = Value then
  1435. exit;
  1436. FUseFixedSize := Value;
  1437. ArrangePanels;
  1438. end;
  1439. procedure TBCExpandPanels.setAutoCollapseIfTooHigh(Value: boolean);
  1440. begin
  1441. if FAutoCollapseIfTooHigh = Value then
  1442. exit;
  1443. FAutoCollapseIfTooHigh := Value;
  1444. if FAutoCollapseIfTooHigh then
  1445. CollapseIfTooHigh;
  1446. end;
  1447. procedure TBCExpandPanels.setFixedSize(Value: integer);
  1448. var
  1449. r: real;
  1450. begin
  1451. if FFixedSize = Value then
  1452. exit;
  1453. r := Value;
  1454. korrigiere(r, 20, 10000);
  1455. FFixedSize := round(r);
  1456. ArrangePanels;
  1457. end;
  1458. procedure TBCExpandPanels.setOrthogonalAbove(Value: integer);
  1459. begin
  1460. if FOrthogonalAbove = Value then
  1461. exit;
  1462. FOrthogonalAbove := Value;
  1463. ArrangePanels;
  1464. end;
  1465. procedure TBCExpandPanels.setAbove(Value: integer);
  1466. begin
  1467. if FAbove = Value then
  1468. exit;
  1469. FAbove := Value;
  1470. ArrangePanels;
  1471. end;
  1472. procedure TBCExpandPanels.setOrthogonalSize(Value: integer);
  1473. var
  1474. i: integer;
  1475. begin
  1476. FOrthogonalSize := Value;
  1477. for I := 0 to PanelArray.Count - 1 do
  1478. WriteRelevantOrthogonalSize(TBCExpandPanel(PanelArray[i]), FOrthogonalSize);
  1479. end;
  1480. procedure TBCExpandPanels.setBehaviour(Value: TBCExpandPanelsBehaviour);
  1481. var
  1482. i: integer;
  1483. isAlreadyOneExpand: boolean;
  1484. begin
  1485. isAlreadyOneExpand := False;
  1486. FBehaviour := Value;
  1487. MakeCorrectButtonClickPointers;
  1488. // look if more then one is open
  1489. for I := 0 to PanelArray.Count - 1 do
  1490. with TBCExpandPanel(PanelArray[i]) do
  1491. if (Behaviour <> EPMultipanel) and not Collapsed then //leave only the first open, if it is not MultiPanel
  1492. if not isAlreadyOneExpand then
  1493. isAlreadyOneExpand := True
  1494. else
  1495. Collapsed := True;
  1496. end;
  1497. procedure TBCExpandPanels.MakeCorrectButtonClickPointers;
  1498. var
  1499. i: integer;
  1500. begin
  1501. // set correct pointers
  1502. for I := 0 to PanelArray.Count - 1 do
  1503. with TBCExpandPanel(PanelArray[i]) do
  1504. if FBehaviour <> EPMultipanel then
  1505. EPManagesCollapsing := @RollOutClick
  1506. else
  1507. EPManagesCollapsing := nil;
  1508. end;
  1509. procedure TBCExpandPanels.CollapseIfTooHigh;
  1510. var
  1511. i, h, max: integer;
  1512. tempanimated: boolean;
  1513. begin
  1514. if Count <= 1 then
  1515. exit;
  1516. h := RelevantAbove(Panel(0));
  1517. max := RelevantSize(Panel(0).Parent);
  1518. for i := 0 to Count - 1 do
  1519. if h + RelevantSize(Panel(i)) > max then
  1520. with Panel(i) do
  1521. begin
  1522. tempanimated := Animated;
  1523. Animated := False;
  1524. Collapsed := True;
  1525. Animated := tempanimated;
  1526. h := h + TBCExpandPanel(Panel(i)).ButtonSize;
  1527. end
  1528. else
  1529. h := h + RelevantSize(Panel(i));
  1530. end;
  1531. procedure TBCExpandPanels.RollOutOnAnimate(Sender: TObject; deltaLeft, deltaTop, deltaWidth, deltaHeight: integer);
  1532. var
  1533. idx, i, size: integer;
  1534. begin
  1535. idx := PanelArray.IndexOf(Sender);
  1536. for i := idx + 1 to PanelArray.Count - 1 do
  1537. begin
  1538. size := RelevantAbove(TBCExpandPanel(PanelArray[i]));
  1539. case FArrangeKind of
  1540. akTop: size := size + deltaTop + deltaHeight;
  1541. akLeft: size := size + deltaLeft + deltaWidth;
  1542. end;
  1543. WriteRelevantAbove(TBCExpandPanel(PanelArray[i]), size);
  1544. end;
  1545. end;
  1546. //procedure TBCExpandPanels.SetCorrectSize;
  1547. //const plus=1; //extra Anstand
  1548. //var
  1549. // i, exSize,
  1550. // countexpanded,
  1551. // SumSize, closedSize:Integer;
  1552. //begin
  1553. // if PanelArray.Count<=0 then
  1554. // exit;
  1555. // SumSize:=FFixedSize;
  1556. // if FUseClientSize then
  1557. // SumSize:=TBCExpandPanel(PanelArray[0]).Parent.Height;
  1558. // countexpanded:=0;
  1559. // closedSize:=0;
  1560. // for I := 0 to PanelArray.count-1 do
  1561. // with TBCExpandPanel(PanelArray[i]) do
  1562. // begin
  1563. // if not Collapsed and not Animating //error producer!!! animating does not neccessairily mean that it is expanding
  1564. // or Collapsed and Animating then
  1565. // inc(countexpanded)
  1566. // else
  1567. // closedSize:=closedSize+Height;
  1568. // end;
  1569. // exSize:=SumSize- FTop- closedSize;
  1570. // case Behaviour of
  1571. // EPMultipanel:
  1572. // if countexpanded>0 then
  1573. // exSize:=trunc(exSize/countexpanded)
  1574. // else
  1575. // exSize:=400;
  1576. // end;
  1577. // for I := 0 to PanelArray.count-1 do
  1578. // with TBCExpandPanel(PanelArray[i]) do
  1579. // begin
  1580. // if not FUseFixedSize and not FUseClientSize then
  1581. // ExpandedSize:=200
  1582. // else
  1583. // ExpandedSize:=exSize;
  1584. // end;
  1585. //end;
  1586. {==============================================================================
  1587. Procedure: ArrangePanels
  1588. Belongs to: TBCExpandPanels
  1589. Result: None
  1590. Parameters:
  1591. Description:
  1592. ==============================================================================}
  1593. procedure TBCExpandPanels.ArrangePanels;
  1594. const
  1595. plus = 1; //extra Anstand
  1596. var
  1597. i, t: integer;
  1598. begin
  1599. if Count <= 0 then
  1600. exit;
  1601. //left setzen!!!
  1602. // SetCorrectSize;
  1603. t := FAbove + plus;
  1604. for I := 0 to PanelArray.Count - 1 do
  1605. begin
  1606. if not TBCExpandPanel(PanelArray[i]).Visible then
  1607. continue;
  1608. WriteRelevantAbove(TBCExpandPanel(PanelArray[i]), t);
  1609. WriteRelevantOrthogonalAbove(TBCExpandPanel(PanelArray[i]), OrthogonalAbove);
  1610. t := t + plus + self.RelevantSize(TBCExpandPanel(PanelArray[i]));
  1611. end;
  1612. if FAutoCollapseIfTooHigh then
  1613. CollapseIfTooHigh;
  1614. if Assigned(FOnArrangePanels) then
  1615. FOnArrangePanels(Self);
  1616. end;
  1617. function TBCExpandPanels.Count: integer;
  1618. begin
  1619. Result := PanelArray.Count;
  1620. end;
  1621. function TBCExpandPanels.Panel(idx: integer): TBCExpandPanel;
  1622. begin
  1623. if idx < Count then
  1624. Result := TBCExpandPanel(PanelArray.Items[idx])
  1625. else
  1626. Result := nil;
  1627. end;
  1628. {==============================================================================
  1629. Procedure: RollOutClick
  1630. Belongs to: TBCExpandPanels
  1631. Result: None
  1632. Parameters:
  1633. Sender : TObject =
  1634. Description:
  1635. ==============================================================================}
  1636. procedure TBCExpandPanels.RollOutClick(Sender: TObject);
  1637. begin
  1638. if (Behaviour <> EPMultipanel) then
  1639. HotTrackSetActivePanel(TBCBoundButton(Sender).Tag);
  1640. end;
  1641. procedure TBCExpandPanels.HotTrackSetActivePanel(Value: integer);
  1642. var
  1643. i: integer;
  1644. begin
  1645. for I := PanelArray.Count - 1 downto 0 do
  1646. TBCExpandPanel(PanelArray[i]).Collapsed := Value <> i;
  1647. end;
  1648. procedure TBCExpandPanels.RollOut1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: integer);
  1649. begin
  1650. if (Behaviour = EPHotMouse) and (TBCExpandPanel(PanelArray[TBCBoundButton(Sender).Tag]).Collapsed) then
  1651. HotTrackSetActivePanel(TBCBoundButton(Sender).Tag);
  1652. end;
  1653. function TBCExpandPanels.IdxOfPanel(aname: string): integer;
  1654. var
  1655. i: integer;
  1656. begin
  1657. Result := -1; // is not here
  1658. for i := 0 to PanelArray.Count - 1 do
  1659. if TBCExpandPanel(PanelArray[i]).Name = aname then
  1660. begin
  1661. Result := i;
  1662. break;
  1663. end;
  1664. end;
  1665. { TBCExpandPanel }
  1666. procedure TBCExpandPanel.setCollapsed(Value: boolean);
  1667. begin
  1668. {$ifopt D+}
  1669. debugln('TBCExpandPanel.setCollapsed '+BoolToStr(Collapsed, True));
  1670. {$endif}
  1671. if FCollapsed = Value then
  1672. exit;
  1673. FCollapsed := Value;
  1674. if not(csLoading in ComponentState)
  1675. then if Value
  1676. then DoCollapse
  1677. else DoExpand;
  1678. end;
  1679. procedure TBCExpandPanel.SetRelevantSize(comp: TControl; AKind: TAnchorKind; ASize: Integer);
  1680. begin
  1681. case AKind of
  1682. akTop, akBottom: comp.Height :=ASize;
  1683. akLeft, akRight: comp.Width :=ASize;
  1684. end;
  1685. end;
  1686. function TBCExpandPanel.RelevantSize(comp: TControl; akind: TAnchorKind): integer;
  1687. begin
  1688. case akind of
  1689. akTop, akBottom: Result := comp.Height;
  1690. akLeft, akRight: Result := comp.Width;
  1691. end;
  1692. end;
  1693. function TBCExpandPanel.RelevantOrthogonalSize(comp: TControl; akind: TAnchorKind): integer;
  1694. begin
  1695. case akind of
  1696. akTop, akBottom: Result := comp.Width;
  1697. akLeft, akRight: Result := comp.Height;
  1698. end;
  1699. end;
  1700. function TBCExpandPanel.DeltaCoordinates(deltaMove, deltaSize: integer): TRect;
  1701. begin
  1702. Result := Rect(0, 0, 0, 0);
  1703. case FCollapseKind of
  1704. akTop: Result := Rect(0, 0, 0, deltaSize);
  1705. akLeft: Result := Rect(0, 0, deltaSize, 0);
  1706. akBottom: Result := Rect(0, deltaMove, 0, deltaSize);
  1707. akRight: Result := Rect(deltaMove, 0, deltaSize, 0);
  1708. end;
  1709. end;
  1710. procedure TBCExpandPanel.TimerAnimateSize(Sender: TObject);
  1711. var
  1712. step: real;
  1713. originalsize, size: integer;
  1714. deltaMove, deltaSize: integer;
  1715. delta: TRect;
  1716. vorzeichen: integer;
  1717. begin
  1718. deltaMove := 0;
  1719. deltaSize := 0;
  1720. StopCircleActions := False;
  1721. FAnimating := True;
  1722. step := FAnimationSpeed;
  1723. Size := RelevantSize(Self, FCollapseKind);
  1724. vorzeichen := Sign(TargetAnimationSize - RelevantSize(self, FCollapseKind)); // muss ich delta addieren oder muss ich delta abziehen
  1725. originalsize := ExpandedSize;
  1726. //One huge step if not animated
  1727. if not FAnimated or not (ComponentState * [csLoading, csDesigning] = []) then
  1728. step := abs(Size - TargetAnimationSize);
  1729. //small steps if animated
  1730. if FAnimated and (ComponentState * [csLoading, csDesigning] = []) then
  1731. begin
  1732. step := step * originalsize / 200;
  1733. if step < 3 then
  1734. step := 3;
  1735. end;
  1736. //now actually do something
  1737. if Abs(Size - TargetAnimationSize) > 0 then
  1738. begin
  1739. if Abs(Size - TargetAnimationSize) < abs(step) then // if there is just a little bit left to go, set delta so it can go directly to the end size
  1740. deltaSize := TargetAnimationSize - Size
  1741. else
  1742. deltaSize := vorzeichen * round(step);
  1743. if (CollapseKind = akBottom) or (CollapseKind = akRight) then
  1744. deltaMove := -deltaSize;
  1745. delta := DeltaCoordinates(deltaMove, deltaSize);
  1746. SetBounds(Left + delta.Left, Top + delta.Top, Width + delta.Right, Height + delta.Bottom);
  1747. if assigned(FInternalOnAnimate) then
  1748. FInternalOnAnimate(self, delta.Left, delta.Top, delta.Right, delta.Bottom);
  1749. if assigned(FOnAnimate) then
  1750. FOnAnimate(self, delta.Left, delta.Top, delta.Right, delta.Bottom);
  1751. end;
  1752. if Abs(Size - TargetAnimationSize) = 0 then //it's finished ( executes it NEXT time the timer activates!)
  1753. begin
  1754. Timer.Enabled := False;
  1755. FAnimating := False;
  1756. StopCircleActions := False;
  1757. if assigned(EndProcedureOfAnimation) then
  1758. EndProcedureOfAnimation;
  1759. end;
  1760. end;
  1761. procedure TBCExpandPanel.EndTimerCollapse;
  1762. begin
  1763. if assigned(OnCollapse) then
  1764. OnCollapse(self);
  1765. UpdateAll;
  1766. end;
  1767. procedure TBCExpandPanel.EndTimerExpand;
  1768. begin
  1769. if assigned(OnExpand) then
  1770. OnExpand(self);
  1771. UpdateAll;
  1772. end;
  1773. procedure TBCExpandPanel.UpdateAll;
  1774. begin
  1775. Update;
  1776. //FButton.Update;
  1777. end;
  1778. procedure TBCExpandPanel.setExpandedSize(Value: integer);
  1779. begin
  1780. {$ifopt D+}
  1781. debugln('TBCExpandPanel.setExpandedSize');
  1782. debugln(IntToStr(Value));
  1783. {$endif}
  1784. if (FExpandedSize = Value) then
  1785. exit;
  1786. FExpandedSize := Value;
  1787. if not(csLoading in ComponentState) and not(FCollapsed)
  1788. then Animate(FExpandedSize);
  1789. end;
  1790. function TBCExpandPanel.GetEnabled: Boolean;
  1791. begin
  1792. Result :=inherited Enabled;
  1793. if (FButton.Enabled <> Result) //Paranoic Think
  1794. then FButton.Enabled :=Result;
  1795. end;
  1796. procedure TBCExpandPanel.SetBevelColorHighlight(AValue: TColor);
  1797. begin
  1798. if (rBevelColorHighlight <> AValue) then
  1799. begin
  1800. rBevelColorHighlight := AValue;
  1801. if not(csLoading in ComponentState)
  1802. then Invalidate;
  1803. end;
  1804. end;
  1805. procedure TBCExpandPanel.SetBevelColorShadow(AValue: TColor);
  1806. begin
  1807. if (rBevelColorShadow <> AValue) then
  1808. begin
  1809. rBevelColorShadow := AValue;
  1810. if not(csLoading in ComponentState)
  1811. then Invalidate;
  1812. end;
  1813. end;
  1814. procedure TBCExpandPanel.SetBevelRounded(AValue: Boolean);
  1815. begin
  1816. if (rBevelRounded <> AValue) then
  1817. begin
  1818. rBevelRounded := AValue;
  1819. if not(csLoading in ComponentState)
  1820. then Invalidate;
  1821. end;
  1822. end;
  1823. procedure TBCExpandPanel.SetEnabled(AValue: Boolean);
  1824. begin
  1825. inherited Enabled :=AValue;
  1826. FButton.Enabled :=AValue;
  1827. end;
  1828. procedure TBCExpandPanel.setButtonSize(Value: integer);
  1829. begin
  1830. if FButtonSize = Value then
  1831. exit;
  1832. FButtonSize := Value;
  1833. PositionButton;
  1834. end;
  1835. procedure TBCExpandPanel.SetBounds(ALeft, ATop, AWidth, AHeight: integer);
  1836. begin
  1837. inherited SetBounds(ALeft, ATop, AWidth, AHeight);
  1838. if not Collapsed and not Animating and (ComponentState * [csLoading] = []) then
  1839. FExpandedSize := RelevantSize(self, FCollapseKind);
  1840. end;
  1841. procedure TBCExpandPanel.setButtonPosition(Value: TAnchorKind);
  1842. var
  1843. wasanimated, wascollpased: boolean;
  1844. begin
  1845. if FButtonPosition = Value then
  1846. exit;
  1847. wasanimated := Animated;
  1848. wascollpased := Collapsed;
  1849. Animated := False;
  1850. if Collapsed then
  1851. Collapsed := False;
  1852. FButtonPosition := Value;
  1853. PositionButton;
  1854. Collapsed := wascollpased;
  1855. Animated := wasanimated;
  1856. Invalidate;
  1857. end;
  1858. procedure TBCExpandPanel.setCollapseKind(Value: TAnchorKind);
  1859. var
  1860. wasanimated, wascollpased: boolean;
  1861. begin
  1862. if FCollapseKind = Value then
  1863. exit;
  1864. wasanimated := Animated;
  1865. wascollpased := Collapsed;
  1866. Animated := False;
  1867. if Collapsed then
  1868. Collapsed := False;
  1869. FCollapseKind := Value;
  1870. //switsch sizes
  1871. case FCollapseKind of
  1872. akLeft, akRight: FExpandedSize := Width;
  1873. akTop, akBottom: FExpandedSize := Height;
  1874. end;
  1875. if not(csLoading in ComponentState) then
  1876. begin
  1877. FButton.BuildGlyphs;
  1878. FButton.Invalidate;
  1879. end;
  1880. Collapsed := wascollpased;
  1881. Animated := wasanimated;
  1882. end;
  1883. procedure TBCExpandPanel.setAnimationSpeed(Value: real);
  1884. begin
  1885. korrigiere(Value, 3, 1000);
  1886. FAnimationSpeed := Value;
  1887. end;
  1888. procedure TBCExpandPanel.PositionButton;
  1889. function ButtonRect: TRect;
  1890. begin
  1891. case FButtonPosition of
  1892. akBottom, akTop: Result := Rect(0, 0, RelevantOrthogonalSize(self, FButtonPosition), FButtonSize);
  1893. akLeft, akRight: Result := Rect(0, 0, FButtonSize, RelevantOrthogonalSize(self, FButtonPosition));
  1894. end;
  1895. //this must come after the thing above!!!
  1896. // this moves the button to the bottom, or the right
  1897. case FButtonPosition of
  1898. akBottom: Result.Top := Result.Top + RelevantSize(self, FButtonPosition) - FButtonSize;
  1899. akRight: Result.Left := Result.Left + RelevantSize(self, FButtonPosition) - FButtonSize;
  1900. end;
  1901. end;
  1902. var
  1903. new: TRect;
  1904. begin
  1905. if StopCircleActions or not(Assigned(FButton)) or (csLoading in ComponentState)
  1906. then exit;
  1907. StopCircleActions := True;
  1908. new := ButtonRect;
  1909. FButton.SetBounds(new.Left, new.Top, new.Right, new.Bottom);
  1910. //set anchors
  1911. case FButtonPosition of
  1912. akBottom: FButton.Anchors := [akTop, akLeft, akBottom, akRight] - [akTop];
  1913. akLeft: FButton.Anchors := [akTop, akLeft, akBottom, akRight] - [akRight];
  1914. akTop: FButton.Anchors := [akTop, akLeft, akBottom, akRight] - [akBottom];
  1915. akRight: FButton.Anchors := [akTop, akLeft, akBottom, akRight] - [akLeft];
  1916. end;
  1917. Invalidate;
  1918. StopCircleActions := False;
  1919. end;
  1920. procedure TBCExpandPanel.ButtonClick(Sender: TObject);
  1921. begin
  1922. if Assigned(FEPManagesCollapsing) then
  1923. FEPManagesCollapsing(self)
  1924. else
  1925. Collapsed := not Collapsed;
  1926. if Assigned(OnButtonClick) then
  1927. OnButtonClick(self);
  1928. end;
  1929. procedure TBCExpandPanel.Animate(aTargetSize: integer);
  1930. var
  1931. storAnimated: boolean;
  1932. begin
  1933. if (FAnimating) then
  1934. begin
  1935. // FinishLastAnimationFast
  1936. storAnimated := FAnimated;
  1937. FAnimated := False;
  1938. TimerAnimateSize(self);
  1939. FAnimated := storAnimated;
  1940. end;
  1941. // Now do animation
  1942. TargetAnimationSize := aTargetSize;
  1943. if (ComponentState * [csLoading, csDesigning] = []) and FAnimated then
  1944. begin
  1945. Timer.Enabled := True;
  1946. Timer.OnTimer := @TimerAnimateSize;
  1947. //EndProcedureOfAnimation := nil; //On Collapse then EndTimerCollapse never Executed
  1948. end
  1949. else
  1950. begin
  1951. TimerAnimateSize(self);
  1952. TimerAnimateSize(self);
  1953. end;
  1954. end;
  1955. procedure TBCExpandPanel.SetTextAlignment(AValue: TAlignment);
  1956. begin
  1957. if FTextAlignment=AValue then Exit;
  1958. FTextAlignment:=AValue;
  1959. Invalidate;
  1960. end;
  1961. procedure TBCExpandPanel.DoCollapse;
  1962. var
  1963. i :Integer;
  1964. curControl: TControl;
  1965. begin
  1966. (* may work but is irrilevant because TSpeedButton is always on Bottom ????why?
  1967. i :=0;
  1968. while (i < ControlCount) do
  1969. begin
  1970. curControl :=Controls[i];
  1971. if not(curControl is TBCBoundButton) then
  1972. begin
  1973. Self.SetChildZPosition(curControl, 0);
  1974. end;
  1975. inc(i)
  1976. end;*)
  1977. if assigned(OnPreCollapse) then
  1978. OnPreCollapse(self);
  1979. //FButton.Color := FCollapsedButtonColor;
  1980. EndProcedureOfAnimation := @EndTimerCollapse;
  1981. Animate(FButtonSize);
  1982. {$ifopt D+}
  1983. debugln('TBCExpandPanel.DoCollapse');
  1984. debugln('FButtonSize ' + IntToStr(FButtonSize));
  1985. {$endif}
  1986. end;
  1987. procedure TBCExpandPanel.DoExpand;
  1988. begin
  1989. if assigned(OnPreExpand) then
  1990. OnPreExpand(self);
  1991. // FButton.ControlStyle := FButton.ControlStyle + [csNoFocus, csNoDesignSelectable];
  1992. // FButton.Parent:=self;
  1993. //FButton.Color := FExpandedButtonColor;
  1994. EndProcedureOfAnimation := @EndTimerExpand;
  1995. Animate(FExpandedSize);
  1996. {$ifopt D+}
  1997. debugln('TBCExpandPanel.DoExpand');
  1998. debugln('FExpandedSize ' + IntToStr(FExpandedSize));
  1999. {$endif}
  2000. end;
  2001. procedure TBCExpandPanel.AdjustClientRect(var ARect: TRect);
  2002. begin
  2003. inherited AdjustClientRect(ARect);
  2004. if Assigned(FButton) then
  2005. case ButtonPosition of
  2006. akTop:
  2007. ARect.Top := ARect.Top + fButton.Height;
  2008. akBottom:
  2009. ARect.Bottom := ARect.Bottom - fButton.Height;
  2010. akLeft:
  2011. ARect.Left := ARect.Left + fButton.Width;
  2012. akRight:
  2013. ARect.Right := ARect.Right - fButton.Width;
  2014. end;
  2015. end;
  2016. procedure TBCExpandPanel.Loaded;
  2017. begin
  2018. inherited Loaded;
  2019. end;
  2020. procedure TBCExpandPanel.CreateWnd;
  2021. begin
  2022. inherited CreateWnd;
  2023. FButton.BuildGlyphs; //Button Loaded is called Before Self.Loaded and cannot Build Glyphs
  2024. (* if (FCollapsed)
  2025. then SetRelevantSize(Self, FButtonPosition, FButtonSize)
  2026. else SetRelevantSize(Self, FButtonPosition, FExpandedSize); *)
  2027. PositionButton;
  2028. end;
  2029. procedure TBCExpandPanel.Paint;
  2030. var
  2031. ARect: TRect;
  2032. TS: TTextStyle;
  2033. begin
  2034. if not(FCollapsed) then
  2035. begin
  2036. ARect := GetClientRect;
  2037. Case FButtonPosition of
  2038. akTop: inc(ARect.Top, FButtonSize);
  2039. akBottom: dec(ARect.Bottom, FButtonSize);
  2040. akLeft: inc(ARect.Left, FButtonSize);
  2041. akRight: dec(ARect.Right, FButtonSize);
  2042. end;
  2043. {$ifdef DEBUG_PAINT}
  2044. Canvas.Brush.Color:=clRed;
  2045. Canvas.Brush.Style:=bsSolid;
  2046. Canvas.FillRect(ARect);
  2047. {$endif}
  2048. // if BevelOuter is set then draw a frame with BevelWidth
  2049. if (BevelOuter <> bvNone)
  2050. then if rBevelRounded
  2051. then Frame3d_Rounded(Self.Canvas, ARect, BevelWidth, 5, 5, BevelOuter,
  2052. rBevelColorShadow, rBevelColorHighlight, Color)
  2053. else Self.Canvas.Frame3d(ARect, BevelWidth, BevelOuter);
  2054. InflateRect(ARect, -BorderWidth, -BorderWidth);
  2055. // if BevelInner is set then skip the BorderWidth and draw a frame with BevelWidth
  2056. if (BevelInner <> bvNone)
  2057. then if rBevelRounded
  2058. then Frame3d_Rounded(Self.Canvas, ARect, BevelWidth, 5, 5, BevelInner,
  2059. rBevelColorShadow, rBevelColorHighlight, Color)
  2060. else Self.Canvas.Frame3d(ARect, BevelWidth, BevelInner);
  2061. if (Self.Caption <> '') then
  2062. begin
  2063. TS := Canvas.TextStyle;
  2064. TS.Alignment := BidiFlipAlignment(Self.TextAlignment, UseRightToLeftAlignment);
  2065. if (BiDiMode <> bdLeftToRight)
  2066. then TS.RightToLeft:= True;
  2067. TS.Layout:= Graphics.tlCenter;
  2068. TS.Opaque:= false;
  2069. TS.Clipping:= false;
  2070. TS.SystemFont:=Canvas.Font.IsDefault;
  2071. if not(Enabled) then
  2072. begin
  2073. Canvas.Font.Color := clBtnHighlight;
  2074. Types.OffsetRect(ARect, 1, 1);
  2075. Self.Canvas.TextRect(ARect, ARect.Left, ARect.Top, Self.Caption, TS);
  2076. Self.Canvas.Font.Color := clBtnShadow;
  2077. Types.OffsetRect(ARect, -1, -1);
  2078. end
  2079. else Self.Canvas.Font.Color := Font.Color;
  2080. Self.Canvas.TextRect(ARect,ARect.Left,ARect.Top, Self.Caption, TS);
  2081. end;
  2082. end;
  2083. end;
  2084. constructor TBCExpandPanel.Create(TheOwner: TComponent);
  2085. begin
  2086. StopCircleActions := True;
  2087. inherited;
  2088. FButtonSize := 27;
  2089. FAnimated := True;
  2090. FCollapseKind := akTop;
  2091. FVisibleTotal := True;
  2092. FCollapsed := False;
  2093. FButtonPosition := akTop;
  2094. FCollapsedButtonColor := clSkyBlue;
  2095. FExpandedButtonColor := RGBToColor(23, 136, 248);
  2096. rBevelColorHighlight:=clBtnHighlight;
  2097. rBevelColorShadow:=clBtnShadow;
  2098. rBevelRounded:=True;
  2099. FExpandedSize := 200;
  2100. Height := FExpandedSize;
  2101. Width := 200;
  2102. FAnimationSpeed := 20;
  2103. Caption := '';
  2104. Timer := TTimer.Create(self);
  2105. Timer.Enabled := False;
  2106. Timer.Name := 'Animationtimer';
  2107. Timer.Interval := 20;
  2108. FButton := TBCBoundButton.Create(self);
  2109. with FButton do
  2110. begin
  2111. Parent := self;
  2112. Name := 'Button';
  2113. Caption := 'Caption';
  2114. ControlStyle := ControlStyle + [csNoFocus, csNoDesignSelectable];
  2115. FButton.OnClick := @self.ButtonClick;
  2116. end;
  2117. StopCircleActions := False;
  2118. //may be only in CreateWnd but the button is greater by some pixels
  2119. PositionButton;
  2120. end;
  2121. destructor TBCExpandPanel.Destroy;
  2122. begin
  2123. timer.Enabled := False;
  2124. Timer.Free;
  2125. if (ComponentState * [csLoading, csDesigning] = []) then
  2126. FButton.Free; // bringt einen Fehler in der Designtime wenn ich das hier mache
  2127. // FButton.Free; // bringt einen Fehler in der Designtime wenn ich das hier mache
  2128. inherited Destroy;
  2129. end;
  2130. {$IFDEF FPC}
  2131. procedure Register;
  2132. begin
  2133. RegisterComponents('BGRA Controls', [TBCExpandPanel, TBCExpandPanels]);
  2134. end;
  2135. {$ENDIF}
  2136. initialization
  2137. {$i BCExpandPanels.lrs}
  2138. end.