lazarus/components/sparta/generics/examples/THashMap/THashMapProject.lpr
hnb d53cfa9c28 Merged revision(s) 51414, 51448-51450, 51468, 51473, 51477, 51480, 51483, 51486, 51511, 51543-51544, 51638, 52714, 52725-52727 from branches/free-sparta:
sparta: initial commit of "compilable" new sparta package - smart form editor. !NOTE: not for daily usage.
........
sparta: Initial conception for package for MDI: sparta_MDI. Base for sparta_DockedFormEditor package.
........
sparta: Generics.Collections library ( sync with https://github.com/dathox/generics.collections SHA fda586932bd80ef58c08f8ebf5a24316ca4ccca5)
........
sparta: smart form editor adjustment for new sparta_MDI
........
sparta: new class "TFormImpl" for MDI solution (created from TDesignedFormImpl). 
........
sparta: 
-MDI form container "TFormContainer"
-New IResizeFrame interface to handle MDI form moving
-New frame TfrFormBackgroundForMDI
........
sparta: sparta_MDI package modifications:
-new class TMultiplyResizer to menage MDI desktop
-more generic resizer: TAbstractResizer. Base for IDE resizer and TMultiplyResizer
-more advanced IResizeFrame interface


........
sparta: 
-DockedFormEditor adjustment for latest changes in mdi package
-small changes in mdi (visibility of methods).
-OnModified method for IResizeFrame

........
sparta: MDI
-simulate MDI forms order for TMultiplyResizer
-property DesignedForm: IDesignedForm for IResizeFrame
........
sparta:
-IMPORTANT! pixel perfect form resizing (fix for problems for controls with align alLeft, alRight etc on design form).
-Fix problem for windows: wrong design design window width (a little bigger than designed size) TFormImpl.SetRealBounds -> AdjustSize
........
sparta: mdi bug fix for AV in TMultiplyResizer
........
Fix compilation for FPC 3.0 (TRect changes in FPC 3.1 trunk)
........
sparta: Cannot resize the docked form designer, issue #29380 patch from Anthony Walter. Thanks!
........
sparta ToolsAPI: Delphi compatible ToolsAPI/DesignIDE interface at XE2 level (proxy for IDEIntf). Initial commit (no functionality yet), just interfaces and classes without implementation:

designeditors.pas:
-TComponentEditor

designintf.pas:
-Interfaces: IEventInfo, IClass, IActivatable, IDesignObject, IDesignPersistent, IDesignerSelections, IDesigner60, IDesigner70, IDesigner80, IDesigner100, IDesigner, IComponentEditor
-TBaseComponentEditor
-RegisterComponentEditor

designmenus.pas:
-Interfaces: IMenuItems, IMenu, IMainMenu, IPopupMenu, IMenuItem

 
 


........
when form is removed we need to remove all handlers located in collections FFormsStack and FForms. Necessary to avoid AV.
........
sparta: more correct and simpler calculation of form border for Windows
........
sparta: 
  * Fix for loop error for resize. Highly visible problem for docked forms/frames with Align=alClient. 
  * New THookFrame class as new meta class for Frames.
........
updated lpl
........

git-svn-id: trunk@52728 -
2016-07-20 10:40:03 +00:00

219 lines
7.8 KiB
ObjectPascal
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Generic types for FreeSparta.com and FreePascal!
// Original version by keeper89.blogspot.com, 2011
// FPC version by Maciej Izak (hnb), 2014
program THashMapProject;
{$MODE DELPHI}
{$APPTYPE CONSOLE}
uses
SysUtils, Generics.Collections, Generics.Defaults;
type
TSubscriberInfo = record
Name, SName: string;
class function Create(const Name, SName: string): TSubscriberInfo; static;
function ToString: string;
end;
// Class containing handlers add / remove items in the dictionary
THashMapEventsHandler = class
public
class procedure OnKeyNotify(Sender: TObject; constref Item: string;
Action: TCollectionNotification);
class procedure OnValueNotify(Sender: TObject; constref Item: TSubscriberInfo;
Action: TCollectionNotification);
end;
class function TSubscriberInfo.Create(const Name,
SName: string): TSubscriberInfo;
begin
Result.Name := Name;
Result.SName := SName;
end;
function TSubscriberInfo.ToString: string;
begin
Result := Format('%s %s', [Name, SName]);
end;
// Function to generate the dictionary contents into a string
function PrintTelephoneDirectory(
TelephoneDirectory: THashMap<string, TSubscriberInfo>): string;
var
PhoneNumber: string;
begin
Result := Format('Content directory (%d):', [TelephoneDirectory.Count]);
for PhoneNumber in TelephoneDirectory.Keys do
Result := Result + Format(LineEnding + '%s: %s',
[PhoneNumber, TelephoneDirectory[PhoneNumber].ToString]);
end;
// Handlers add / remove items dictionary
class procedure THashMapEventsHandler.OnKeyNotify(Sender: TObject;
constref Item: string; Action: TCollectionNotification);
begin
case Action of
cnAdded:
Writeln(Format('OnKeyNotify! Phone %s added!', [Item]));
cnRemoved:
Writeln(Format('OnKeyNotify! Number %s deleted!', [Item]));
end;
end;
class procedure THashMapEventsHandler.OnValueNotify(Sender: TObject;
constref Item: TSubscriberInfo; Action: TCollectionNotification);
begin
case Action of
cnAdded:
Writeln(Format('OnValueNotify! Subscriber %s added!', [Item.ToString]));
cnRemoved:
Writeln(Format('OnValueNotify! Subscriber %s deleted!', [Item.ToString]));
end;
end;
function CustomCompare(constref Left, Right: TPair<string, TSubscriberInfo>): Integer;
begin
// Comparable full first names, and then phones if necessary
Result := TCompare.&String(Left.Value.ToString, Right.Value.ToString);
if Result = 0 then
Result := TCompare.&String(Left.Key, Right.Key);
end;
var
// Declare the "dictionary"
// key is the telephone number which will be possible
// to determine information about the owner
TelephoneDirectory: THashMap<string, TSubscriberInfo>;
TTelephoneArray: array of TPair<string, TSubscriberInfo>;
TTelephoneArrayItem: TPair<string, TSubscriberInfo>;
PhoneNumber: string;
Subscriber: TSubscriberInfo;
begin
WriteLn('Working with THashMap - phonebook');
WriteLn;
// create a directory
// Constructor has several overloaded options which will
// enable the capacity of the container, a comparator for values
// or the initial data - we use the easiest option
TelephoneDirectory := THashMap<string, TSubscriberInfo>.Create;
// ---------------------------------------------------
// 1) Adding items to dictionary
// Add new users to the phonebook
TelephoneDirectory.Add('9201111111', TSubscriberInfo.Create('Arnold', 'Schwarzenegger'));
TelephoneDirectory.Add('9202222222', TSubscriberInfo.Create('Jessica', 'Alba'));
TelephoneDirectory.Add('9203333333', TSubscriberInfo.Create('Brad', 'Pitt'));
TelephoneDirectory.Add('9204444444', TSubscriberInfo.Create('Brad', 'Pitt'));
TelephoneDirectory.Add('9205555555', TSubscriberInfo.Create('Sandra', 'Bullock'));
// Adding a new subscriber if number already exist
TelephoneDirectory.AddOrSetValue('9204444444',
TSubscriberInfo.Create('Angelina', 'Jolie'));
// Print list
Writeln(PrintTelephoneDirectory(TelephoneDirectory));
// ---------------------------------------------------
// 2) Working with the elements
// Set the "capacity" of the dictionary according to the current number of elements
TelephoneDirectory.TrimExcess;
// Is there a key? - ContainsKey
if TelephoneDirectory.ContainsKey('9205555555') then
Writeln('Phone 9205555555 registered!');
// Is there a subscriber? - ContainsValue
Subscriber := TSubscriberInfo.Create('Sandra', 'Bullock');
if TelephoneDirectory.ContainsValue(Subscriber) then
Writeln(Format('%s is in the directory!', [Subscriber.ToString]));
// Try to get information via telephone. TryGetValue
if TelephoneDirectory.TryGetValue('9204444444', Subscriber) then
Writeln(Format('Number 9204444444 belongs to %s', [Subscriber.ToString]));
// Directly access by phone number
Writeln(Format('Phone 9201111111 subscribers: %s', [TelephoneDirectory['9201111111'].ToString]));
// Number of people in the directory
Writeln(Format('Total subscribers in the directory: %d', [TelephoneDirectory.Count]));
// ---------------------------------------------------
// 3) Delete items
// Schwarzenegger now will not be listed
TelephoneDirectory.Remove('9201111111');
// Completely clear the list
TelephoneDirectory.Clear;
// ---------------------------------------------------
// 4) Events add / remove values
//
// Events OnKeyNotify OnValueNotify are designed for "tracking"
// for adding / removing keys and values respectively
TelephoneDirectory.OnKeyNotify := THashMapEventsHandler.OnKeyNotify;
TelephoneDirectory.OnValueNotify := THashMapEventsHandler.OnValueNotify;
Writeln;
// Try events
TelephoneDirectory.Add('9201111111', TSubscriberInfo.Create('Arnold', 'Schwarzenegger'));
TelephoneDirectory.Add('9202222222', TSubscriberInfo.Create('Jessica', 'Alba'));
TelephoneDirectory['9202222222'] := TSubscriberInfo.Create('Monica', 'Bellucci');
TelephoneDirectory.Clear;
WriteLn;
TelephoneDirectory.Add('9201111111', TSubscriberInfo.Create('Monica', 'Bellucci'));
TelephoneDirectory.Add('9202222222', TSubscriberInfo.Create('Sylvester', 'Stallone'));
TelephoneDirectory.Add('9203333333', TSubscriberInfo.Create('Bruce', 'Willis'));
WriteLn;
// Show keys (phones)
Writeln('Keys (phones):');
for PhoneNumber in TelephoneDirectory.Keys do
Writeln(PhoneNumber);
Writeln;
// Show values (subscribers)
Writeln('Values (subscribers):');
for Subscriber in TelephoneDirectory.Values do
Writeln(Subscriber.ToString);
Writeln;
// All together now
Writeln('Subscribers list with phones:');
for PhoneNumber in TelephoneDirectory.Keys do
Writeln(Format('%s: %s',
[PhoneNumber, TelephoneDirectory[PhoneNumber].ToString]));
Writeln;
// In addition, we can "export" from the dictionary
// to TArray
// Sort the resulting array and display
TTelephoneArray := TelephoneDirectory.ToArray;
// partial specializations not allowed
// same for anonymous methods
//TArray.Sort<TPair<string, TSubscriberInfo>>(
// TTelephoneArray, TComparer<TPair<string, TSubscriberInfo>>.Construct(
// function (const Left, Right: TPair<string, TSubscriberInfo>): Integer
// begin
// // Comparable full first names, and then phones if necessary
// Result := CompareStr(Left.Value.ToString, Right.Value.ToString);
// if Result = 0 then
// Result := CompareStr(Left.Key, Right.Key);
// end));
TArrayHelper<TelephoneDirectory.TDictionaryPair>.Sort(
TTelephoneArray, TComparer<TelephoneDirectory.TDictionaryPair>.Construct(
CustomCompare));
// Print
Writeln('Sorted list of subscribers into TArray (by name, and eventually by phone):');
for TTelephoneArrayItem in TTelephoneArray do
Writeln(Format('%s: %s',
[TTelephoneArrayItem.Value.ToString, TTelephoneArrayItem.Key]));
Writeln;
FreeAndNil(TelephoneDirectory);
Readln;
end.