summaryrefslogtreecommitdiff
path: root/src/gui/fpg_readonly.pas
blob: dcdee723ca61a19caed174316fab2b957adc2f07 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
{
    fpGUI  -  Free Pascal GUI Toolkit

    Copyright (C) 2006 - 2011 See the file AUTHORS.txt, included in this
    distribution, for details of the copyright.

    See the file COPYING.modifiedLGPL, included in this distribution,
    for details about redistributing fpGUI.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

    Description:
      A component that can set all components on a form and embedded
      containers as read-only or not. There are various events that
      fire during the process, to allow for maximum flexibility.
}

unit fpg_readonly;

{$mode objfpc}{$H+}

interface

uses
  Classes
 ;

type
  TfpgOnChangeReadOnlyEvent = procedure(pSender: TObject; pReadOnly: boolean) of object;
  TfpgOnProcessEvent = procedure(pSender: TObject; var pReadOnly, pProcess: boolean) of object;
  TfpgOnProcessFrmEvent = procedure(pFrame: TComponent; var pProcessDetails: boolean) of object;
  TfpgOnGetParentEvent = procedure(var pParent: TComponent) of object;


  TfpgReadOnly = class(TComponent)
  private
    FReadOnly: boolean;
    FOnChange: TfpgOnChangeReadOnlyEvent;
    FOnProcess: TfpgOnProcessEvent;
    FEnabled: boolean;
    FOnProcessFrm: TfpgOnProcessFrmEvent;
    FProcessContainer: boolean;
    FOnGetParent: TfpgOnGetParentEvent;
    procedure   SetEnabled(const AValue: boolean);
  protected
    function    GetReadOnly: boolean; virtual;
    procedure   SetReadOnly(const AValue: boolean); virtual;
    procedure   SetComponentsReadOnly(pReadOnly: boolean); virtual;
    function    GetParentForm: TComponent;
  public
    constructor Create(AOwner: TComponent); override;
  published
    property    ReadOnly: boolean read GetReadOnly write SetReadOnly default false;
    property    Enabled: boolean read FEnabled write SetEnabled default false;
    property    ProcessContainer: boolean read FProcessContainer write FProcessContainer default false;
    property    OnChange: TfpgOnChangeReadOnlyEvent read FOnChange write FOnChange;
    property    OnProcess: TfpgOnProcessEvent read FOnProcess write FOnProcess;
    property    OnProcessFrm: TfpgOnProcessFrmEvent read FOnProcessFrm write FOnProcessFrm;
    property    OnGetParent: TfpgOnGetParentEvent read FOnGetParent write FOnGetParent;
  end;


implementation

uses
  fpg_main
  ,fpg_form
  ,fpg_widget
  ,TypInfo
  ;

{ TfpgReadOnly }

constructor TfpgReadOnly.Create(AOwner: TComponent);
begin
  inherited;
  FReadOnly := false;
  FEnabled := false;
  FProcessContainer := false;
end;

function TfpgReadOnly.GetParentForm: TComponent;
begin
  result := self;
  while true do
  begin
    if (result is TfpgForm) and
      ((result.Owner is TfpgApplication) or
      (result.Owner = nil)) then
      Break; //==>
    result := result.Owner;
  end;
  if Assigned(FOnGetParent) then
    FOnGetParent(result);
end;

function TfpgReadOnly.GetReadOnly: boolean;
begin
  Result := FReadOnly;
end;

procedure TfpgReadOnly.SetComponentsReadOnly(pReadOnly: boolean);
  procedure _SetComponentsReadOnly(pParent: TComponent);
  var
    i: integer;
    lComponent: TComponent;
    lReadOnly, lProcess: boolean;
  begin
    if pParent=nil then
      Exit; //==>
    for i := 0 to pParent.ComponentCount - 1 do
    begin
      lComponent := pParent.Components[i];
      if lComponent = self then
        Continue; //==>
      if IsPublishedProp(lComponent, 'ReadOnly') then
      begin
        lReadOnly := pReadOnly;
        lProcess := True;
        if Assigned(FOnProcess) then
          FOnProcess(lComponent, lReadOnly, lProcess);
        if lProcess then
          SetOrdProp(lComponent, 'ReadOnly', Ord(lReadOnly));
      end;
      if (lComponent is TfpgWidget) and TfpgWidget(lComponent).IsContainer then
      begin
        lProcess := FProcessContainer; // Now lProcess is: can I go Deep?
        if Assigned(FOnProcessFrm) then
          FOnProcessFrm(lComponent, lProcess);
        if lProcess then
          _SetComponentsReadOnly(lComponent);
      end;
    end;
  end;
begin
  _SetComponentsReadOnly(GetParentForm);
end;

procedure TfpgReadOnly.SetEnabled(const AValue: boolean);
begin
  FEnabled := AValue;
end;

procedure TfpgReadOnly.SetReadOnly(const AValue: boolean);
begin
  if not FEnabled then
    Exit; //==>
  if FReadOnly = AValue then
    Exit; //==>
  FReadOnly := AValue;
  SetComponentsReadOnly(FReadOnly);
  if Assigned(FOnChange) then
    FOnChange(Self, FReadOnly);
end;

end.