Rights.cpp 18 KB

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