unit JvIP4AddressProp; {$I jvcl.inc} interface uses JvComCtrls, DesignEditors, DesignIntf; type TJvIP4AddressProperty = class(TOrdinalProperty) public function GetAttributes: TPropertyAttributes; override; procedure GetProperties(Proc: TGetPropProc); override; function GetValue: string; override; // procedure SetValue(const Value: string); overload; override; end; TJvIP4AddressAsTextProperty = class(TNestedProperty) public function GetName: string; override; function GetValue: string; override; procedure SetValue(const Value: string); override; function GetAttributes: TPropertyAttributes; override; end; TJvIP4AddressAsNumberProperty = class(TNestedProperty) public function GetName: string; override; function GetValue: string; override; procedure SetValue(const Value: string); override; function GetAttributes: TPropertyAttributes; override; end; TJvIP4AddressComponentProperty = class(TNestedProperty) protected idx, ValIdx: Byte; public function GetName: string; override; function GetValue: string; override; procedure SetValue(const Value: string); override; function GetAttributes: TPropertyAttributes; override; procedure GetProperties(Proc: TGetPropProc); override; end; TJvIP4AddressRangeProperty = class(TNestedProperty) protected idx: Byte; IsMax: Boolean; function GetTheValue: byte; public function GetName: string; override; function GetValue: string; override; procedure SetValue(const Value: string); override; function GetAttributes: TPropertyAttributes; override; function GetIsDefault: Boolean; override; end; implementation uses SysUtils; // helpers for SetOrdValue(StrToInt(Value:Cardinal)); // Should care for values between high(integer) and high(cardinal) // Delphi has UIntToStr() but not StrToUInt() // better be moved to JclSysUtils function TryStrToUInt(const Value: string; out Res: Cardinal): boolean; var i6: Int64; begin Result := false; if not TryStrToInt64(Value, i6) then exit; if ( i6 < Low(Res)) or ( i6 > High(Res)) then exit; Result := true; Res := i6; end; function StrToUIntDef(const Value: string; const Default: Cardinal): Cardinal; begin if not TryStrToUInt(Value, Result) then Result := Default; end; function StrToUInt(const Value: string): Cardinal; begin if not TryStrToUInt(Value, Result) then raise EConvertError.Create('"'+Value+'" is not within range of Cardinal data type'); end; { TJvIP4AddressProperty } //function TJvIP4AddressProperty.GetAttributes: TPropertyAttributes; //begin // Result := [paMultiSelect, paSubProperties, paRevertable, paVolatileSubProperties]; // if GetPropInfo.SetProc = nil then // Result := Result + [paReadOnly, paDisplayReadOnly]; //end; function TJvIP4AddressProperty.GetAttributes: TPropertyAttributes; begin Result := [paReadOnly, paDisplayReadOnly, paMultiSelect, paSubProperties, paRevertable, paVolatileSubProperties]; end; procedure TJvIP4AddressProperty.GetProperties(Proc: TGetPropProc); var E: IProperty; I: Integer; vp: TJvIP4AddressComponentProperty; begin // outcome layout in OI: // byte values // x.x.x.x for easy editing (adjusting) // 12345 for easy editing (adjusting) for i := Low(TJvIP4AddressComponentIndex) to High(TJvIP4AddressComponentIndex) do begin vp := TJvIP4AddressComponentProperty.Create(Self); vp.idx := I; vp.ValIdx := 5-i; e := vp; // that's how it is in Delphi OTA sources Proc(e); e := nil; // told t be required for proper reference counting end; e := TJvIP4AddressAsTextProperty.Create(Self); Proc(e); e := nil; e := TJvIP4AddressAsNumberProperty.Create(Self); Proc(e); e := nil; end; function TJvIP4AddressProperty.GetValue: string; var val: JvComCtrls.TJvIP4AddressDual; begin val.Address := GetOrdValue; with val do Result := Format('%u = %d.%d.%d.%d', [Address, Comps[4], Comps[3], Comps[2], Comps[1]] ) end; //procedure TJvIP4AddressProperty.SetValue(const Value: string); //var tmp: Cardinal; //begin // if TryStrToUInt(Value, tmp) then SetOrdValue(tmp) // else // if GetComponent(0) <> nil then // if GetComponent(0) is TJvIPAddress then begin // TJvIPAddress(GetComponent(0)).Text := Value; // Modified; // end; //end; // { TJvIP4AddressComponentProperty } function TJvIP4AddressComponentProperty.GetAttributes: TPropertyAttributes; begin Result := [paMultiSelect, paRevertable]; if GetPropInfo.SetProc = nil then Result := Result + [paReadOnly, paDisplayReadOnly]; if GetComponent(0) <> nil then if GetComponent(0) is TJvIPAddress then Include(Result, paSubProperties); end; function TJvIP4AddressComponentProperty.GetName: string; begin // Result := 'Value '+IntToStr(idx); Result := ' .AddressValue['+Char(idx+Ord('0')) +']'; end; procedure TJvIP4AddressComponentProperty.GetProperties(Proc: TGetPropProc); var E: IProperty; mx:Boolean; vp: TJvIP4AddressRangeProperty; begin if GetComponent(0) <> nil then if GetComponent(0) is TJvIPAddress then for mx := false to true do begin vp := TJvIP4AddressRangeProperty.Create(self); vp.idx := idx; vp.IsMax := mx; e := vp; Proc(e); e := nil; end; end; function TJvIP4AddressComponentProperty.GetValue: string; var val: JvComCtrls.TJvIP4AddressDual; begin val.Address := GetOrdValue; Result := IntToStr(val.Comps[ValIdx]); end; procedure TJvIP4AddressComponentProperty.SetValue(const Value: string); var val: JvComCtrls.TJvIP4AddressDual; i: integer; begin if TryStrToInt(Value, i) then if (i>=0) and (i<=255) then begin val.Address := GetOrdValue; val.Comps[valIdx] := Byte(i); SetOrdValue(val.Address); end; end; { TJvIP4AddressRangeProperty } function TJvIP4AddressRangeProperty.GetAttributes: TPropertyAttributes; begin Result := [paMultiSelect, paRevertable, paVolatileSubProperties]; end; function TJvIP4AddressRangeProperty.GetIsDefault: Boolean; const DefVal: array[boolean] of byte = (0, 255); begin Result := GetTheValue = DefVal[IsMax]; end; function TJvIP4AddressRangeProperty.GetName: string; begin if IsMax then Result := 'Max' else Result := 'Min'; Result := Result + ' ' + IntToStr(idx); end; function TJvIP4AddressRangeProperty.GetTheValue: byte; var Range: TJvIPAddressRange; tmp: byte; begin if isMax then tmp := 255 else tmp := 0; if GetComponent(0) <> nil then if GetComponent(0) is TJvIPAddress then begin Range := TJvIPAddress(GetComponent(0)).Range; if IsMax then tmp := Range.Max[Idx] else tmp := Range.Min[Idx]; end; Result := tmp; end; function TJvIP4AddressRangeProperty.GetValue: string; begin if GetComponent(0) <> nil then if GetComponent(0) is TJvIPAddress then begin Result := IntToStr(GetTheValue); end; end; procedure TJvIP4AddressRangeProperty.SetValue(const Value: string); var Range: TJvIPAddressRange; tmp: integer; begin if TryStrToInt(Value, tmp) then if (tmp>=0) and (tmp <= 255) then if GetComponent(0) <> nil then if GetComponent(0) is TJvIPAddress then begin Range := TJvIPAddress(GetComponent(0)).Range; if IsMax then Range.Max[Idx] := tmp else Range.Min[Idx] := tmp; Modified; end; end; { TJvIP4AddressAsNumberProperty } function TJvIP4AddressAsNumberProperty.GetAttributes: TPropertyAttributes; begin Result := [paMultiSelect, paRevertable]; if GetPropInfo.SetProc = nil then Result := Result + [paReadOnly, paDisplayReadOnly]; end; function TJvIP4AddressAsNumberProperty.GetName: string; begin Result := ' as .Address'; end; function TJvIP4AddressAsNumberProperty.GetValue: string; begin Result := UIntToStr(Cardinal(GetOrdValue)); end; procedure TJvIP4AddressAsNumberProperty.SetValue(const Value: string); begin SetOrdValue(StrToUInt(Value)); end; { TJvIP4AddressAsTextProperty } function TJvIP4AddressAsTextProperty.GetAttributes: TPropertyAttributes; begin Result := [paMultiSelect, paRevertable]; if GetPropInfo.SetProc = nil then Result := Result + [paReadOnly, paDisplayReadOnly]; end; function TJvIP4AddressAsTextProperty.GetName: string; begin Result := ' as .Text'; end; function TJvIP4AddressAsTextProperty.GetValue: string; var val: JvComCtrls.TJvIP4AddressDual; begin val.Address := GetOrdValue; with val do Result := Format('%d.%d.%d.%d', [Comps[4], Comps[3], Comps[2], Comps[1]] ) end; procedure TJvIP4AddressAsTextProperty.SetValue(const Value: string); begin if GetComponent(0) <> nil then if GetComponent(0) is TJvIPAddress then begin TJvIPAddress(GetComponent(0)).Text := Value; Modified; end; end; end.