tabs.pas 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558
  1. unit tabs;
  2. interface
  3. uses
  4. objects,drivers,views;
  5. type
  6. PTabItem = ^TTabItem;
  7. TTabItem = record
  8. Next : PTabItem;
  9. View : PView;
  10. Dis : boolean;
  11. end;
  12. PTabDef = ^TTabDef;
  13. TTabDef = record
  14. Next : PTabDef;
  15. Name : PString;
  16. Items : PTabItem;
  17. DefItem : PView;
  18. ShortCut : char;
  19. end;
  20. PTab = ^TTab;
  21. TTab = object(TGroup)
  22. TabDefs : PTabDef;
  23. ActiveDef : integer;
  24. DefCount : word;
  25. constructor Init(var Bounds: TRect; ATabDef: PTabDef);
  26. function AtTab(Index: integer): PTabDef; virtual;
  27. procedure SelectTab(Index: integer); virtual;
  28. function TabCount: integer;
  29. function Valid(Command: Word): Boolean; virtual;
  30. procedure ChangeBounds(var Bounds: TRect); virtual;
  31. procedure HandleEvent(var Event: TEvent); virtual;
  32. function GetPalette: PPalette; virtual;
  33. procedure Draw; virtual;
  34. function DataSize: sw_word;virtual;
  35. procedure SetData(var Rec);virtual;
  36. procedure GetData(var Rec);virtual;
  37. procedure SetState(AState: Word; Enable: Boolean); virtual;
  38. destructor Done; virtual;
  39. private
  40. InDraw: boolean;
  41. end;
  42. function NewTabItem(AView: PView; ANext: PTabItem): PTabItem;
  43. procedure DisposeTabItem(P: PTabItem);
  44. function NewTabDef(AName: string; ADefItem: PView; AItems: PTabItem; ANext: PTabDef): PTabDef;
  45. procedure DisposeTabDef(P: PTabDef);
  46. implementation
  47. uses
  48. FvCommon,dialogs;
  49. constructor TTab.Init(var Bounds: TRect; ATabDef: PTabDef);
  50. begin
  51. inherited Init(Bounds);
  52. Options:=Options or ofSelectable or ofFirstClick or ofPreProcess or ofPostProcess;
  53. GrowMode:=gfGrowHiX+gfGrowHiY+gfGrowRel;
  54. TabDefs:=ATabDef;
  55. ActiveDef:=-1;
  56. SelectTab(0);
  57. ReDraw;
  58. end;
  59. function TTab.TabCount: integer;
  60. var i: integer;
  61. P: PTabDef;
  62. begin
  63. I:=0; P:=TabDefs;
  64. while (P<>nil) do
  65. begin
  66. Inc(I);
  67. P:=P^.Next;
  68. end;
  69. TabCount:=I;
  70. end;
  71. function TTab.AtTab(Index: integer): PTabDef;
  72. var i: integer;
  73. P: PTabDef;
  74. begin
  75. i:=0; P:=TabDefs;
  76. while (I<Index) do
  77. begin
  78. if P=nil then RunError($AA);
  79. P:=P^.Next;
  80. Inc(i);
  81. end;
  82. AtTab:=P;
  83. end;
  84. procedure TTab.SelectTab(Index: integer);
  85. var P: PTabItem;
  86. V: PView;
  87. begin
  88. if ActiveDef<>Index then
  89. begin
  90. if Owner<>nil then Owner^.Lock;
  91. Lock;
  92. { --- Update --- }
  93. if TabDefs<>nil then
  94. begin
  95. DefCount:=1;
  96. while AtTab(DefCount-1)^.Next<>nil do Inc(DefCount);
  97. end
  98. else DefCount:=0;
  99. if ActiveDef<>-1 then
  100. begin
  101. P:=AtTab(ActiveDef)^.Items;
  102. while P<>nil do
  103. begin
  104. if P^.View<>nil then Delete(P^.View);
  105. P:=P^.Next;
  106. end;
  107. end;
  108. ActiveDef:=Index;
  109. P:=AtTab(ActiveDef)^.Items;
  110. while P<>nil do
  111. begin
  112. if P^.View<>nil then Insert(P^.View);
  113. P:=P^.Next;
  114. end;
  115. V:=AtTab(ActiveDef)^.DefItem;
  116. if V<>nil then V^.Select;
  117. ReDraw;
  118. { --- Update --- }
  119. UnLock;
  120. if Owner<>nil then Owner^.UnLock;
  121. DrawView;
  122. end;
  123. end;
  124. procedure TTab.ChangeBounds(var Bounds: TRect);
  125. var D: TPoint;
  126. procedure DoCalcChange(P: PView); {$ifndef FPC}far;{$endif}
  127. var
  128. R: TRect;
  129. begin
  130. if P^.Owner=nil then Exit; { it think this is a bug in TV }
  131. P^.CalcBounds(R, D);
  132. P^.ChangeBounds(R);
  133. end;
  134. var
  135. P: PTabItem;
  136. I: integer;
  137. begin
  138. D.X := Bounds.B.X - Bounds.A.X - Size.X;
  139. D.Y := Bounds.B.Y - Bounds.A.Y - Size.Y;
  140. inherited ChangeBounds(Bounds);
  141. for I:=0 to TabCount-1 do
  142. if I<>ActiveDef then
  143. begin
  144. P:=AtTab(I)^.Items;
  145. while P<>nil do
  146. begin
  147. if P^.View<>nil then DoCalcChange(P^.View);
  148. P:=P^.Next;
  149. end;
  150. end;
  151. end;
  152. procedure TTab.HandleEvent(var Event: TEvent);
  153. var Index : integer;
  154. I : integer;
  155. X : integer;
  156. Len : byte;
  157. P : TPoint;
  158. V : PView;
  159. CallOrig: boolean;
  160. LastV : PView;
  161. FirstV: PView;
  162. function FirstSelectable: PView;
  163. var
  164. FV : PView;
  165. begin
  166. FV := First;
  167. while (FV<>nil) and ((FV^.Options and ofSelectable)=0) and (FV<>Last) do
  168. FV:=FV^.Next;
  169. if FV<>nil then
  170. if (FV^.Options and ofSelectable)=0 then FV:=nil;
  171. FirstSelectable:=FV;
  172. end;
  173. function LastSelectable: PView;
  174. var
  175. LV : PView;
  176. begin
  177. LV := Last;
  178. while (LV<>nil) and ((LV^.Options and ofSelectable)=0) and (LV<>First) do
  179. LV:=LV^.Prev;
  180. if LV<>nil then
  181. if (LV^.Options and ofSelectable)=0 then LV:=nil;
  182. LastSelectable:=LV;
  183. end;
  184. begin
  185. if (Event.What and evMouseDown)<>0 then
  186. begin
  187. MakeLocal(Event.Where,P);
  188. if P.Y<3 then
  189. begin
  190. Index:=-1; X:=1;
  191. for i:=0 to DefCount-1 do
  192. begin
  193. Len:=CStrLen(AtTab(i)^.Name^);
  194. if (P.X>=X) and (P.X<=X+Len+1) then Index:=i;
  195. X:=X+Len+3;
  196. end;
  197. if Index<>-1 then
  198. SelectTab(Index);
  199. end;
  200. end;
  201. if Event.What=evKeyDown then
  202. begin
  203. Index:=-1;
  204. case Event.KeyCode of
  205. kbTab,kbShiftTab :
  206. if GetState(sfSelected) then
  207. begin
  208. if Current<>nil then
  209. begin
  210. LastV:=LastSelectable; FirstV:=FirstSelectable;
  211. if ((Current=LastV) or (Current=PLabel(LastV)^.Link)) and (Event.KeyCode=kbShiftTab) then
  212. begin
  213. if Owner<>nil then Owner^.SelectNext(true);
  214. end else
  215. if ((Current=FirstV) or (Current=PLabel(FirstV)^.Link)) and (Event.KeyCode=kbTab) then
  216. begin
  217. Lock;
  218. if Owner<>nil then Owner^.SelectNext(false);
  219. UnLock;
  220. end else
  221. SelectNext(Event.KeyCode=kbShiftTab);
  222. ClearEvent(Event);
  223. end;
  224. end;
  225. else
  226. for I:=0 to DefCount-1 do
  227. begin
  228. if Upcase(GetAltChar(Event.KeyCode))=AtTab(I)^.ShortCut
  229. then begin
  230. Index:=I;
  231. ClearEvent(Event);
  232. Break;
  233. end;
  234. end;
  235. end;
  236. if Index<>-1 then
  237. begin
  238. Select;
  239. SelectTab(Index);
  240. V:=AtTab(ActiveDef)^.DefItem;
  241. if V<>nil then V^.Focus;
  242. end;
  243. end;
  244. CallOrig:=true;
  245. if Event.What=evKeyDown then
  246. begin
  247. if ((Owner<>nil) and (Owner^.Phase=phPostProcess) and (GetAltChar(Event.KeyCode)<>#0)) or GetState(sfFocused)
  248. then
  249. else CallOrig:=false;
  250. end;
  251. if CallOrig then inherited HandleEvent(Event);
  252. end;
  253. function TTab.GetPalette: PPalette;
  254. begin
  255. GetPalette:=nil;
  256. end;
  257. procedure TTab.Draw;
  258. var B : TDrawBuffer;
  259. i : integer;
  260. C1,C2,C3,C : word;
  261. HeaderLen : integer;
  262. X,X2 : integer;
  263. Name : PString;
  264. ActiveKPos : integer;
  265. ActiveVPos : integer;
  266. FC : char;
  267. procedure SWriteBuf(X,Y,W,H: integer; var Buf);
  268. var i: integer;
  269. begin
  270. if Y+H>Size.Y then H:=Size.Y-Y;
  271. if X+W>Size.X then W:=Size.X-X;
  272. if Buffer=nil then WriteBuf(X,Y,W,H,Buf)
  273. else for i:=1 to H do
  274. Move(Buf,Buffer^[X+(Y+i-1)*Size.X],W*2);
  275. end;
  276. procedure ClearBuf;
  277. begin
  278. MoveChar(B,' ',C1,Size.X);
  279. end;
  280. begin
  281. if InDraw then Exit;
  282. InDraw:=true;
  283. { - Start of TGroup.Draw - }
  284. { if Buffer = nil then
  285. begin
  286. GetBuffer;
  287. end; }
  288. { - Start of TGroup.Draw - }
  289. C1:=GetColor(1);
  290. C2:=(GetColor(7) and $f0 or $08)+GetColor(9)*256;
  291. C3:=GetColor(8)+GetColor({9}8)*256;
  292. { Calculate the size of the headers }
  293. HeaderLen:=0;
  294. for i:=0 to DefCount-1 do
  295. HeaderLen:=HeaderLen+CStrLen(AtTab(i)^.Name^)+3;
  296. Dec(HeaderLen);
  297. if HeaderLen>Size.X-2 then HeaderLen:=Size.X-2;
  298. { --- 1. sor --- }
  299. ClearBuf; MoveChar(B[0],'³',C1,1); MoveChar(B[HeaderLen+1],'³',C1,1);
  300. X:=1;
  301. for i:=0 to DefCount-1 do
  302. begin
  303. Name:=AtTab(i)^.Name; X2:=CStrLen(Name^);
  304. if i=ActiveDef
  305. then begin
  306. ActiveKPos:=X-1;
  307. ActiveVPos:=X+X2+2;
  308. if GetState(sfFocused) then C:=C3 else C:=C2;
  309. end
  310. else C:=C2;
  311. MoveCStr(B[X],' '+Name^+' ',C); X:=X+X2+3;
  312. MoveChar(B[X-1],'³',C1,1);
  313. end;
  314. SWriteBuf(0,1,Size.X,1,B);
  315. { --- 0. sor --- }
  316. ClearBuf; MoveChar(B[0],'Ú',C1,1);
  317. X:=1;
  318. for i:=0 to DefCount-1 do
  319. begin
  320. if I<ActiveDef then FC:='Ú'
  321. else FC:='¿';
  322. X2:=CStrLen(AtTab(i)^.Name^)+2;
  323. MoveChar(B[X+X2],{'Â'}FC,C1,1);
  324. if i=DefCount-1 then X2:=X2+1;
  325. if X2>0 then
  326. MoveChar(B[X],'Ä',C1,X2);
  327. X:=X+X2+1;
  328. end;
  329. MoveChar(B[HeaderLen+1],'¿',C1,1);
  330. MoveChar(B[ActiveKPos],'Ú',C1,1); MoveChar(B[ActiveVPos],'¿',C1,1);
  331. SWriteBuf(0,0,Size.X,1,B);
  332. { --- 2. sor --- }
  333. MoveChar(B[1],'Ä',C1,Max(HeaderLen,0)); MoveChar(B[HeaderLen+2],'Ä',C1,Max(Size.X-HeaderLen-3,0));
  334. MoveChar(B[Size.X-1],'¿',C1,1);
  335. MoveChar(B[ActiveKPos],'Ù',C1,1);
  336. if ActiveDef=0 then MoveChar(B[0],'³',C1,1)
  337. else MoveChar(B[0],{'Ã'}'Ú',C1,1);
  338. MoveChar(B[HeaderLen+1],'Ä'{'Á'},C1,1); MoveChar(B[ActiveVPos],'À',C1,1);
  339. MoveChar(B[ActiveKPos+1],' ',C1,Max(ActiveVPos-ActiveKPos-1,0));
  340. SWriteBuf(0,2,Size.X,1,B);
  341. { --- marad‚k sor --- }
  342. ClearBuf; MoveChar(B[0],'³',C1,1); MoveChar(B[Size.X-1],'³',C1,1);
  343. {SWriteBuf(0,3,Size.X,Size.Y-4,B);}
  344. for i:=3 to Size.Y-1 do
  345. SWriteBuf(0,i,Size.X,1,B);
  346. { --- Size.X . sor --- }
  347. MoveChar(B[0],'À',C1,1); MoveChar(B[1],'Ä',C1,Max(Size.X-2,0)); MoveChar(B[Size.X-1],'Ù',C1,1);
  348. SWriteBuf(0,Size.Y-1,Size.X,1,B);
  349. { - End of TGroup.Draw - }
  350. if Buffer <> nil then
  351. begin
  352. Lock;
  353. Redraw;
  354. UnLock;
  355. end;
  356. if Buffer <> nil then
  357. WriteBuf(0, 0, Size.X, Size.Y, Buffer^)
  358. else
  359. Redraw;
  360. { - End of TGroup.Draw - }
  361. InDraw:=false;
  362. end;
  363. function TTab.Valid(Command: Word): Boolean;
  364. var PT : PTabDef;
  365. PI : PTabItem;
  366. OK : boolean;
  367. begin
  368. OK:=true;
  369. PT:=TabDefs;
  370. while (PT<>nil) and (OK=true) do
  371. begin
  372. PI:=PT^.Items;
  373. while (PI<>nil) and (OK=true) do
  374. begin
  375. if PI^.View<>nil then OK:=OK and PI^.View^.Valid(Command);
  376. PI:=PI^.Next;
  377. end;
  378. PT:=PT^.Next;
  379. end;
  380. Valid:=OK;
  381. end;
  382. procedure TTab.SetData(var Rec);
  383. type
  384. Bytes = array[0..65534] of Byte;
  385. var
  386. I: Sw_Word;
  387. PT : PTabDef;
  388. PI : PTabItem;
  389. begin
  390. I := 0;
  391. PT:=TabDefs;
  392. while (PT<>nil) do
  393. begin
  394. PI:=PT^.Items;
  395. while (PI<>nil) do
  396. begin
  397. if PI^.View<>nil then
  398. begin
  399. PI^.View^.SetData(Bytes(Rec)[I]);
  400. Inc(I, PI^.View^.DataSize);
  401. end;
  402. PI:=PI^.Next;
  403. end;
  404. PT:=PT^.Next;
  405. end;
  406. end;
  407. function TTab.DataSize: sw_word;
  408. var
  409. I: Sw_Word;
  410. PT : PTabDef;
  411. PI : PTabItem;
  412. begin
  413. I := 0;
  414. PT:=TabDefs;
  415. while (PT<>nil) do
  416. begin
  417. PI:=PT^.Items;
  418. while (PI<>nil) do
  419. begin
  420. if PI^.View<>nil then
  421. begin
  422. Inc(I, PI^.View^.DataSize);
  423. end;
  424. PI:=PI^.Next;
  425. end;
  426. PT:=PT^.Next;
  427. end;
  428. DataSize:=i;
  429. end;
  430. procedure TTab.GetData(var Rec);
  431. type
  432. Bytes = array[0..65534] of Byte;
  433. var
  434. I: Sw_Word;
  435. PT : PTabDef;
  436. PI : PTabItem;
  437. begin
  438. I := 0;
  439. PT:=TabDefs;
  440. while (PT<>nil) do
  441. begin
  442. PI:=PT^.Items;
  443. while (PI<>nil) do
  444. begin
  445. if PI^.View<>nil then
  446. begin
  447. PI^.View^.GetData(Bytes(Rec)[I]);
  448. Inc(I, PI^.View^.DataSize);
  449. end;
  450. PI:=PI^.Next;
  451. end;
  452. PT:=PT^.Next;
  453. end;
  454. end;
  455. procedure TTab.SetState(AState: Word; Enable: Boolean);
  456. begin
  457. inherited SetState(AState,Enable);
  458. if (AState and sfFocused)<>0 then DrawView;
  459. end;
  460. destructor TTab.Done;
  461. var P,X: PTabDef;
  462. procedure DeleteViews(P: PView); {$ifndef FPC}far;{$endif}
  463. begin
  464. if P<>nil then Delete(P);
  465. end;
  466. begin
  467. ForEach(@DeleteViews);
  468. inherited Done;
  469. P:=TabDefs;
  470. while P<>nil do
  471. begin
  472. X:=P^.Next;
  473. DisposeTabDef(P);
  474. P:=X;
  475. end;
  476. end;
  477. function NewTabItem(AView: PView; ANext: PTabItem): PTabItem;
  478. var P: PTabItem;
  479. begin
  480. New(P); FillChar(P^,SizeOf(P^),0);
  481. P^.Next:=ANext; P^.View:=AView;
  482. NewTabItem:=P;
  483. end;
  484. procedure DisposeTabItem(P: PTabItem);
  485. begin
  486. if P<>nil then
  487. begin
  488. if P^.View<>nil then Dispose(P^.View, Done);
  489. Dispose(P);
  490. end;
  491. end;
  492. function NewTabDef(AName: string; ADefItem: PView; AItems: PTabItem; ANext: PTabDef): PTabDef;
  493. var P: PTabDef;
  494. x: byte;
  495. begin
  496. New(P);
  497. P^.Next:=ANext; P^.Name:=NewStr(AName); P^.Items:=AItems;
  498. x:=pos('~',AName);
  499. if (x<>0) and (x<length(AName)) then P^.ShortCut:=Upcase(AName[x+1])
  500. else P^.ShortCut:=#0;
  501. P^.DefItem:=ADefItem;
  502. NewTabDef:=P;
  503. end;
  504. procedure DisposeTabDef(P: PTabDef);
  505. var PI,X: PTabItem;
  506. begin
  507. DisposeStr(P^.Name);
  508. PI:=P^.Items;
  509. while PI<>nil do
  510. begin
  511. X:=PI^.Next;
  512. DisposeTabItem(PI);
  513. PI:=X;
  514. end;
  515. Dispose(P);
  516. end;
  517. end.