diff options
Diffstat (limited to 'extras/tiopf')
-rw-r--r-- | extras/tiopf/demos/Common/Constants.pas | 14 | ||||
-rw-r--r-- | extras/tiopf/demos/Common/Model.pas | 203 | ||||
-rw-r--r-- | extras/tiopf/demos/Common/Model_View.pas | 151 | ||||
-rw-r--r-- | extras/tiopf/demos/EditControlsDemo/editmediators.lpi | 82 | ||||
-rw-r--r-- | extras/tiopf/demos/EditControlsDemo/editmediators.lpr | 27 | ||||
-rw-r--r-- | extras/tiopf/demos/EditControlsDemo/frmMain.pas | 291 | ||||
-rw-r--r-- | extras/tiopf/gui/tiGenericEditMediators.pas | 9 | ||||
-rw-r--r-- | extras/tiopf/tiOPFfpGUI.lpk | 9 |
8 files changed, 777 insertions, 9 deletions
diff --git a/extras/tiopf/demos/Common/Constants.pas b/extras/tiopf/demos/Common/Constants.pas new file mode 100644 index 00000000..6c93719d --- /dev/null +++ b/extras/tiopf/demos/Common/Constants.pas @@ -0,0 +1,14 @@ +unit Constants; + +{$mode objfpc}{$H+} + +interface + +const + cNameMissing = 'Please enter a name'; + cAgeOutofRange = 'Please enter a valid age'; + + +implementation + +end. diff --git a/extras/tiopf/demos/Common/Model.pas b/extras/tiopf/demos/Common/Model.pas new file mode 100644 index 00000000..148f94b9 --- /dev/null +++ b/extras/tiopf/demos/Common/Model.pas @@ -0,0 +1,203 @@ +unit Model; + +{$mode objfpc}{$H+} + +interface +uses + tiObject + ; + +type + TGender = (genMale, genFemale); + +const + cGender: array[TGender] of string = ('Male', 'Female'); + +type + TPerson = class; + TPersonList = class; + + { TPerson - The subject being observed } + TPerson = class(TtiObject) + private + FGender: TGender; + FName: string; + FAge: integer; + function GetGenderGUI: string; + procedure SetGender(const AValue: TGender); + procedure SetGenderGUI(const AValue: string); + procedure SetName(const Value: string); + procedure SetAge(const Value: integer); + protected + function GetCaption: string; override; + public + constructor Create; override; + function IsValid(const pErrors: TtiObjectErrors): Boolean; override; + procedure NotifyObservers; override; + property Gender: TGender read FGender write SetGender; + published + property Name: string read FName write SetName; + property Age: integer read FAge write SetAge; + property GenderGUI: string read GetGenderGUI write SetGenderGUI; + end; + + + { TPersonList } + TPersonList = class(TtiObjectList) + private + protected + function GetItems(i: integer): TPerson; reintroduce; + procedure SetItems(i: integer; const Value: TPerson); reintroduce; + public + property Items[i: integer]: TPerson read GetItems write SetItems; + procedure Add(const pObject: TPerson); reintroduce; + end; + + +function GeneratePersonList: TPersonList; + + +implementation +uses + Constants + ; + + +function GeneratePersonList: TPersonList; +var + lList: TPersonList; + lData: TPerson; +begin + lList := TPersonList.Create; + + lData := TPerson.Create; + lData.Name := 'Graeme Geldenhuys'; + lData.Age := 23; + lList.Add(lData); + + lData := TPerson.Create; + lData.Name := 'Peter Hinrichsen'; + lData.Age := 34; + lList.Add(lData); + + lData := TPerson.Create; + lData.Name := 'Ian Krigsman'; + lData.Age := 45; + lData.Deleted := True; + lList.Add(lData); + + lData := TPerson.Create; + lData.Name := 'John Guthrie'; + lData.Age := 56; + lList.Add(lData); + + Result := lList; +end; + + +{ TPerson } + +function TPerson.IsValid(const pErrors: TtiObjectErrors): Boolean; +begin + inherited IsValid(pErrors); + + if Name = '' then + pErrors.AddError('Name', cNameMissing); + + if Age < 1 then + pErrors.AddError('Age', cAgeOutofRange); + + Result := pErrors.Count = 0; +end; + +{ This was used for debugging, so you can see when NotifiObservers get called } +procedure TPerson.NotifyObservers; +begin +// writeln('NotifyObservers'); + inherited NotifyObservers; +end; + +procedure TPerson.SetAge(const Value: integer); +begin + { BeginUpdate and EndUpdate are optional. They allow the observers to only + get updated once, and not continuous for small updates. It doesn't really + make a difference for this simple example though. } + BeginUpdate; + FAge := Value; + EndUpdate; + { If you don't use BeginUpdate and EndUpdate, you need to call NotifyObserver + to they can be updated. } +// NotifyObservers; +end; + +function TPerson.GetCaption: string; +begin + Result := Name; + if Deleted then + Result := Result + ' (deleted)'; +end; + +constructor TPerson.Create; +begin + inherited Create; + FGender := genMale; +end; + +procedure TPerson.SetName(const Value: string); +begin + BeginUpdate; + FName := Value; + EndUpdate; +end; + +procedure TPerson.SetGender(const AValue: TGender); +begin + if FGender = AValue then exit; + BeginUpdate; + FGender := AValue; + EndUpdate; +end; + +function TPerson.GetGenderGUI: string; +begin + result := cGender[FGender]; +end; + +procedure TPerson.SetGenderGUI(const AValue: string); +var + i: TGender; +begin + for i := Low(TGender) to High(TGender) do + begin + if cGender[i] = AValue then + begin + Gender := i; + Exit; //==> + end; + end; + Gender := genMale; +end; + + +{ TPersonList } + +function TPersonList.GetItems(i: integer): TPerson; +begin + result := TPerson(inherited GetItems(i)); +end; + +procedure TPersonList.SetItems(i: integer; const Value: TPerson); +begin + inherited SetItems(i, Value); +end; + +procedure TPersonList.Add(const pObject: TPerson); +begin + BeginUpdate; + inherited Add(pObject); + EndUpdate; +end; + + +end. + diff --git a/extras/tiopf/demos/Common/Model_View.pas b/extras/tiopf/demos/Common/Model_View.pas new file mode 100644 index 00000000..937b51a3 --- /dev/null +++ b/extras/tiopf/demos/Common/Model_View.pas @@ -0,0 +1,151 @@ +unit Model_View; + +{$IFDEF FPC} + {$mode objfpc}{$H+} +{$ENDIF} + +interface + +uses + Classes + ,tiGenericEditMediators +// ,tiGenericListMediators +// ,tiCompositeMediators + ; + +type + { TEdit - Name } + TPerson_Name_TextEdit_View = class(TMediatorEditView) + protected + procedure SetupGUIandObject; override; + end; + + + { TSpinEdit - Age } +{ + TPerson_Age_SpinEdit_View = class(TMediatorSpinEditView) + protected + procedure SetupGUIandObject; override; + end; +} + + { TTrackBar - Age } + TPerson_Age_TrackBar_Mediator = class(TMediatorTrackBarView) + protected + procedure SetupGUIandObject; override; + end; + + + { TMemo - Name } + TPerson_Name_Memo_Mediator = class(TMediatorMemoView) + protected + procedure SetupGUIandObject; override; + end; + + + { TCombobox - Gender } + TPerson_Gender_ComboBox_Mediator = class(TMediatorComboBoxView) + protected + procedure SetupGUIandObject; override; + end; + + + { TPersonList_ComboBox_Mediator } +{ + TPersonList_ComboBox_Mediator = class(TComboBoxMediator) + protected + procedure SetupGUIandObject; override; + end; + + + TPersonList_ListView_CompositeMediator = class(TCompositeListViewMediator) + protected + procedure SetupGUIandObject; override; + end; +} + +implementation + + +{ TPersonNameView } + +procedure TPerson_Name_TextEdit_View.SetupGUIandObject; +begin + inherited; + { The Name field my only contain 25 characters max. } + EditControl.MaxLength := 25; +end; + + +{ TPerson_Name_Memo_Mediator } + +procedure TPerson_Name_Memo_Mediator.SetupGUIandObject; +begin + inherited SetupGUIandObject; + { The Name field my only contain 25 characters max. } +// EditControl.ReadOnly := True; + EditControl.Enabled := False; +end; + + +{ TPerson_Gender_ComboBox_Mediator } + +procedure TPerson_Gender_ComboBox_Mediator.SetupGUIandObject; +begin + inherited SetupGUIandObject; +// EditControl.Style := csDropDownList; +// TComboBox(EditControl).ReadOnly := True; +end; + + +{ TPersonList_ComboBox_Mediator } +(* +procedure TPersonList_ComboBox_Mediator.SetupGUIandObject; +begin + inherited SetupGUIandObject; + View.Style := csDropDownList; +// View.ReadOnly := True; +end; + + +{ TPersonList_ListView_CompositeMediator } + +procedure TPersonList_ListView_CompositeMediator.SetupGUIandObject; +begin + inherited SetupGUIandObject; +// View.OnCustomDrawItem := ListViewCustomDrawItem; +end; +*) + +{ TPerson_Age_SpinEdit_View } +{ +procedure TPerson_Age_SpinEdit_View.SetupGUIandObject; +begin + inherited SetupGUIandObject; + EditControl.MaxValue := 100; +end; +} +{ TPerson_Age_TrackBar_Mediator } + +procedure TPerson_Age_TrackBar_Mediator.SetupGUIandObject; +begin + inherited SetupGUIandObject; + EditControl.Max := 100; +end; + +initialization + {----------------------------------------------------------------------------- + Register all your Mediator Views here + Params: ClassName and Property name of the business object as a string + Mediator View class + -----------------------------------------------------------------------------} + + // This is not used anymore and needs to be removed +{ + gMediatorFactory.RegisterMediatorClass('TPerson.Name' ,TPerson_Name_TextEdit_View); + gMediatorFactory.RegisterMediatorClass('TPerson.Age' ,TPerson_Age_SpinEdit_View); + gMediatorFactory.RegisterMediatorClass('TPerson.Age' ,TPerson_Age_TrackBar_Mediator); + gMediatorFactory.RegisterMediatorClass('TPerson.Name' ,TPerson_Name_Memo_Mediator); + gMediatorFactory.RegisterMediatorClass('TPerson.GenderGUI',TPerson_Gender_ComboBox_Mediator); +} +end. diff --git a/extras/tiopf/demos/EditControlsDemo/editmediators.lpi b/extras/tiopf/demos/EditControlsDemo/editmediators.lpi new file mode 100644 index 00000000..d24d8e8b --- /dev/null +++ b/extras/tiopf/demos/EditControlsDemo/editmediators.lpi @@ -0,0 +1,82 @@ +<?xml version="1.0"?> +<CONFIG> + <ProjectOptions> + <PathDelim Value="/"/> + <Version Value="5"/> + <General> + <Flags> + <SaveOnlyProjectUnits Value="True"/> + </Flags> + <SessionStorage Value="InProjectDir"/> + <MainUnit Value="0"/> + <IconPath Value="./"/> + <TargetFileExt Value=""/> + <UseAppBundle Value="False"/> + </General> + <VersionInfo> + <ProjectVersion Value=""/> + </VersionInfo> + <PublishOptions> + <Version Value="2"/> + <IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/> + <ExcludeFileFilter Value="*.(bak|ppu|ppw|o|so);*~;backup"/> + </PublishOptions> + <RunParams> + <local> + <FormatVersion Value="1"/> + <LaunchingApplication PathPlusParams="/usr/X11R6/bin/xterm -T 'Lazarus Run Output' -e $(LazarusDir)/tools/runwait.sh $(TargetCmdLine)"/> + </local> + </RunParams> + <RequiredPackages Count="2"> + <Item1> + <PackageName Value="fpgui_package"/> + <MinVersion Minor="5" Valid="True"/> + </Item1> + <Item2> + <PackageName Value="tiOPFfpGUI"/> + <MinVersion Major="2" Release="3" Valid="True"/> + </Item2> + </RequiredPackages> + <Units Count="5"> + <Unit0> + <Filename Value="editmediators.lpr"/> + <IsPartOfProject Value="True"/> + <UnitName Value="editmediators"/> + </Unit0> + <Unit1> + <Filename Value="frmMain.pas"/> + <IsPartOfProject Value="True"/> + <UnitName Value="frmMain"/> + </Unit1> + <Unit2> + <Filename Value="../Common/Model_View.pas"/> + <IsPartOfProject Value="True"/> + <UnitName Value="Model_View"/> + </Unit2> + <Unit3> + <Filename Value="../Common/Constants.pas"/> + <IsPartOfProject Value="True"/> + <UnitName Value="Constants"/> + </Unit3> + <Unit4> + <Filename Value="../Common/Model.pas"/> + <IsPartOfProject Value="True"/> + <UnitName Value="Model"/> + </Unit4> + </Units> + </ProjectOptions> + <CompilerOptions> + <Version Value="5"/> + <SearchPaths> + <OtherUnitFiles Value="../Common/"/> + </SearchPaths> + <CodeGeneration> + <Generate Value="Faster"/> + </CodeGeneration> + <Other> + <CustomOptions Value="-FUunits +"/> + <CompilerPath Value="$(CompPath)"/> + </Other> + </CompilerOptions> +</CONFIG> diff --git a/extras/tiopf/demos/EditControlsDemo/editmediators.lpr b/extras/tiopf/demos/EditControlsDemo/editmediators.lpr new file mode 100644 index 00000000..7e462e83 --- /dev/null +++ b/extras/tiopf/demos/EditControlsDemo/editmediators.lpr @@ -0,0 +1,27 @@ +program editmediators; + +{$mode objfpc}{$H+} + +uses + {$IFDEF UNIX}{$IFDEF UseCThreads} + cthreads, + {$ENDIF}{$ENDIF} + Classes, fpgfx, frmMain; + + + +procedure MainProc; +var + frm: TMainForm; +begin + fpgApplication.Initialize; + frm := TMainForm.Create(nil); + frm.Show; + fpgApplication.Run; +end; + +begin + MainProc; +end. + + diff --git a/extras/tiopf/demos/EditControlsDemo/frmMain.pas b/extras/tiopf/demos/EditControlsDemo/frmMain.pas new file mode 100644 index 00000000..afa03d91 --- /dev/null +++ b/extras/tiopf/demos/EditControlsDemo/frmMain.pas @@ -0,0 +1,291 @@ +unit frmMain; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, gui_form, gui_button, gui_label, gui_edit, gui_trackbar, + gui_combobox, gui_memo, Model, tiGenericEditMediators; + +type + TMainForm = class(TfpgForm) + private + btnClose: TfpgButton; + btnViaCode: TfpgButton; + btnShowModel: TfpgButton; + Label1: TfpgLabel; + Label2: TfpgLabel; + edtName: TfpgEdit; +// edtAge: TSpinEdit; + AgeTrackBar: TfpgTrackBar; + memMemo: TfpgMemo; + cbGender: TfpgComboBox; + Label3: TfpgLabel; + + { The object we will be working with. } + FPerson: TPerson; + { Edit mediators } + FEditNameMediator: TMediatorEditView; +// FSpinEditAgeMediator: TMediatorSpinEditView; + FTrackBarAgeMediator: TMediatorTrackBarView; + FMemoNameMediator: TMediatorMemoView; + FComboBoxGenderMediator: TMediatorComboBoxView; + + procedure btnCloseClick(Sender: TObject); + procedure btnShowModelClick(Sender: TObject); + procedure btnViaCodeClick(Sender: TObject); + procedure edtNameChange(Sender: TObject); + procedure edtAgeChange(Sender: TObject); + procedure AgeTrackBarChange(Sender: TObject; APosition: integer); + procedure cbGenderChange(Sender: TObject); + procedure InitializeComponents; + procedure SetupMediators; + procedure SetupEventHandlers; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + procedure AfterConstruction; override; + end; + +implementation + +uses + gui_dialogs + ,Model_View + ; + +{ TMainForm } + +procedure TMainForm.btnCloseClick(Sender: TObject); +begin + Close; +end; + +procedure TMainForm.btnShowModelClick(Sender: TObject); +begin + ShowMessage(FPerson.AsDebugString); +end; + +{ The controls will automatically update as well! } +procedure TMainForm.btnViaCodeClick(Sender: TObject); +begin + FPerson.Name := 'John Doe'; + FPerson.Age := 23; + FPerson.Gender := genFemale; +end; + +procedure TMainForm.edtNameChange(Sender: TObject); +begin + FEditNameMediator.GUIChanged; +end; + +procedure TMainForm.edtAgeChange(Sender: TObject); +begin +// FSpinEditAgeMediator.GUIChanged; +end; + +procedure TMainForm.AgeTrackBarChange(Sender: TObject; APosition: integer); +begin + FTrackBarAgeMediator.GUIChanged; +end; + +procedure TMainForm.cbGenderChange(Sender: TObject); +begin + writeln('cbGenderChange'); + FComboBoxGenderMediator.GUIChanged; +end; + +procedure TMainForm.InitializeComponents; +begin + Label1 := TfpgLabel.Create(self); + with Label1 do + begin + Left := 8; + Height := 17; + Top := 16; + Width := 49; + Text := 'Name:'; + end; + + Label2 := TfpgLabel.Create(self); + with Label2 do + begin + Left := 8; + Height := 17; + Top := 48; + Width := 34; + Text := 'Age:'; + end; + + Label3 := TfpgLabel.Create(self); + with Label3 do + begin + Left := 264; + Height := 17; + Top := 16; + Width := 90; + Text := '(Read-Only)'; + end; + + btnClose := TfpgButton.Create(self); + with btnClose do + begin + Left := 416; + Height := 25; + Top := 160; + Width := 75; + Text := 'Close'; + OnClick := @btnCloseClick; + ImageName := 'stdimg.Close'; + ShowImage := True; + TabOrder := 0; + end; + + btnViaCode := TfpgButton.Create(self); + with btnViaCode do + begin + Left := 7; + Height := 25; + Top := 160; + Width := 150; + Text := 'Change via Code'; + OnClick := @btnViaCodeClick; + TabOrder := 1; + end; + + btnShowModel := TfpgButton.Create(self); + with btnShowModel do + begin + Left := 164; + Height := 25; + Top := 160; + Width := 100; + Text := 'Show Model'; + OnClick := @btnShowModelClick; + TabOrder := 2; + end; + + edtName := TfpgEdit.Create(self); + with edtName do + begin + Left := 64; + Height := 21; + Top := 16; + Width := 150; + TabOrder := 3; + end; + +{ + object edtAge: TSpinEdit + Left = 64 + Height = 22 + Top = 40 + Width = 100 + MaxValue = 0 + TabOrder = 4 + end +} + + AgeTrackBar := TfpgTrackBar.Create(self); + with AgeTrackBar do + begin + Left := 64; + Height := 41; + Top := 72; + Width := 150; +// ScrollStep := 10; +// Frequency := 10; + Max := 100; +// ScalePos := trTop; + ShowPosition := True; + TabOrder := 5; + end; + + memMemo := TfpgMemo.Create(self); + with memMemo do + begin + Left := 264; + Height := 57; + Top := 32; + Width := 185; + TabOrder := 6; + end; + + cbGender := TfpgComboBox.Create(self); + with cbGender do + begin + Left := 264; + Height := 21; + Top := 96; +// Width := 145; +// AutoCompleteText = [cbactEndOfLineComplete, cbactSearchAscending]; +// MaxLength := 0; + TabOrder := 7; + end; +end; + +procedure TMainForm.SetupMediators; +begin + FEditNameMediator := TPerson_Name_TextEdit_View.CreateCustom(edtName, FPerson, 'Name', 'Text'); +// FSpinEditAgeMediator := TPerson_Age_SpinEdit_View.CreateCustom(edtAge, FPerson, 'Age', 'Value'); + FTrackBarAgeMediator := TPerson_Age_TrackBar_Mediator.CreateCustom(AgeTrackBar, FPerson, 'Age', 'Position'); + FMemoNameMediator := TPerson_Name_Memo_Mediator.CreateCustom(memMemo, FPerson, 'Name', ''); + FComboBoxGenderMediator := TPerson_Gender_ComboBox_Mediator.CreateCustom(cbGender, FPerson, 'GenderGUI', 'Text'); +end; + +procedure TMainForm.SetupEventHandlers; +begin + { Setup generic OnChange event for all GUI controls. } + edtName.OnChange := @edtNameChange; +// edtAge.OnChange := @edtAgeChange; + AgeTrackBar.OnChange := @AgeTrackBarChange; + cbGender.OnChange := @cbGenderChange; +end; + +constructor TMainForm.Create(AOwner: TComponent); +var + i: TGender; +begin + inherited Create(AOwner); + WindowTitle := 'Edit Mediators Demo'; + SetPosition(100, 100, 500, 200); + + { The Data Object being observed } + FPerson := TPerson.Create; + FPerson.Name := 'Graeme Geldenhuys'; + FPerson.Age := 32; + + InitializeComponents; + + for i := Low(TGender) to High(TGender) do + cbGender.Items.Add(cGender[i]); +end; + +destructor TMainForm.Destroy; +begin + { free mediators - they will detach themselves } + FEditNameMediator.Free; +// FSpinEditAgeMediator.Free; + FTrackBarAgeMediator.Free; + FMemoNameMediator.Free; + FComboBoxGenderMediator.Free; + + FPerson.Free; + inherited Destroy; +end; + +procedure TMainForm.AfterConstruction; +begin + inherited AfterConstruction; + { The only trick here is to not let the OnChange events fire + before the mediators are not set up!! } + SetupMediators; + SetupEventHandlers; + // This will cause all components to update at once + FPerson.NotifyObservers; +end; + + +end. + diff --git a/extras/tiopf/gui/tiGenericEditMediators.pas b/extras/tiopf/gui/tiGenericEditMediators.pas index c485fa5d..299fed26 100644 --- a/extras/tiopf/gui/tiGenericEditMediators.pas +++ b/extras/tiopf/gui/tiGenericEditMediators.pas @@ -671,8 +671,9 @@ end; procedure TMediatorComboBoxView.ObjectToGui; begin + // NOTE: FocusItem is 1 based!! EditControl.FocusItem := - EditControl.Items.IndexOf(Subject.PropValue[FieldName]); + EditControl.Items.IndexOf(Subject.PropValue[FieldName]) +1; end; @@ -741,7 +742,7 @@ var begin lItems := EditControl.Items; lItems.Clear; -// EditControl.Text := ''; + EditControl.Text := ''; if (FList = nil) or (FList.Count < 1) or @@ -794,7 +795,7 @@ constructor TMediatorDynamicComboBoxView.CreateCustom(pList: TtiObjectList; pEditControl: TfpgWidget; pSubject: TtiObject; pFieldName: string); begin Create; - FGuiFieldName := 'Text'; // TComboBox defaults to Text property + FGuiFieldName := 'Text'; // TfpgComboBox defaults to Text property FSubject := pSubject; FFieldName := pFieldName; @@ -848,7 +849,7 @@ begin SetOnChangeActive(false); // Set the index only (We're assuming the item is present in the list) - EditControl.FocusItem := -1; + EditControl.FocusItem := 0; if FSubject = nil then Exit; //==> diff --git a/extras/tiopf/tiOPFfpGUI.lpk b/extras/tiopf/tiOPFfpGUI.lpk index 6b38e720..340f9e71 100644 --- a/extras/tiopf/tiOPFfpGUI.lpk +++ b/extras/tiopf/tiOPFfpGUI.lpk @@ -3,7 +3,6 @@ <Package Version="2"> <Name Value="tiOPFfpGUI"/> <Author Value="Graeme Geldenhuys"/> - <AutoUpdate Value="OnRebuildingAll"/> <CompilerOptions> <Version Value="5"/> <SearchPaths> @@ -46,16 +45,16 @@ </Files> <RequiredPkgs Count="3"> <Item1> - <PackageName Value="FCL"/> - <MinVersion Major="1" Valid="True"/> + <PackageName Value="fpgui_package"/> + <MinVersion Minor="5" Valid="True"/> </Item1> <Item2> <PackageName Value="tiOPF"/> <MinVersion Major="2" Release="3" Valid="True"/> </Item2> <Item3> - <PackageName Value="fpgui_package"/> - <MinVersion Minor="5" Valid="True"/> + <PackageName Value="FCL"/> + <MinVersion Major="1" Valid="True"/> </Item3> </RequiredPkgs> <UsageOptions> |