Rights.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574
  1. //---------------------------------------------------------------------------
  2. #include <vcl.h>
  3. #pragma hdrstop
  4. #include "Rights.h"
  5. #include <Common.h>
  6. #include <VCLCommon.h>
  7. #include <Tools.h>
  8. #include <GUITools.h>
  9. //---------------------------------------------------------------------------
  10. #pragma package(smart_init)
  11. #pragma link "GrayedCheckBox"
  12. #pragma resource "*.dfm"
  13. //---------------------------------------------------------------------------
  14. __fastcall TRightsFrame::TRightsFrame(TComponent* Owner)
  15. : TFrame(Owner)
  16. {
  17. FAddXToDirectoriesSuffix = "+x";
  18. FOnChange = NULL;
  19. FAllowAddXToDirectories = true;
  20. FPopup = false;
  21. FPopupParent = NULL;
  22. FDefaultButton = NULL;
  23. FCancelButton = NULL;
  24. // to avoid duplication of reference in forms that uses the frame
  25. PopupMenu = RightsPopup;
  26. FPopingContextMenu = false;
  27. #define COPY_HINT(R) \
  28. Checks[TRights::rrGroup ## R]->Hint = Checks[TRights::rrUser ## R]->Hint; \
  29. Checks[TRights::rrOther ## R]->Hint = Checks[TRights::rrUser ## R]->Hint;
  30. COPY_HINT(Read);
  31. COPY_HINT(Write);
  32. COPY_HINT(Exec);
  33. #undef COPY_HINT
  34. }
  35. //---------------------------------------------------------------------------
  36. __fastcall TRightsFrame::~TRightsFrame()
  37. {
  38. }
  39. //---------------------------------------------------------------------------
  40. void __fastcall TRightsFrame::SetStates(TRights::TRight Right, TRights::TState value)
  41. {
  42. assert(((value == TRights::rsNo) || (value == TRights::rsYes) || (value == TRights::rsUndef)));
  43. TCheckBox * CheckBox = Checks[Right];
  44. if (CheckBox != NULL)
  45. {
  46. switch (value) {
  47. case TRights::rsNo: CheckBox->State = cbUnchecked; break;
  48. case TRights::rsYes: CheckBox->State = cbChecked; break;
  49. case TRights::rsUndef: CheckBox->State = cbGrayed; break;
  50. }
  51. }
  52. }
  53. //---------------------------------------------------------------------------
  54. TRights::TState __fastcall TRightsFrame::GetStates(TRights::TRight Right)
  55. {
  56. TCheckBox * CheckBox = Checks[Right];
  57. if (CheckBox != NULL)
  58. {
  59. switch (CheckBox->State) {
  60. case cbUnchecked: return TRights::rsNo;
  61. case cbChecked: return TRights::rsYes;
  62. case cbGrayed:
  63. default: return TRights::rsUndef;
  64. }
  65. }
  66. else
  67. {
  68. return TRights::rsNo;
  69. }
  70. }
  71. //---------------------------------------------------------------------------
  72. void __fastcall TRightsFrame::SetRights(const TRights & value)
  73. {
  74. bool Changed = (AllowUndef != value.AllowUndef);
  75. AllowUndef = true; // temporarily
  76. for (int Right = TRights::rrFirst; Right <= TRights::rrLast; Right++)
  77. {
  78. TRights::TRight R = static_cast<TRights::TRight>(Right);
  79. if (States[R] != value.RightUndef[R])
  80. {
  81. States[R] = value.RightUndef[R];
  82. Changed = true;
  83. }
  84. }
  85. AllowUndef = value.AllowUndef;
  86. if (Changed)
  87. {
  88. UpdateControls();
  89. }
  90. }
  91. //---------------------------------------------------------------------------
  92. TRights __fastcall TRightsFrame::GetRights()
  93. {
  94. TRights Result;
  95. Result.AllowUndef = AllowUndef;
  96. for (int Right = TRights::rrFirst; Right <= TRights::rrLast; Right++)
  97. {
  98. Result.RightUndef[static_cast<TRights::TRight>(Right)] =
  99. States[static_cast<TRights::TRight>(Right)];
  100. }
  101. return Result;
  102. }
  103. //---------------------------------------------------------------------------
  104. void __fastcall TRightsFrame::SetAllowUndef(bool value)
  105. {
  106. for (int Right = TRights::rrFirst; Right <= TRights::rrLast; Right++)
  107. {
  108. TCheckBox * CheckBox = Checks[static_cast<TRights::TRight>(Right)];
  109. if (CheckBox != NULL)
  110. {
  111. CheckBox->AllowGrayed = value;
  112. }
  113. }
  114. }
  115. //---------------------------------------------------------------------------
  116. bool __fastcall TRightsFrame::GetAllowUndef()
  117. {
  118. bool Result = false, First = true;
  119. for (int Right = TRights::rrFirst; Right <= TRights::rrLast; Right++)
  120. {
  121. TCheckBox * Check = Checks[static_cast<TRights::TRight>(Right)];
  122. if (Check != NULL)
  123. {
  124. if (First)
  125. {
  126. Result = Check->AllowGrayed;
  127. First = false;
  128. }
  129. else if (Result != Check->AllowGrayed)
  130. {
  131. assert(false);
  132. }
  133. }
  134. }
  135. return Result;
  136. }
  137. //---------------------------------------------------------------------------
  138. TCheckBox * __fastcall TRightsFrame::GetChecks(TRights::TRight Right)
  139. {
  140. for (int Index = 0; Index < ControlCount; Index++)
  141. {
  142. if (Controls[Index]->InheritsFrom(__classid(TCheckBox)) &&
  143. (Controls[Index]->Tag == TRights::RightToFlag(Right)))
  144. {
  145. return ((TCheckBox *)Controls[Index]);
  146. }
  147. }
  148. return NULL;
  149. }
  150. //---------------------------------------------------------------------------
  151. void __fastcall TRightsFrame::SetAddXToDirectories(bool value)
  152. {
  153. DirectoriesXCheck->Checked = value;
  154. }
  155. //---------------------------------------------------------------------------
  156. bool __fastcall TRightsFrame::GetAddXToDirectories()
  157. {
  158. return DirectoriesXCheck->Checked;
  159. }
  160. //---------------------------------------------------------------------------
  161. void __fastcall TRightsFrame::ControlChange(TObject * /*Sender*/)
  162. {
  163. UpdateControls();
  164. }
  165. //---------------------------------------------------------------------------
  166. bool __fastcall TRightsFrame::DirectoriesXEffective()
  167. {
  168. return !((Rights.NumberSet & TRights::rfExec) == TRights::rfExec);
  169. }
  170. //---------------------------------------------------------------------------
  171. void __fastcall TRightsFrame::UpdateControls()
  172. {
  173. Color = (FPopup ? clWindow : clBtnFace);
  174. DirectoriesXCheck->Visible = AllowAddXToDirectories;
  175. EnableControl(DirectoriesXCheck,
  176. Enabled && DirectoriesXEffective());
  177. DoChange();
  178. }
  179. //---------------------------------------------------------------------------
  180. void __fastcall TRightsFrame::CycleRights(int Group)
  181. {
  182. TRights::TState State;
  183. bool Same = true;
  184. for (int Right = 0; Right < 3; Right++)
  185. {
  186. TRights::TState CState = States[static_cast<TRights::TRight>(
  187. TRights::rrUserRead + Right + ((Group - 1) * 3))];
  188. if (Right == 0) State = CState;
  189. else
  190. if (State != CState) Same = False;
  191. }
  192. if (!Same)
  193. {
  194. State = TRights::rsYes;
  195. }
  196. else
  197. {
  198. switch (State) {
  199. case TRights::rsYes:
  200. State = TRights::rsNo;
  201. break;
  202. case TRights::rsNo:
  203. State = AllowUndef ? TRights::rsUndef : TRights::rsYes;
  204. break;
  205. case TRights::rsUndef:
  206. State = TRights::rsYes;
  207. break;
  208. }
  209. }
  210. for (int Right = 0; Right < 3; Right++)
  211. {
  212. States[static_cast<TRights::TRight>(
  213. TRights::rrUserRead + Right + ((Group - 1) * 3))] = State;
  214. }
  215. UpdateControls();
  216. }
  217. //---------------------------------------------------------------------------
  218. void __fastcall TRightsFrame::RightsButtonsClick(TObject *Sender)
  219. {
  220. CycleRights(((TComponent*)Sender)->Tag);
  221. }
  222. //---------------------------------------------------------------------------
  223. void __fastcall TRightsFrame::SetAllowAddXToDirectories(bool value)
  224. {
  225. if (FAllowAddXToDirectories != value)
  226. {
  227. FAllowAddXToDirectories = value;
  228. UpdateControls();
  229. }
  230. }
  231. //---------------------------------------------------------------------------
  232. void __fastcall TRightsFrame::DoChange()
  233. {
  234. if (FOnChange)
  235. {
  236. FOnChange(this);
  237. }
  238. }
  239. //---------------------------------------------------------------------------
  240. void __fastcall TRightsFrame::SetEnabled(bool Value)
  241. {
  242. TFrame::SetEnabled(Value);
  243. UpdateControls();
  244. }
  245. //---------------------------------------------------------------------------
  246. void __fastcall TRightsFrame::ForceUpdate()
  247. {
  248. }
  249. //---------------------------------------------------------------------------
  250. bool __fastcall TRightsFrame::HasFocus()
  251. {
  252. return
  253. (Focused() ||
  254. ((Screen->ActiveControl != NULL) && (Screen->ActiveControl->Parent == this))) ||
  255. ((PopupParent != NULL) && PopupParent->Focused());
  256. }
  257. //---------------------------------------------------------------------------
  258. void __fastcall TRightsFrame::RightsActionsExecute(TBasicAction * Action,
  259. bool & Handled)
  260. {
  261. // prevent shortcuts to be avaluated when frame does not have a focus
  262. if (HasFocus())
  263. {
  264. bool Changed = true;
  265. TRights R = Rights;
  266. R.Number = TRights::rfNo;
  267. Handled = true;
  268. if (Action == NoRightsAction)
  269. {
  270. R = TRights::rfNo;
  271. }
  272. else if (Action == DefaultRightsAction)
  273. {
  274. R = TRights::rfDefault;
  275. }
  276. else if (Action == AllRightsAction)
  277. {
  278. R = TRights::rfAll;
  279. }
  280. else if (Action == LeaveRightsAsIsAction)
  281. {
  282. R.AllUndef();
  283. }
  284. else
  285. {
  286. Handled = false;
  287. }
  288. if (Changed)
  289. {
  290. Rights = R;
  291. ForceUpdate();
  292. DoChange();
  293. }
  294. }
  295. }
  296. //---------------------------------------------------------------------------
  297. void __fastcall TRightsFrame::RightsActionsUpdate(TBasicAction *Action,
  298. bool &Handled)
  299. {
  300. TRights R = Rights;
  301. Handled = true;
  302. if (Action == NoRightsAction)
  303. {
  304. // explicitly enable as action gets disabled, if its shortcut is pressed,
  305. // while the form does not have a focus and OnExecute handler denies the execution
  306. NoRightsAction->Enabled = true;
  307. NoRightsAction->Checked = !R.IsUndef && (R.NumberSet == TRights::rfNo);
  308. }
  309. else if (Action == DefaultRightsAction)
  310. {
  311. DefaultRightsAction->Enabled = true;
  312. DefaultRightsAction->Checked = !R.IsUndef && (R.NumberSet == TRights::rfDefault);
  313. }
  314. else if (Action == AllRightsAction)
  315. {
  316. AllRightsAction->Enabled = true;
  317. AllRightsAction->Checked = !R.IsUndef && (R.NumberSet == TRights::rfAll);
  318. }
  319. else if (Action == LeaveRightsAsIsAction)
  320. {
  321. LeaveRightsAsIsAction->Enabled = true;
  322. LeaveRightsAsIsAction->Visible = R.AllowUndef;
  323. LeaveRightsAsIsAction->Checked = (R.NumberSet == TRights::rfNo) &&
  324. (R.NumberUnset == TRights::rfNo);
  325. }
  326. else
  327. {
  328. Handled = false;
  329. }
  330. }
  331. //---------------------------------------------------------------------------
  332. void __fastcall TRightsFrame::CreateParams(TCreateParams & Params)
  333. {
  334. TFrame::CreateParams(Params);
  335. if (FPopup)
  336. {
  337. Params.Style |= WS_BORDER;
  338. }
  339. }
  340. //---------------------------------------------------------------------------
  341. void __fastcall TRightsFrame::CreateWnd()
  342. {
  343. if (FPopup)
  344. {
  345. Width += 2 * GetSystemMetrics(SM_CXBORDER);
  346. Height += 2 * GetSystemMetrics(SM_CYBORDER);
  347. }
  348. TFrame::CreateWnd();
  349. }
  350. //---------------------------------------------------------------------------
  351. void __fastcall TRightsFrame::SetPopup(bool value)
  352. {
  353. if (Popup != value)
  354. {
  355. FPopup = value;
  356. Visible = !FPopup;
  357. }
  358. }
  359. //---------------------------------------------------------------------------
  360. void __fastcall TRightsFrame::DoCloseUp()
  361. {
  362. Hide();
  363. if (FDefaultButton != NULL)
  364. {
  365. FDefaultButton->Default = true;
  366. FDefaultButton = NULL;
  367. }
  368. if (FCancelButton != NULL)
  369. {
  370. FCancelButton->Cancel = true;
  371. FCancelButton = NULL;
  372. }
  373. }
  374. //---------------------------------------------------------------------------
  375. void __fastcall TRightsFrame::DoExit()
  376. {
  377. // this is bit hack to make frame hide when ComboEdit button is pressed while
  378. // from is poped-up already.
  379. if (FPopup && !IsAncestor(Screen->ActiveControl, FPopupParent))
  380. {
  381. DoCloseUp();
  382. }
  383. TFrame::DoExit();
  384. }
  385. //---------------------------------------------------------------------------
  386. bool __fastcall TRightsFrame::IsAncestor(TControl * Control, TControl * Ancestor)
  387. {
  388. while ((Control != NULL) &&
  389. (Control->Parent != Ancestor))
  390. {
  391. Control = Control->Parent;
  392. }
  393. return (Control != NULL);
  394. }
  395. //---------------------------------------------------------------------------
  396. void __fastcall TRightsFrame::WMContextMenu(TWMContextMenu & Message)
  397. {
  398. FPopingContextMenu = true;
  399. try
  400. {
  401. TFrame::Dispatch(&Message);
  402. }
  403. __finally
  404. {
  405. FPopingContextMenu = false;
  406. }
  407. }
  408. //---------------------------------------------------------------------------
  409. void __fastcall TRightsFrame::CMDialogKey(TCMDialogKey & Message)
  410. {
  411. if (FPopup && Visible &&
  412. ((Message.CharCode == VK_RETURN) ||
  413. (Message.CharCode == VK_ESCAPE)) &&
  414. KeyDataToShiftState(Message.KeyData).Empty())
  415. {
  416. CloseUp();
  417. Message.Result = 1;
  418. }
  419. else
  420. {
  421. TFrame::Dispatch(&Message);
  422. }
  423. }
  424. //---------------------------------------------------------------------------
  425. void __fastcall TRightsFrame::CMCancelMode(TCMCancelMode & Message)
  426. {
  427. if (FPopup && Visible && !FPopingContextMenu &&
  428. ((Message.Sender == NULL) ||
  429. (!IsAncestor(Message.Sender, this) &&
  430. !IsAncestor(Message.Sender, FPopupParent) &&
  431. (Message.Sender != this))))
  432. {
  433. CloseUp();
  434. }
  435. TFrame::Dispatch(&Message);
  436. }
  437. //---------------------------------------------------------------------------
  438. void __fastcall TRightsFrame::Dispatch(void * Message)
  439. {
  440. TMessage & AMessage = *static_cast<TMessage *>(Message);
  441. switch (AMessage.Msg)
  442. {
  443. case CM_CANCELMODE:
  444. CMCancelMode(*(TCMCancelMode *)Message);
  445. break;
  446. case CM_DIALOGKEY:
  447. CMDialogKey(*(TCMDialogKey *)Message);
  448. break;
  449. case WM_CONTEXTMENU:
  450. WMContextMenu(*(TWMContextMenu *)Message);
  451. break;
  452. default:
  453. TFrame::Dispatch(Message);
  454. break;
  455. }
  456. }
  457. //---------------------------------------------------------------------------
  458. void __fastcall TRightsFrame::DropDown()
  459. {
  460. TCustomForm * Form = GetParentForm(this);
  461. // due to lack of better idea, we clear "default" and "cancel" flags of respective
  462. // form buttons to prevent them to handle ESC/ENTER keys.
  463. for (int Index = 0; Index < Form->ControlCount; Index++)
  464. {
  465. TButton * Button = dynamic_cast<TButton *>(Form->Controls[Index]);
  466. if (Button != NULL)
  467. {
  468. if (Button->Default)
  469. {
  470. assert(FDefaultButton == NULL);
  471. FDefaultButton = Button;
  472. Button->Default = false;
  473. }
  474. if (Button->Cancel)
  475. {
  476. assert(FCancelButton == NULL);
  477. FCancelButton = Button;
  478. Button->Cancel = false;
  479. }
  480. }
  481. }
  482. TPoint Origin(PopupParent->Left, PopupParent->Top + PopupParent->Height);
  483. Origin = Parent->ScreenToClient(PopupParent->Parent->ClientToScreen(Origin));
  484. if (Origin.x + Width > Parent->ClientWidth)
  485. {
  486. Origin.x += PopupParent->Width - Width;
  487. }
  488. Left = Origin.x;
  489. Top = Origin.y;
  490. Show();
  491. SetFocus();
  492. }
  493. //---------------------------------------------------------------------------
  494. void __fastcall TRightsFrame::CloseUp()
  495. {
  496. assert(FPopup);
  497. assert(Visible);
  498. if (!Focused())
  499. {
  500. // this can happen only if called from on-click handler of drop down button
  501. DoCloseUp();
  502. }
  503. FPopupParent->SetFocus();
  504. }
  505. //---------------------------------------------------------------------------
  506. AnsiString __fastcall TRightsFrame::GetText()
  507. {
  508. AnsiString Result = Rights.Text;
  509. if (AllowAddXToDirectories && DirectoriesXEffective() && AddXToDirectories)
  510. {
  511. Result = FORMAT("%s (%s)", (Result, FAddXToDirectoriesSuffix));
  512. }
  513. return Result;
  514. }
  515. //---------------------------------------------------------------------------
  516. void __fastcall TRightsFrame::SetText(AnsiString value)
  517. {
  518. if (Text != value)
  519. {
  520. AnsiString RightsStr = value;
  521. int P = RightsStr.LowerCase().Pos(FAddXToDirectoriesSuffix);
  522. bool AAddXToDirectories = (P > 0);
  523. if (AAddXToDirectories)
  524. {
  525. RightsStr.Delete(P, FAddXToDirectoriesSuffix.Length());
  526. }
  527. RightsStr = DeleteChar(DeleteChar(RightsStr, '('), ')').Trim();
  528. TRights R = Rights;
  529. int Dummy;
  530. if (((RightsStr.Length() == 3) || (RightsStr.Length() == 4)) &&
  531. TryStrToInt(RightsStr, Dummy))
  532. {
  533. R.Octal = RightsStr;
  534. }
  535. else
  536. {
  537. R.Text = RightsStr;
  538. }
  539. Rights = R;
  540. AddXToDirectories = AAddXToDirectories;
  541. }
  542. }
  543. //---------------------------------------------------------------------------
  544. void __fastcall TRightsFrame::RightsPopupPopup(TObject * /*Sender*/)
  545. {
  546. if (!HasFocus())
  547. {
  548. SetFocus();
  549. }
  550. }
  551. //---------------------------------------------------------------------------