123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455 |
- unit SimplePropEdit;
- (* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Nested Sampling Example
- *
- * The Initial Developer of the Original Code is
- * Mattias Andersson <[email protected]>
- *
- * Portions created by the Initial Developer are Copyright (C) 2000-2005
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- * Michael Hansen <[email protected]>
- * Andre Beckedorf <[email protected]>
- *
- * ***** END LICENSE BLOCK ***** *)
- interface
- uses
- {$IFDEF FPC} LCLIntf, LResources, {$ELSE} Windows, {$ENDIF}
- Forms, Controls, StdCtrls, ExtCtrls, ComCtrls, Grids, Messages, Classes,
- Graphics, TypInfo, GR32_OrdinalMaps;
- const
- WM_SELECTOBJECT = WM_USER + 2000;
- type
- TWMSelectObject = packed record
- Msg: Cardinal;
- Unused: Longint;
- Obj: TPersistent;
- Result: Longint;
- end;
- PPropertyRangeEntry = ^TPropertyRangeEntry;
- TPropertyRangeEntry = record
- AClass: TClass;
- PropName: string;
- LoValue: Single;
- HiValue: Single;
- end;
- TSimplePropertyEditor = class(TCustomPanel)
- private
- FLabels: TList;
- FPropertyControls: TList;
- FPropertyRangeList: TList;
- FSelectedObject: TPersistent;
- FProps: PPropList;
- FCaption: string;
- procedure ButtonHandler(Sender: TObject);
- procedure TrackBarHandler(Sender: TObject);
- procedure ComboBoxHandler(Sender: TObject);
- procedure StringGridEditHandler(Sender: TObject; ACol, ARow: Longint; const Value: string);
- procedure WMSelectObject(var Msg: TWMSelectObject); message WM_SELECTOBJECT;
- protected
- function GetControlClass(Kind: TTypeKind): TPersistentClass; // TODO : Unused. What is its purpose?
- procedure Paint; override;
- public
- constructor Create(AOwner: TComponent); override;
- destructor Destroy; override;
- procedure RemoveSelectedObject;
- procedure SelectObject(ObjName: string; AObject: TPersistent);
- procedure RegisterClassPropertyRange(AClass: TClass; const PropName: string;
- LoValue, HiValue: Single);
- procedure GetPropertyRange(Instance: TObject; const PropName: string;
- out LoValue, HiValue: Single);
- end;
- const
- // scale trackbar min and max values for floating-point properties
- SCALE_FLOAT = 10000;
- implementation
- uses
- SysUtils, Math, GR32, GR32_Resamplers, GR32_LowLevel;
- { TSimplePropertyEditor }
- procedure TSimplePropertyEditor.ButtonHandler(Sender: TObject);
- var
- PropInfo: PPropInfo;
- Obj: TPersistent;
- begin
- PropInfo := FProps^[TComponent(Sender).Tag];
- Obj := TPersistent(GetObjectProp(FSelectedObject, string(PropInfo.Name)));
- PostMessage(Handle, WM_SELECTOBJECT, 0, Integer(Obj));
- end;
- procedure TSimplePropertyEditor.ComboBoxHandler(Sender: TObject);
- var
- PropInfo: PPropInfo;
- begin
- PropInfo := FProps[TComponent(Sender).Tag];
- with PropInfo^ do
- begin
- case PropType^.Kind of
- tkEnumeration:
- SetOrdProp(FSelectedObject, PropInfo, TComboBox(Sender).ItemIndex);
- end;
- end;
- end;
- constructor TSimplePropertyEditor.Create(AOwner: TComponent);
- begin
- inherited Create(AOwner);
- FPropertyControls := TList.Create;
- FLabels := TList.Create;
- FPropertyRangeList := TList.Create;
- BorderWidth := 1;
- BorderStyle := bsNone;
- {$IFNDEF FPC}
- Ctl3D := False;
- {$ENDIF}
- Color := clWhite;
- BevelInner := bvNone;
- BevelOuter := bvNone;
- Font.Size := 7;
- Font.Name := 'Verdana';
- end;
- destructor TSimplePropertyEditor.Destroy;
- var
- I: Integer;
- begin
- if Assigned(FSelectedObject) then
- RemoveSelectedObject;
- FPropertyControls.Free;
- FLabels.Free;
- for I := 0 to FPropertyRangeList.Count - 1 do
- Dispose(PPropertyRangeEntry(FPropertyRangeList.Items[I]));
- FPropertyRangeList.Clear;
- FPropertyRangeList.Free;
- inherited;
- end;
- function TSimplePropertyEditor.GetControlClass(
- Kind: TTypeKind): TPersistentClass;
- begin
- case Kind of
- tkInteger: Result := TEdit;
- tkClass: Result := TButton;
- else
- Result := TEdit;
- end;
- end;
- procedure TSimplePropertyEditor.GetPropertyRange(Instance: TObject;
- const PropName: string; out LoValue, HiValue: Single);
- var
- I: Integer;
- P: PPropertyRangeEntry;
- begin
- LoValue := 0;
- HiValue := 100;
- for I := 0 to FPropertyRangeList.Count - 1 do
- begin
- P := FPropertyRangeList.Items[I];
- if Instance is P.AClass then
- if P.PropName = PropName then
- begin
- LoValue := P.LoValue;
- HiValue := P.HiValue;
- Exit;
- end;
- end;
- end;
- procedure TSimplePropertyEditor.Paint;
- begin
- inherited;
- with Canvas do
- begin
- Brush.Color := clSilver;
- Pen.Color := clWhite;
- Font.Style := [fsBold];
- Font.Size := 8;
- Font.Name := 'Tahoma';
- if FCaption <> '' then
- TextRect(Rect(0, 0, Width, 18), 6, 2, FCaption);
- end;
- end;
- procedure TSimplePropertyEditor.RegisterClassPropertyRange(AClass: TClass;
- const PropName: string; LoValue, HiValue: Single);
- var
- P: PPropertyRangeEntry;
- begin
- New(P);
- P.AClass := AClass;
- P.PropName := PropName;
- P.LoValue := LoValue;
- P.HiValue := HiValue;
- FPropertyRangeList.Add(P);
- end;
- procedure TSimplePropertyEditor.RemoveSelectedObject;
- var
- I: Integer;
- begin
- for I := 0 to FPropertyControls.Count - 1 do
- begin
- if Assigned(FPropertyControls[I]) then
- TWinControl(FPropertyControls[I]).Free;
- if Assigned(Flabels[I]) then
- TLabel(FLabels[I]).Free;
- end;
- FPropertyControls.Clear;
- FLabels.Clear;
- if Assigned(FProps) then
- FreeMem(FProps);
- end;
- procedure TSimplePropertyEditor.SelectObject(ObjName: string; AObject: TPersistent);
- var
- I, L, K, Count, T, T1: Integer;
- Control: TWinControl;
- ALabel: TLabel;
- Map: TIntegerMap;
- LoValue, HiValue: Single;
- P: PPropInfo;
- TD: PTypeData;
- S, SelName: string;
- const
- ROW_SPACE = 30;
- TOP_MARGIN = 20;
- MARGIN_CONTROLS = TOP_MARGIN + 4;
- MARGIN_LABELS = TOP_MARGIN + 8;
- begin
- if Assigned(FSelectedObject) then
- RemoveSelectedObject;
- FSelectedObject := AObject;
- if not Assigned(AObject) then
- begin
- FCaption := '';
- Repaint;
- Exit;
- end;
- FCaption := ObjName + ': ' + AObject.ClassName;
- Count := GetTypeData(AObject.ClassInfo).PropCount;
- if AObject is TIntegerMap then
- begin
- Map := AObject as TIntegerMap;
- Control := TStringGrid.Create(nil);
- with TStringGrid(Control) do
- begin
- RowCount := 5;
- ColCount := 5;
- FixedCols := 0;
- FixedRows := 0;
- DefaultColWidth := 32;
- DefaultRowHeight := 16;
- Options := Options + [goEditing];
- for K := 0 to 4 do
- for L := 0 to 4 do
- Cells[K, L] := FloatToStr(Map[K, L] / 256);
- OnSetEditText := StringGridEditHandler;
- end;
- Control.Width := 168;
- Control.Height := 89;
- Control.Left := 12;
- Control.Top := MARGIN_CONTROLS + ROW_SPACE;
- Control.Parent := Self;
- FPropertyControls.Add(Control);
- ALabel := TLabel.Create(nil);
- ALabel.Caption := 'Kernel / Structuring Element:';
- ALabel.Left := 8;
- ALabel.Top := MARGIN_CONTROLS + 8;
- ALabel.Width := 84;
- ALabel.Parent := Self;
- FLabels.Add(ALabel);
- end;
- FProps := nil;
- if Count > 0 then
- begin
- GetMem(FProps, Count * SizeOf(PPropInfo));
- Count := GetPropList(AObject.ClassInfo, tkProperties, FProps);
- Self.Canvas.Brush.Color := Self.Color;
- T := MARGIN_CONTROLS;
- for I := 0 to Count - 1 do
- begin
- P := FProps[I];
- T1 := T;
- case P.PropType^.Kind of
- tkInteger, tkFloat:
- begin
- GetPropertyRange(AObject, string(P.Name), LoValue, HiValue);
- Control := TTrackBar.Create(nil);
- Control.Parent := Self;
- Control.Tag := I;
- FPropertyControls.Add(Control);
- with TTrackBar(Control) do
- begin
- if P.PropType^.Kind = tkInteger then
- begin
- Min := Round(LoValue);
- Max := Round(HiValue);
- Frequency := Math.Max(1, Round(HiValue - LoValue) div 20);
- Position := GetOrdProp(FSelectedObject, P)
- end
- else
- begin
- LoValue := LoValue * SCALE_FLOAT;
- HiValue := HiValue * SCALE_FLOAT;
- Min := Round(LoValue);
- Max := Round(HiValue);
- Frequency := Math.Max(1, Round((HiValue - LoValue) / 20));
- Position := Round(GetFloatProp(FSelectedObject, P) * SCALE_FLOAT);
- end;
- {$IFNDEF FPC}
- ThumbLength := 16;
- {$ENDIF}
- OnChange := TrackBarHandler;
- end;
- Control.Width := 98;
- Control.Height := 25;
- Control.Left := 88;
- Control.Top := T + 4;
- end;
- tkClass:
- begin
- Control := TButton.Create(nil);
- Control.Parent := Self;
- Control.Tag := I;
- FPropertyControls.Add(Control);
- TButton(Control).OnClick := ButtonHandler;
- TButton(Control).Caption := 'Edit';
- Control.Width := 60;
- Control.Height := 20;
- Control.Left := 90;
- Control.Top := T + 4;
- if GetObjectProp(FSelectedObject, P) = nil then
- Control.Enabled := False;
- end;
- tkEnumeration:
- begin
- Control := TComboBox.Create(nil);
- Control.Parent := Self;
- Control.Tag := I;
- FPropertyControls.Add(Control);
- TComboBox(Control).OnChange := ComboBoxHandler;
- TComboBox(Control).Style := csDropDownList;
- Control.Width := 100;
- Control.Height := 20;
- Control.Left := 90;
- Control.Top := T + 4;
- SelName := GetEnumProp(FSelectedObject, P);
- {$IFDEF FPC}
- TD := GetTypeData(P.PropType);
- {$ELSE}
- TD := GetTypeData(P.PropType^);
- {$ENDIF}
- L := 0;
- for K := TD.MinValue to TD.MaxValue do
- begin
- {$IFDEF FPC}
- S := GetEnumName(P.PropType, K);
- {$ELSE}
- S := GetEnumName(P.PropType^, K);
- {$ENDIF}
- if S = SelName then L := K;
- TComboBox(Control).AddItem(S, nil);
- end;
- TComboBox(Control).ItemIndex := L;
- end;
- else
- FPropertyControls.Add(nil);
- FLabels.Add(nil);
- Continue;
- end;
- ALabel := TLabel.Create(nil);
- ALabel.Caption := string(P.Name + ':');
- ALabel.Left := 0;
- ALabel.Top := T1 + 8;
- ALabel.Width := 84;
- ALabel.Alignment := taRightJustify;
- ALabel.Parent := Self;
- FLabels.Add(ALabel);
- Inc(T, ROW_SPACE);
- end;
- end;
- Repaint;
- end;
- procedure TSimplePropertyEditor.StringGridEditHandler(Sender: TObject;
- ACol, ARow: Integer; const Value: string);
- var
- Weights: TIntegerMap;
- W: Real;
- Code: Integer;
- begin
- Weights := FSelectedObject as TIntegerMap;
- Val(Value, W, Code);
- if Code = 0 then
- Weights[ACol, ARow] := Round(W * 256);
- end;
- procedure TSimplePropertyEditor.TrackBarHandler(Sender: TObject);
- var
- PropInfo: PPropInfo;
- begin
- PropInfo := FProps[TComponent(Sender).Tag];
- with PropInfo^ do
- begin
- case PropType^.Kind of
- tkInteger:
- SetOrdProp(FSelectedObject, PropInfo, TTrackBar(Sender).Position);
- tkFloat:
- SetFloatProp(FSelectedObject, PropInfo, TTrackBar(Sender).Position / SCALE_FLOAT);
- end;
- end;
- end;
- procedure TSimplePropertyEditor.WMSelectObject(var Msg: TWMSelectObject);
- begin
- SelectObject('Object', Msg.Obj);
- end;
- end.
|