Rights.cpp 17 KB

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