diff --git a/components/jvcllaz/design/JvCtrls/images/images.txt b/components/jvcllaz/design/JvCtrls/images/images.txt
index 0e69eec03..65c80bbcd 100644
--- a/components/jvcllaz/design/JvCtrls/images/images.txt
+++ b/components/jvcllaz/design/JvCtrls/images/images.txt
@@ -25,6 +25,7 @@ tjvgroupheader_200.png
tjvrollout.png
tjvrollout_150.png
tjvrollout_200.png
+tjvbehaviorlabel.bmp
tjvcombolistbox.bmp
tjvlookupautocomplete.bmp
tjvinstalllabel.bmp
diff --git a/components/jvcllaz/design/JvCtrls/images/tjvbehaviorlabel.bmp b/components/jvcllaz/design/JvCtrls/images/tjvbehaviorlabel.bmp
new file mode 100644
index 000000000..a778da179
Binary files /dev/null and b/components/jvcllaz/design/JvCtrls/images/tjvbehaviorlabel.bmp differ
diff --git a/components/jvcllaz/design/JvCtrls/images/tjvmovablebevel_150.png b/components/jvcllaz/design/JvCtrls/images/tjvmovablebevel_150.png
new file mode 100644
index 000000000..98dfd5d99
Binary files /dev/null and b/components/jvcllaz/design/JvCtrls/images/tjvmovablebevel_150.png differ
diff --git a/components/jvcllaz/design/JvCtrls/images/tjvmovablebevel_200.png b/components/jvcllaz/design/JvCtrls/images/tjvmovablebevel_200.png
new file mode 100644
index 000000000..827b01e3e
Binary files /dev/null and b/components/jvcllaz/design/JvCtrls/images/tjvmovablebevel_200.png differ
diff --git a/components/jvcllaz/design/JvCtrls/jvbehaviorlabeleditor.pas b/components/jvcllaz/design/JvCtrls/jvbehaviorlabeleditor.pas
new file mode 100644
index 000000000..e1c48aa51
--- /dev/null
+++ b/components/jvcllaz/design/JvCtrls/jvbehaviorlabeleditor.pas
@@ -0,0 +1,97 @@
+{-----------------------------------------------------------------------------
+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/MPL-1.1.html
+
+Software distributed under the License is distributed on an "AS IS" basis,
+WITHOUT WARRANTY OF ANY KIND, either expressed or implied. See the License for
+the specific language governing rights and limitations under the License.
+
+The Original Code is: JvBandsReg.PAS, released on 2002-05-26.
+
+The Initial Developer of the Original Code is John Doe.
+Portions created by John Doe are Copyright (C) 2003 John Doe.
+All Rights Reserved.
+
+Contributor(s):
+
+You may retrieve the latest version of this file at the Project JEDI's JVCL home page,
+located at http://jvcl.delphi-jedi.org
+
+Known Issues:
+-----------------------------------------------------------------------------}
+// $Id$
+
+unit JvBehaviorLabelEditor;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+ Classes, SysUtils,
+ PropEdits;
+// DesignEditors, DesignIntf;
+
+type
+ TJvLabelBehaviorProperty = class(TStringProperty)
+ public
+ function AutoFill: Boolean; override;
+ procedure SetValue(const Value: string); override;
+ procedure GetValues(Proc: TGetStrProc); override;
+ function GetAttributes: TPropertyAttributes; override;
+ end;
+
+implementation
+
+uses
+ JvBehaviorLabel; //, JvDsgnTypes;
+
+function TJvLabelBehaviorProperty.AutoFill: Boolean;
+begin
+ Result := inherited AutoFill;
+ // if you want to fix the flickering when double-clicking a value, uncomment line below:
+ // Result := False;
+end;
+
+function TJvLabelBehaviorProperty.GetAttributes: TPropertyAttributes;
+begin
+ Result := [paValueList, paRevertable, paMultiSelect];
+end;
+
+procedure TJvLabelBehaviorProperty.GetValues(Proc: TGetStrProc);
+var
+ S: TStringList;
+ I: Integer;
+begin
+ S := TStringList.Create;
+ try
+ GetRegisteredLabelBehaviorOptions(S);
+ S.Sort;
+ for I := 0 to S.Count -1 do
+ Proc(S[I]);
+ finally
+ S.Free;
+ end;
+end;
+
+procedure TJvLabelBehaviorProperty.SetValue(const Value: string);
+{
+var wp -- to do
+ List: IDesignerSelections;
+ LDesigner: IJvFormDesigner;
+ }
+begin
+ inherited SetValue(Value);
+ {
+ List := CreateSelectionList;
+ Designer.GetSelections(List);
+ LDesigner := Designer; // keep Designer alive
+ LDesigner.SetSelections(nil);
+ LDesigner.SetSelections(List);
+ //Designer.Modified;
+ }
+end;
+
+end.
diff --git a/components/jvcllaz/design/JvCtrls/jvctrlsreg.pas b/components/jvcllaz/design/JvCtrls/jvctrlsreg.pas
index 13688eec5..556d7d2c1 100644
--- a/components/jvcllaz/design/JvCtrls/jvctrlsreg.pas
+++ b/components/jvcllaz/design/JvCtrls/jvctrlsreg.pas
@@ -15,6 +15,7 @@ implementation
uses
Classes, Controls, ActnList, PropEdits, JvDsgnConsts,
+ JvBehaviorLabel, JvBehaviorLabelEditor,
JvMovableBevel, JvRuler, JvGroupHeader, JvRollOut,
JvHtControls, JvHint, JvHTHintForm, JvComboListBox, JvInstallLabel,
JvOfficeColorPanel,
@@ -23,11 +24,13 @@ uses
procedure Register;
begin
RegisterComponents(RsPaletteJvclVisual, [
+ TJvBehaviorLabel,
TJvMovableBevel, TJvMovablePanel, TJvRuler, TJvGroupHeader, TJvRollOut,
TJvHint, TJvHTLabel, TJvHTListbox, TJvHTCombobox, TJvComboListBox,
TJvOfficeColorPanel,
TJvLookupAutoComplete, TJvInstallLabel
]);
+ RegisterPropertyEditor(TypeInfo(TJvLabelBehaviorName), TJvBehaviorLabel, 'Behavior', TJvLabelBehaviorProperty);
RegisterPropertyEditor(TypeInfo(TCaption), TJvHTLabel, 'Caption', TJvHintProperty);
RegisterActions(RsJVCLActionsCategory, [TJvRollOutAction], nil);
end;
diff --git a/components/jvcllaz/examples/JvBehaviorLabel/JvBehaviorLabelDemo.lpi b/components/jvcllaz/examples/JvBehaviorLabel/JvBehaviorLabelDemo.lpi
new file mode 100644
index 000000000..f042cd9fd
--- /dev/null
+++ b/components/jvcllaz/examples/JvBehaviorLabel/JvBehaviorLabelDemo.lpi
@@ -0,0 +1,81 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/jvcllaz/examples/JvBehaviorLabel/JvBehaviorLabelDemo.lpr b/components/jvcllaz/examples/JvBehaviorLabel/JvBehaviorLabelDemo.lpr
new file mode 100644
index 000000000..7886eacb8
--- /dev/null
+++ b/components/jvcllaz/examples/JvBehaviorLabel/JvBehaviorLabelDemo.lpr
@@ -0,0 +1,14 @@
+program JvBehaviorLabelDemo;
+
+uses
+ Interfaces, Forms,
+ JvBehaviorLblMainFrmU in 'JvBehaviorLblMainFrmU.pas' {JvBehaviorLblMainFrm};
+
+{$R *.res}
+
+begin
+ Application.Scaled:=True;
+ Application.Initialize;
+ Application.CreateForm(TJvBehaviorLblMainFrm, JvBehaviorLblMainFrm);
+ Application.Run;
+end.
diff --git a/components/jvcllaz/examples/JvBehaviorLabel/JvBehaviorLblMainFrmU.lfm b/components/jvcllaz/examples/JvBehaviorLabel/JvBehaviorLblMainFrmU.lfm
new file mode 100644
index 000000000..9e9eb66f6
--- /dev/null
+++ b/components/jvcllaz/examples/JvBehaviorLabel/JvBehaviorLblMainFrmU.lfm
@@ -0,0 +1,281 @@
+object JvBehaviorLblMainFrm: TJvBehaviorLblMainFrm
+ Left = 327
+ Height = 304
+ Top = 118
+ Width = 572
+ AutoSize = True
+ BorderStyle = bsDialog
+ Caption = 'JvBehaviorLabel Demo'
+ ClientHeight = 304
+ ClientWidth = 572
+ Color = clBtnFace
+ Font.Color = clWindowText
+ LCLVersion = '2.1.0.0'
+ object lblCodeBreaker: TJvBehaviorLabel
+ AnchorSideLeft.Control = Owner
+ AnchorSideTop.Control = Owner
+ Left = 24
+ Height = 22
+ Top = 18
+ Width = 259
+ Behavior = 'CodeBreaker'
+ BehaviorOptions.DecodedText = 'ENTER THE MATRIX!'
+ BehaviorOptions.Interval = 5
+ Alignment = taCenter
+ AutoSize = False
+ BorderSpacing.Left = 24
+ BorderSpacing.Top = 18
+ Caption = 'x6/yhjSkhHHDski"=90sd'
+ Color = clBlack
+ Font.CharSet = ANSI_CHARSET
+ Font.Color = clLime
+ Font.Height = -19
+ Font.Name = 'Courier New'
+ Font.Style = [fsBold]
+ ParentColor = False
+ ParentFont = False
+ ShowAccelChar = False
+ Transparent = False
+ end
+ object lblAppearing: TJvBehaviorLabel
+ AnchorSideLeft.Control = lblCodeBreaker
+ AnchorSideLeft.Side = asrBottom
+ AnchorSideTop.Control = lblCodeBreaker
+ Left = 301
+ Height = 22
+ Top = 18
+ Width = 259
+ Behavior = 'Appearing'
+ BehaviorOptions.Delay = 10
+ BehaviorOptions.Pixels = 2
+ Alignment = taCenter
+ AutoSize = False
+ BorderSpacing.Left = 18
+ BorderSpacing.Right = 24
+ Caption = 'MAKE ME APPEAR'
+ Color = clBlack
+ Font.CharSet = ANSI_CHARSET
+ Font.Color = clLime
+ Font.Height = -19
+ Font.Name = 'Courier New'
+ Font.Style = [fsBold]
+ ParentColor = False
+ ParentFont = False
+ Transparent = False
+ end
+ object lblBlinking: TJvBehaviorLabel
+ AnchorSideLeft.Control = lblCodeBreaker
+ AnchorSideTop.Control = btnCodeBreak
+ AnchorSideTop.Side = asrBottom
+ Left = 24
+ Height = 22
+ Top = 91
+ Width = 259
+ Behavior = 'Blinking'
+ BehaviorOptions.Interval = 220
+ Alignment = taCenter
+ AutoSize = False
+ BorderSpacing.Top = 18
+ Caption = 'BLINK ME'
+ Color = clBlack
+ Font.CharSet = ANSI_CHARSET
+ Font.Color = clLime
+ Font.Height = -19
+ Font.Name = 'Courier New'
+ Font.Style = [fsBold]
+ ParentColor = False
+ ParentFont = False
+ Transparent = False
+ end
+ object lblBouncing: TJvBehaviorLabel
+ AnchorSideLeft.Control = lblAppearing
+ AnchorSideTop.Control = lblBlinking
+ Left = 301
+ Height = 22
+ Top = 91
+ Width = 259
+ Behavior = 'Bouncing'
+ BehaviorOptions.Interval = 12
+ BehaviorOptions.Pixels = 4
+ Alignment = taCenter
+ AutoSize = False
+ Caption = 'BOUNCE ME'
+ Color = clBlack
+ Font.CharSet = ANSI_CHARSET
+ Font.Color = clLime
+ Font.Height = -19
+ Font.Name = 'Courier New'
+ Font.Style = [fsBold]
+ ParentColor = False
+ ParentFont = False
+ Transparent = False
+ end
+ object lblScrolling: TJvBehaviorLabel
+ AnchorSideLeft.Control = lblCodeBreaker
+ AnchorSideTop.Control = btnBlink
+ AnchorSideTop.Side = asrBottom
+ Left = 24
+ Height = 22
+ Top = 164
+ Width = 259
+ Behavior = 'Scrolling'
+ BehaviorOptions.Interval = 70
+ Alignment = taCenter
+ AutoSize = False
+ BorderSpacing.Top = 18
+ Caption = 'SCROLL ME'
+ Color = clBlack
+ Font.CharSet = ANSI_CHARSET
+ Font.Color = clLime
+ Font.Height = -19
+ Font.Name = 'Courier New'
+ Font.Style = [fsBold]
+ ParentColor = False
+ ParentFont = False
+ Transparent = False
+ end
+ object lblSpecial: TJvBehaviorLabel
+ AnchorSideLeft.Control = lblAppearing
+ AnchorSideTop.Control = lblScrolling
+ Left = 301
+ Height = 22
+ Top = 164
+ Width = 259
+ Behavior = 'Special'
+ BehaviorOptions.Interval = 35
+ Alignment = taCenter
+ AutoSize = False
+ Caption = 'I ACT IN A SPECIAL WAY'
+ Color = clBlack
+ Font.CharSet = ANSI_CHARSET
+ Font.Color = clLime
+ Font.Height = -19
+ Font.Name = 'Courier New'
+ Font.Style = [fsBold]
+ ParentColor = False
+ ParentFont = False
+ Transparent = False
+ end
+ object lblTyping: TJvBehaviorLabel
+ AnchorSideLeft.Control = lblCodeBreaker
+ AnchorSideTop.Control = btnScroll
+ AnchorSideTop.Side = asrBottom
+ Left = 24
+ Height = 22
+ Top = 237
+ Width = 259
+ Behavior = 'Typing'
+ Alignment = taCenter
+ AutoSize = False
+ BorderSpacing.Top = 18
+ Caption = 'TYPE THE TEXT'
+ Color = clBlack
+ Font.CharSet = ANSI_CHARSET
+ Font.Color = clLime
+ Font.Height = -19
+ Font.Name = 'Courier New'
+ Font.Style = [fsBold]
+ ParentColor = False
+ ParentFont = False
+ Transparent = False
+ end
+ object btnCodeBreak: TButton
+ AnchorSideLeft.Control = lblCodeBreaker
+ AnchorSideTop.Control = lblCodeBreaker
+ AnchorSideTop.Side = asrBottom
+ Left = 38
+ Height = 25
+ Top = 48
+ Width = 80
+ BorderSpacing.Left = 14
+ BorderSpacing.Top = 8
+ Caption = '&CodeBreaker'
+ OnClick = btnCodeBreakClick
+ TabOrder = 0
+ end
+ object btnAppear: TButton
+ AnchorSideLeft.Control = lblAppearing
+ AnchorSideTop.Control = btnCodeBreak
+ Left = 315
+ Height = 25
+ Top = 48
+ Width = 80
+ BorderSpacing.Left = 14
+ Caption = '&Appearing'
+ OnClick = btnAppearClick
+ TabOrder = 1
+ end
+ object btnBlink: TButton
+ AnchorSideLeft.Control = btnCodeBreak
+ AnchorSideTop.Control = lblBlinking
+ AnchorSideTop.Side = asrBottom
+ Left = 38
+ Height = 25
+ Top = 121
+ Width = 80
+ BorderSpacing.Top = 8
+ Caption = '&Blinking'
+ OnClick = btnBlinkClick
+ TabOrder = 2
+ end
+ object btnBounce: TButton
+ AnchorSideLeft.Control = btnAppear
+ AnchorSideTop.Control = btnBlink
+ Left = 315
+ Height = 25
+ Top = 121
+ Width = 80
+ Caption = 'B&ouncing'
+ OnClick = btnBounceClick
+ TabOrder = 3
+ end
+ object btnScroll: TButton
+ AnchorSideLeft.Control = btnCodeBreak
+ AnchorSideTop.Control = lblScrolling
+ AnchorSideTop.Side = asrBottom
+ Left = 38
+ Height = 25
+ Top = 194
+ Width = 80
+ BorderSpacing.Top = 8
+ Caption = '&Scrolling'
+ OnClick = btnScrollClick
+ TabOrder = 4
+ end
+ object btnSpecial: TButton
+ AnchorSideLeft.Control = btnAppear
+ AnchorSideTop.Control = btnScroll
+ Left = 315
+ Height = 25
+ Top = 194
+ Width = 80
+ Caption = 'S&pecial'
+ OnClick = btnSpecialClick
+ TabOrder = 5
+ end
+ object btnType: TButton
+ AnchorSideLeft.Control = btnCodeBreak
+ AnchorSideTop.Control = lblTyping
+ AnchorSideTop.Side = asrBottom
+ Left = 38
+ Height = 25
+ Top = 267
+ Width = 80
+ BorderSpacing.Top = 8
+ BorderSpacing.Bottom = 18
+ Caption = '&Typing'
+ OnClick = btnTypeClick
+ TabOrder = 6
+ end
+ object btnAll: TButton
+ AnchorSideLeft.Control = btnAppear
+ AnchorSideTop.Control = btnType
+ Left = 315
+ Height = 25
+ Top = 267
+ Width = 80
+ Caption = 'Do ''em all!'
+ OnClick = btnAllClick
+ TabOrder = 7
+ end
+end
diff --git a/components/jvcllaz/examples/JvBehaviorLabel/JvBehaviorLblMainFrmU.pas b/components/jvcllaz/examples/JvBehaviorLabel/JvBehaviorLblMainFrmU.pas
new file mode 100644
index 000000000..98bf12330
--- /dev/null
+++ b/components/jvcllaz/examples/JvBehaviorLabel/JvBehaviorLblMainFrmU.pas
@@ -0,0 +1,135 @@
+{******************************************************************
+
+ JEDI-VCL Demo
+
+ Copyright (C) 2002 Project JEDI
+
+ Original author:
+
+ You may retrieve the latest version of this file at the JEDI-JVCL
+ home page, located at http://jvcl.delphi-jedi.org
+
+ The contents of this file are used with permission, 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/MPL-1_1Final.html
+
+ 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.
+
+******************************************************************}
+
+unit JvBehaviorLblMainFrmU;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+ SysUtils, Classes, Graphics, Controls, Forms,
+ Dialogs, StdCtrls, JvBehaviorLabel;
+
+type
+ TJvBehaviorLblMainFrm = class(TForm)
+ lblCodeBreaker: TJvBehaviorLabel;
+ btnCodeBreak: TButton;
+ lblAppearing: TJvBehaviorLabel;
+ btnAppear: TButton;
+ lblBlinking: TJvBehaviorLabel;
+ btnBlink: TButton;
+ lblBouncing: TJvBehaviorLabel;
+ btnBounce: TButton;
+ lblScrolling: TJvBehaviorLabel;
+ btnScroll: TButton;
+ lblSpecial: TJvBehaviorLabel;
+ btnSpecial: TButton;
+ lblTyping: TJvBehaviorLabel;
+ btnType: TButton;
+ btnAll: TButton;
+ procedure btnCodeBreakClick(Sender: TObject);
+ procedure btnAppearClick(Sender: TObject);
+ procedure btnBlinkClick(Sender: TObject);
+ procedure btnBounceClick(Sender: TObject);
+ procedure btnScrollClick(Sender: TObject);
+ procedure btnSpecialClick(Sender: TObject);
+ procedure btnTypeClick(Sender: TObject);
+ procedure btnAllClick(Sender: TObject);
+ private
+ procedure DoCodeBreakStart(Sender:TObject);
+ procedure DoCodeBreakStop(Sender:TObject);
+ public
+ end;
+
+var
+ JvBehaviorLblMainFrm: TJvBehaviorLblMainFrm;
+
+implementation
+
+{$R *.lfm}
+
+procedure TJvBehaviorLblMainFrm.btnCodeBreakClick(Sender: TObject);
+begin
+ Randomize;
+ lblCodeBreaker.OnStart := nil;
+ lblCodeBreaker.OnStop := nil;
+ if lblCodeBreaker.Caption = TJvLabelCodeBreaker(lblCodeBreaker.BehaviorOptions).DecodedText then
+ lblCodeBreaker.Caption := 'x6/yhjSkhHHDski"=90sd';
+ // this might trigger the OnStart/OnStop events, so set to nil
+ lblCodeBreaker.BehaviorOptions.Active := not lblCodeBreaker.BehaviorOptions.Active;
+ lblCodeBreaker.OnStart := @DoCodeBreakStart;
+ lblCodeBreaker.OnStop := @DoCodeBreakStop;
+end;
+
+procedure TJvBehaviorLblMainFrm.DoCodeBreakStart(Sender: TObject);
+begin
+ lblCodeBreaker.Caption := 'BREAK THE CODE';
+end;
+
+procedure TJvBehaviorLblMainFrm.DoCodeBreakStop(Sender: TObject);
+begin
+ ShowMessage('Congratulations! You''ve hacked the system!');
+end;
+
+procedure TJvBehaviorLblMainFrm.btnAppearClick(Sender: TObject);
+begin
+ lblAppearing.Alignment := taCenter;
+ lblAppearing.BehaviorOptions.Active := not lblAppearing.BehaviorOptions.Active;
+end;
+
+procedure TJvBehaviorLblMainFrm.btnBlinkClick(Sender: TObject);
+begin
+ lblBlinking.BehaviorOptions.Active := not lblBlinking.BehaviorOptions.Active;
+end;
+
+procedure TJvBehaviorLblMainFrm.btnBounceClick(Sender: TObject);
+begin
+ lblBouncing.BehaviorOptions.Active := not lblBouncing.BehaviorOptions.Active;
+end;
+
+procedure TJvBehaviorLblMainFrm.btnScrollClick(Sender: TObject);
+begin
+ lblScrolling.BehaviorOptions.Active := not lblScrolling.BehaviorOptions.Active;
+end;
+
+procedure TJvBehaviorLblMainFrm.btnSpecialClick(Sender: TObject);
+begin
+ lblSpecial.BehaviorOptions.Active := not lblSpecial.BehaviorOptions.Active;
+end;
+
+procedure TJvBehaviorLblMainFrm.btnTypeClick(Sender: TObject);
+begin
+ lblTyping.BehaviorOptions.Active := not lblTyping.BehaviorOptions.Active;
+end;
+
+procedure TJvBehaviorLblMainFrm.btnAllClick(Sender: TObject);
+var i:integer;
+begin
+ for i := 0 to ControlCount -1 do
+ if (Controls[i] <> btnAll) and (Controls[i] is TButton) then
+ TButton(Controls[i]).Click;
+end;
+
+end.
diff --git a/components/jvcllaz/packages/jvctrlslazr.lpk b/components/jvcllaz/packages/jvctrlslazr.lpk
index 9f777d0e9..ae30cc611 100644
--- a/components/jvcllaz/packages/jvctrlslazr.lpk
+++ b/components/jvcllaz/packages/jvctrlslazr.lpk
@@ -17,7 +17,7 @@ Movable bevel and panel, ruler, exandable panel (RollOut), group header, hyperte
"/>
-
+
@@ -58,6 +58,10 @@ Movable bevel and panel, ruler, exandable panel (RollOut), group header, hyperte
+
+
+
+
diff --git a/components/jvcllaz/resource/jvctrlsreg.res b/components/jvcllaz/resource/jvctrlsreg.res
index 3da02600b..ed0e9ca0a 100644
Binary files a/components/jvcllaz/resource/jvctrlsreg.res and b/components/jvcllaz/resource/jvctrlsreg.res differ
diff --git a/components/jvcllaz/run/JvCtrls/jvbehaviorlabel.pas b/components/jvcllaz/run/JvCtrls/jvbehaviorlabel.pas
new file mode 100644
index 000000000..d97681e7e
--- /dev/null
+++ b/components/jvcllaz/run/JvCtrls/jvbehaviorlabel.pas
@@ -0,0 +1,1294 @@
+{-----------------------------------------------------------------------------
+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/MPL-1.1.html
+
+Software distributed under the License is distributed on an "AS IS" basis,
+WITHOUT WARRANTY OF ANY KIND, either expressed or implied. See the License for
+the specific language governing rights and limitations under the License.
+
+The Original Code is: JvBehaviorLabel.PAS, released on 2003-03-24.
+
+The Initial Developer of the Original Code is Peter Thörnqvist [peter3 at sourceforge dot net]
+Portions created by Peter Thörnqvist are Copyright (C) 2003 Peter Thörnqvist.
+All Rights Reserved.
+
+Contributor(s):
+Sébastien Buysse [sbuysse att buypin dott com] - original author of the merged components
+Michael Beck [mbeck att bigfoot dott com].
+
+You may retrieve the latest version of this file at the Project JEDI's JVCL home page,
+located at http://jvcl.delphi-jedi.org
+
+Description:
+* TJvBehaviorLabel is a merging of several label components in JVCL: JvSpecialLabel,
+ JvRealLabel, JvBouncingLabel, JvBlinkingLabel and JvAppearingLabel
+* To change the way the label works, change the Behavior property: this in turn changes the
+ BehaviorOptions property to show only options available for the current Behavior.
+* New behaviors can be added by creating a sub-class of TJvLabelBehavior, implement the
+ functionality and register it with RegisterLabelBehaviorOptions.
+
+Known Issues:
+* Changing Behavior at design-time does not update the BehaviorOptions property unless
+ you collapse / expand the Options property in the OI manually. No known solution yet. SOLVED
+
+-----------------------------------------------------------------------------}
+// $Id$
+
+unit JvBehaviorLabel;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+ LCLIntf, Classes, //Windows, Messages,
+ Controls, StdCtrls, ExtCtrls; //, JvExStdCtrls;
+
+type
+ TJvCustomBehaviorLabel = class;
+
+ TJvLabelBehaviorName = string;
+ TJvLabelScrollDirection = (sdLeftToRight, sdRightToLeft);
+ TJvAppearDirection = (drFromLeft, drFromRight, drFromTop, drFromBottom);
+
+ // TJvLabelBehavior is the base class for label behaviors
+ // To create a new behavior, derive a new class from this base class,
+ // add appropriate published properties, override the Start, Stop and possibly the OwnerResize methods.
+ // Register the new behavior by calling RegisterLabelBehaviorOptions
+ TJvLabelBehavior = class(TPersistent)
+ private
+ FLabel: TJvCustomBehaviorLabel;
+ FTmpActive: Boolean;
+ FActive: Boolean;
+ FTemporary: Boolean;
+ procedure SetActive(const Value: Boolean);
+ protected
+ // Call Suspend to store the current state of the Active property and
+ // set Active to False. If the behavior was already inactive, Suspend does nothing
+ procedure Suspend;
+ // Call Resume to set the Active property to the state it was in before calling Suspend.
+ // Resume sets Active to True if it was True when Suspend was called.
+ // If Active was False before calling Suspend, Resume does nothing
+ procedure Resume;
+ // OwnerResize is called when the OwnerLabel is resized. Override this
+ // method to do special processing when the OwnerLabel changes it's size or position.
+ // OwnerResize does nothing in this class
+ procedure OwnerResize; virtual;
+ // Start is automatically called when Active is set to True
+ // Override this method to take special action when the behavior is "started".
+ // Start does nothing in this class
+ procedure Start; virtual;
+ // Stop is automatically called when Active is set to True
+ // Override this method to take special action when the behavior is "stopped".
+ // Stop does nothing in this class
+ procedure Stop; virtual;
+ // The label that the behavior is acting upon
+ property OwnerLabel: TJvCustomBehaviorLabel read FLabel;
+ public
+ constructor Create(ALabel: TJvCustomBehaviorLabel); virtual;
+ destructor Destroy; override;
+ published
+ // Set Active to True to enable the behavior and set it to False to disable it.
+ // Active calls Start and Stop as appropriate
+ property Active: Boolean read FActive write SetActive default False;
+ end;
+
+ // TJvLabelNone implements no special behavior
+ TJvLabelNone = class(TJvLabelBehavior)
+ published
+ property Active;
+ end;
+
+ // TJvLabelBlink implements a blinking behavior
+ TJvLabelBlink = class(TJvLabelBehavior)
+ private
+ FDelay: Cardinal;
+ FInterval: Cardinal;
+ FTimer: TTimer;
+ FToggled: Boolean;
+ procedure SetDelay(const Value: Cardinal);
+ procedure SetInterval(const Value: Cardinal);
+ procedure DoTimerEvent(Sender: TObject);
+ protected
+ procedure Start; override;
+ procedure Stop; override;
+ public
+ constructor Create(ALabel: TJvCustomBehaviorLabel); override;
+ published
+ property Active;
+ // Delay specifies the initial delay before the blinking starts. Delay is specified in milliseconds.
+ property Delay: Cardinal read FDelay write SetDelay default 100;
+ // Interval specifies the number f milliseconds that elapses between "blinks"
+ property Interval: Cardinal read FInterval write SetInterval default 400;
+ end;
+
+ // TJvLabelBounce implements a bouncing label
+ // NOTE that to use this behavior, the labels Align property should be set to alNone
+ TJvLabelBounce = class(TJvLabelBehavior)
+ private
+ FOriginalRect: TRect;
+ FInterval: Cardinal;
+ FParent: TWinControl;
+ FDirection: Integer;
+ FTimer: TTimer;
+ FPixels: Integer;
+ procedure SetInterval(const Value: Cardinal);
+ procedure SetPixels(const Value: Integer);
+ procedure DoTimerEvent(Sender: TObject);
+ protected
+ procedure Start; override;
+ procedure Stop; override;
+ public
+ constructor Create(ALabel: TJvCustomBehaviorLabel); override;
+ published
+ property Active;
+ // Interval specifies the number of milliseconds that elapses between "bounces"
+ // Lower values will make the label move faster
+ property Interval: Cardinal read FInterval write SetInterval default 20;
+ // Pixels specifes the number of pixels the label is moved at each bounce.
+ // Lower values will make the label move slower and smoother. Compensate by decreasing the value of Interval
+ property Pixels: Integer read FPixels write SetPixels default 6;
+ end;
+
+ // TJvLabelScroll implements a scrolling behavior, a behavior where the text is scrolled horizontally
+ // This is sometimes also referred to as a "marquee"
+ TJvLabelScroll = class(TJvLabelBehavior)
+ private
+ FInterval: Cardinal;
+ FDirection: TJvLabelScrollDirection;
+ FTimer: TTimer;
+ FPadding: Boolean;
+ procedure SetDirection(const Value: TJvLabelScrollDirection);
+ procedure SetInterval(const Value: Cardinal);
+ procedure DoTimerEvent(Sender: TObject);
+ procedure SetPadding(Value: Boolean);
+ protected
+ procedure Start; override;
+ procedure Stop; override;
+ public
+ constructor Create(ALabel: TJvCustomBehaviorLabel); override;
+ published
+ property Active;
+ // Set Padding to True to simulate the Caption being scrolled "around the Edge" of the
+ // label. This property is implemented such that the text is right-padded with spaces
+ property Padding: Boolean read FPadding write SetPadding default False;
+ // Interval specifies the number of milliseconds that elapses between each scroll
+ // A lower Interval increases the speed of the scroll
+ property Interval: Cardinal read FInterval write SetInterval default 50;
+ // Direction specifies the direction of the scroll. Possible values are
+ // sdLeftToRight - the text is scrolled from left to right
+ // sdRightToLeft - the text is scrolled from right to left
+ property Direction: TJvLabelScrollDirection read FDirection write SetDirection default sdLeftToRight;
+ end;
+
+ // TJvLabelAppear implements a behavior where the label appears
+ // from one edge, moves across the form and stops at the other edge
+ // NOTE that to use this behavior, the labels Align property should be set to alNone
+ TJvLabelAppear = class(TJvLabelBehavior)
+ private
+ FParent: TWinControl;
+ FDelay: Cardinal;
+ FInterval: Cardinal;
+ FPixels: Integer;
+ FAppearFrom: TJvAppearDirection;
+ FTimer: TTimer;
+ FOriginalRect: TRect;
+ FFirst: Boolean;
+ procedure SetDelay(const Value: Cardinal);
+ procedure SetInterval(const Value: Cardinal);
+ procedure DoTimerEvent(Sender: TObject);
+ protected
+ procedure Start; override;
+ procedure Stop; override;
+ public
+ constructor Create(ALabel: TJvCustomBehaviorLabel); override;
+ published
+ property Active;
+ // Delay sets the initial delay before the label starts moving
+ property Delay: Cardinal read FDelay write SetDelay default 100;
+ // Interval sets the number of milliseconds that elapses between each move of the label
+ property Interval: Cardinal read FInterval write SetInterval default 20;
+ // Pixels sets number of piels the label moves at each interval
+ property Pixels: Integer read FPixels write FPixels default 3;
+ // AppearFrom sets the edge from which the label appears. It also specifies the direction the label moves in
+ // Possible values for AppearFrom are:
+ // drFromLeft - label appears from the parents left edge and moves to the right edge where it stops
+ // drFromRight - label appears from the parents right edge and moves to the left edge where it stops
+ // drFromTop - label appears from the parents top edge and moves to the bottom edge where it stops
+ // drFromBottom - label appears from the parents bottom edge and moves to the top edge where it stops
+ property AppearFrom: TJvAppearDirection read FAppearFrom write FAppearFrom default drFromRight;
+ end;
+
+ // TJvLabelTyping implements a behavior where the label's original Caption is typed
+ // into the label character by character
+ TJvLabelTyping = class(TJvLabelBehavior)
+ private
+ FMakeErrors: Boolean;
+ FInterval: Cardinal;
+ FTextPos: Integer;
+ FTimer: TTimer;
+ procedure SetInterval(const Value: Cardinal);
+ procedure SetMakeErrors(const Value: Boolean);
+ procedure DoTimerEvent(Sender: TObject);
+ protected
+ procedure Start; override;
+ procedure Stop; override;
+ public
+ constructor Create(ALabel: TJvCustomBehaviorLabel); override;
+ published
+ property Active;
+ // MakeErrors specifies whether the typing sometimes contains errors. Errors are
+ // removed after a short delay and the correct characters are "typed" instead.
+ property MakeErrors: Boolean read FMakeErrors write SetMakeErrors default True;
+ // Interval sets the speed of the typing in milliseconds
+ property Interval: Cardinal read FInterval write SetInterval default 100;
+ end;
+
+ // TJvLabelSpecial implements a behavior where each character of the Caption is
+ // started at #32 (space) and automatically incremented up to it's final value.
+ // When the final value is reached, the next character of the original Caption is
+ // added and incremented. This proceeds until the entire original Caption is shown in the label.
+ TJvLabelSpecial = class(TJvLabelBehavior)
+ private
+ FInterval: Cardinal;
+ FTextPos: Integer;
+ FCharValue: Integer;
+ FTimer: TTimer;
+ procedure SetInterval(const Value: Cardinal);
+ procedure DoTimerEvent(Sender: TObject);
+ protected
+ procedure Start; override;
+ procedure Stop; override;
+ public
+ constructor Create(ALabel: TJvCustomBehaviorLabel); override;
+ published
+ property Active;
+ // Interval sets the number of milliseconds that elapses between increments
+ property Interval: Cardinal read FInterval write SetInterval default 20;
+ end;
+
+ // TJvLabelCodeBreaker "decodes" the text in the label to the
+ // text in DecodedText. Interval sets the number of milliseconds between
+ // "decode attempts", i.e character changes
+ TJvLabelCodeBreaker = class(TJvLabelBehavior)
+ private
+ FScratchPad: TCaption;
+ FDecodedText: TCaption;
+ FInterval: Integer;
+ FCurrentPos: Integer;
+ FTimer: TTimer;
+ procedure SetInterval(const Value: Integer);
+ procedure DoTimer(Sender: TObject);
+ protected
+ procedure Start; override;
+ procedure Stop; override;
+ public
+ constructor Create(ALabel: TJvCustomBehaviorLabel); override;
+ published
+ property DecodedText: TCaption read FDecodedText write FDecodedText;
+ property Interval: Integer read FInterval write SetInterval default 10;
+ end;
+
+ TJvLabelBehaviorOptionsClass = class of TJvLabelBehavior;
+
+ TJvCustomBehaviorLabel = class(TCustomLabel) //TJvExCustomLabel)
+ private
+ FBehavior: TJvLabelBehaviorName;
+ FOptions: TJvLabelBehavior;
+ FOnStart: TNotifyEvent;
+ FOnStop: TNotifyEvent;
+ FUseEffectText: Boolean;
+ FEffectText: TCaption;
+ function GetOptions: TJvLabelBehavior;
+ function BehaviorStored: Boolean;
+ procedure UpdateDesigner;
+ procedure SetBehavior(const Value: TJvLabelBehaviorName);
+ procedure SetOptions(const Value: TJvLabelBehavior);
+ procedure SetUseEffectText(const Value: Boolean);
+ protected
+ procedure Loaded; override;
+ procedure Resize; override;
+ procedure DoStart; dynamic;
+ procedure DoStop; dynamic;
+
+ function GetLabelText: string; override;
+ property Behavior: TJvLabelBehaviorName read FBehavior write SetBehavior stored BehaviorStored;
+ property Caption;
+ property BehaviorOptions: TJvLabelBehavior read GetOptions write SetOptions;
+ property OnStart: TNotifyEvent read FOnStart write FOnStart;
+ property OnStop: TNotifyEvent read FOnStop write FOnStop;
+ public
+ constructor Create(AComponent: TComponent); override;
+ destructor Destroy; override;
+
+ // do not make these published
+ property EffectText: TCaption read FEffectText write FEffectText;
+ property UseEffectText: Boolean read FUseEffectText write SetUseEffectText;
+ end;
+
+ TJvBehaviorLabel = class(TJvCustomBehaviorLabel)
+ published
+ property BiDiMode;
+ property DragCursor;
+ property OnEndDock;
+ property OnStartDock;
+ property ParentBiDiMode;
+ property Behavior;
+ property BehaviorOptions;
+ property OnMouseEnter;
+ property OnMouseLeave;
+// property OnParentColorChange;
+ property OnStart;
+ property OnStop;
+
+ property Align;
+ property Alignment;
+ property Anchors;
+ property AutoSize;
+ property BorderSpacing;
+ property Caption;
+ property Color;
+ property Constraints;
+ property OnEndDrag;
+ property DragKind;
+ property DragMode;
+ property Enabled;
+ property FocusControl;
+ property Font;
+ property ParentColor;
+ property ParentFont;
+ property ParentShowHint;
+ property PopupMenu;
+ property ShowAccelChar;
+ property ShowHint;
+ property Transparent;
+ property Layout;
+ property Visible;
+ property WordWrap;
+ property OnClick;
+ property OnContextPopup;
+ property OnDblClick;
+ property OnDragDrop;
+ property OnDragOver;
+ property OnMouseDown;
+ property OnMouseMove;
+ property OnMouseUp;
+ property OnStartDrag;
+ end;
+
+ // register a new behaviour
+procedure RegisterLabelBehaviorOptions(const Name: TJvLabelBehaviorName; BehaviorOptionsClass:
+ TJvLabelBehaviorOptionsClass);
+// returns the class of the behaviour named Name or TJvLabelBehavior if Name not registered
+function GetLabelBehaviorOptionsClass(const Name: TJvLabelBehaviorName): TJvLabelBehaviorOptionsClass;
+// returns the registered name of BehaviorOptionsClass or an empty string if BehaviorOptionsClass is not registered
+function GetLabelBehaviorName(BehaviorOptionsClass: TJvLabelBehaviorOptionsClass): string;
+// Copies the internal TStrings list to Strings where each Strings[] is the name of a
+// registered class and each Objects[] is a pointer to the corresponding class
+procedure GetRegisteredLabelBehaviorOptions(Strings: TStrings);
+
+
+implementation
+
+uses
+ SysUtils, Forms,
+ JvTypes, JvResources;
+
+var
+ AllBehaviorOptions: TStringList = nil;
+
+function GetLabelBehaviorOptionsClass(const Name: TJvLabelBehaviorName): TJvLabelBehaviorOptionsClass;
+var
+ I: Integer;
+begin
+ Result := TJvLabelBehavior;
+ if AllBehaviorOptions <> nil then
+ begin
+ I := AllBehaviorOptions.IndexOf(Name);
+ if I >= 0 then
+ Result := TJvLabelBehaviorOptionsClass(AllBehaviorOptions.Objects[I]);
+ end;
+end;
+
+function GetLabelBehaviorName(BehaviorOptionsClass: TJvLabelBehaviorOptionsClass): string;
+var
+ I: Integer;
+begin
+ Result := '';
+ if AllBehaviorOptions <> nil then
+ begin
+ I := AllBehaviorOptions.IndexOfObject(TObject(BehaviorOptionsClass));
+ if I >= 0 then
+ Result := AllBehaviorOptions[I];
+ end;
+end;
+
+procedure GetRegisteredLabelBehaviorOptions(Strings: TStrings);
+begin
+ if Strings <> nil then
+ Strings.Assign(AllBehaviorOptions);
+end;
+
+procedure RegisterLabelBehaviorOptions(const Name: TJvLabelBehaviorName;
+ BehaviorOptionsClass: TJvLabelBehaviorOptionsClass);
+begin
+ if AllBehaviorOptions = nil then
+ begin
+ AllBehaviorOptions := TStringList.Create;
+ AllBehaviorOptions.Sorted := True;
+ end;
+ if AllBehaviorOptions.IndexOf(Name) >= 0 then
+ Exit;
+ // raise Exception.CreateFmt('Options %s already registered!',[Name]); // can't raise here: we are probably in an initialization section
+ AllBehaviorOptions.AddObject(Name, TObject(BehaviorOptionsClass));
+end;
+
+procedure NeedBehaviorLabel(const ClassName: string);
+begin
+ raise EJVCLException.CreateResFmt(@RsENeedBehaviorLabel, [ClassName]);
+end;
+
+procedure NoOwnerLabelParent(const ClassName: string);
+begin
+ raise EJVCLException.CreateResFmt(@RsENoOwnerLabelParent, [ClassName]);
+end;
+
+//=== { TJvLabelBehavior } ===================================================
+
+constructor TJvLabelBehavior.Create(ALabel: TJvCustomBehaviorLabel);
+begin
+ inherited Create;
+ if ALabel = nil then
+ NeedBehaviorLabel(ClassName);
+ FLabel := ALabel;
+ FActive := False;
+end;
+
+destructor TJvLabelBehavior.Destroy;
+begin
+ FTemporary := True;
+ Stop;
+ inherited Destroy;
+end;
+
+procedure TJvLabelBehavior.OwnerResize;
+begin
+ //
+end;
+
+procedure TJvLabelBehavior.Resume;
+begin
+ Active := FTmpActive;
+ FTemporary := False;
+end;
+
+procedure TJvLabelBehavior.SetActive(const Value: Boolean);
+begin
+ if FActive <> Value then
+ begin
+ if FActive then
+ Stop;
+ FActive := Value;
+ if FActive then
+ Start;
+ end;
+end;
+
+procedure TJvLabelBehavior.Start;
+begin
+ if not FTemporary then
+ OwnerLabel.DoStart;
+end;
+
+procedure TJvLabelBehavior.Stop;
+begin
+ if not FTemporary then
+ OwnerLabel.DoStop;
+end;
+
+procedure TJvLabelBehavior.Suspend;
+begin
+ FTmpActive := Active;
+ FTemporary := True;
+ Active := False;
+end;
+
+//=== { TJvCustomBehaviorLabel } =============================================
+
+constructor TJvCustomBehaviorLabel.Create(AComponent: TComponent);
+begin
+ // registration
+ if not Assigned(AllBehaviorOptions) then
+ begin
+ RegisterLabelBehaviorOptions(RsNoneCaption, TJvLabelNone);
+ RegisterLabelBehaviorOptions('Blinking', TJvLabelBlink);
+ RegisterLabelBehaviorOptions('Bouncing', TJvLabelBounce);
+ RegisterLabelBehaviorOptions('Scrolling', TJvLabelScroll);
+ RegisterLabelBehaviorOptions('Typing', TJvLabelTyping);
+ RegisterLabelBehaviorOptions('Appearing', TJvLabelAppear);
+ RegisterLabelBehaviorOptions('Special', TJvLabelSpecial);
+ RegisterLabelBehaviorOptions('CodeBreaker', TJvLabelCodeBreaker);
+ end;
+
+ inherited Create(AComponent);
+ FBehavior := RsNoneCaption;
+ FUseEffectText := False;
+ FEffectText := '';
+end;
+
+destructor TJvCustomBehaviorLabel.Destroy;
+begin
+ FreeAndNil(FOptions);
+ inherited Destroy;
+end;
+
+procedure TJvCustomBehaviorLabel.DoStart;
+begin
+ if Assigned(FOnStart) then
+ FOnStart(Self);
+end;
+
+procedure TJvCustomBehaviorLabel.DoStop;
+begin
+ if Assigned(FOnStop) then
+ FOnStop(Self);
+end;
+
+
+function TJvCustomBehaviorLabel.GetLabelText: string;
+begin
+ if UseEffectText then
+ Result := EffectText
+ else
+ Result := inherited GetLabelText;
+end;
+
+
+
+
+function TJvCustomBehaviorLabel.BehaviorStored: Boolean;
+begin
+ Result := FBehavior <> RsNoneCaption;
+end;
+
+function TJvCustomBehaviorLabel.GetOptions: TJvLabelBehavior;
+begin
+ if FOptions = nil then
+ begin
+ // (p3) this doesn't update Options in the OI at DT (unless you collapse/expand the property)
+ FOptions := GetLabelBehaviorOptionsClass(FBehavior).Create(Self);
+ UpdateDesigner;
+ end;
+ Result := FOptions;
+end;
+
+procedure TJvCustomBehaviorLabel.Loaded;
+begin
+ inherited Loaded;
+
+ // Start method usually exits immediately when the component is loading.
+ // As a result, when the component is loaded, we must start the behavior
+ // or the user won't see anything (Mantis 4809)
+ if BehaviorOptions.Active then
+ BehaviorOptions.Start;
+end;
+
+procedure TJvCustomBehaviorLabel.Resize;
+begin
+ inherited Resize;
+ BehaviorOptions.OwnerResize;
+end;
+
+procedure TJvCustomBehaviorLabel.SetBehavior(const Value: TJvLabelBehaviorName);
+var
+ S: TStringList;
+begin
+ if FBehavior <> Value then
+ begin
+ S := TStringList.Create;
+ try
+ GetRegisteredLabelBehaviorOptions(S);
+ if S.IndexOf(Value) < 0 then
+ Exit;
+ finally
+ S.Free;
+ end;
+ // (p3) this doesn't update Options in the OI at DT (unless you collapse/expand the property)
+ FBehavior := Value;
+ FreeAndNil(FOptions);
+ UpdateDesigner;
+ end;
+end;
+
+procedure TJvCustomBehaviorLabel.SetOptions(const Value: TJvLabelBehavior);
+begin
+ if Value = nil then
+ Behavior := ''
+ else
+ if (FOptions = nil) or (FOptions.ClassType <> Value.ClassType) then
+ Behavior := GetLabelBehaviorName(TJvLabelBehaviorOptionsClass(Value.ClassType));
+ UpdateDesigner;
+end;
+
+procedure TJvCustomBehaviorLabel.SetUseEffectText(const Value: Boolean);
+begin
+ if Value <> FUseEffectText then
+ begin
+ FUseEffectText := Value;
+ if ComponentState * [csLoading, csDestroying] = [] then
+ Repaint;
+ end;
+end;
+
+procedure TJvCustomBehaviorLabel.UpdateDesigner;
+var
+ F: TCustomForm;
+begin
+ if csDesigning in ComponentState then
+ begin
+ F := GetParentForm(Self);
+ if (F <> nil) and (F.Designer <> nil) then
+ F.Designer.Modified;
+ end;
+end;
+
+//=== { TJvLabelBlink } ======================================================
+
+constructor TJvLabelBlink.Create(ALabel: TJvCustomBehaviorLabel);
+begin
+ inherited Create(ALabel);
+ ALabel.EffectText := '';
+ FDelay := 100;
+ FInterval := 400;
+end;
+
+procedure TJvLabelBlink.DoTimerEvent(Sender: TObject);
+begin
+ FTimer.Enabled := False;
+ FTimer.Interval := FInterval;
+ FToggled := not FToggled;
+ OwnerLabel.UseEffectText := FToggled;
+ FTimer.Enabled := FInterval > 0;
+end;
+
+procedure TJvLabelBlink.SetDelay(const Value: Cardinal);
+begin
+ if FDelay <> Value then
+ begin
+ Suspend;
+ FDelay := Value;
+ Resume;
+ end;
+end;
+
+procedure TJvLabelBlink.SetInterval(const Value: Cardinal);
+begin
+ if FInterval <> Value then
+ begin
+ Suspend;
+ FInterval := Value;
+ Resume;
+ end;
+end;
+
+procedure TJvLabelBlink.Start;
+begin
+ inherited Start;
+ if OwnerLabel.ComponentState * [csLoading, csDestroying] <> [] then
+ Exit;
+ if FTimer = nil then
+ begin
+ FTimer := TTimer.Create(nil);
+ FTimer.Enabled := False;
+ FTimer.OnTimer := @DoTimerEvent;
+ end;
+ FTimer.Interval := FDelay;
+ FToggled := False;
+ if FDelay = 0 then
+ FDelay := 1;
+ FTimer.Enabled := True; // not (csDesigning in OwnerLabel.ComponentState);
+end;
+
+procedure TJvLabelBlink.Stop;
+begin
+ if FTimer <> nil then
+ begin
+ FreeAndNil(FTimer);
+ OwnerLabel.UseEffectText := False;
+ end;
+ inherited Stop;
+end;
+
+//=== { TJvLabelBounce } =====================================================
+
+constructor TJvLabelBounce.Create(ALabel: TJvCustomBehaviorLabel);
+begin
+ inherited Create(ALabel);
+ FInterval := 20;
+ FPixels := 6;
+end;
+
+procedure TJvLabelBounce.DoTimerEvent(Sender: TObject);
+begin
+ FTimer.Enabled := False;
+ if Pixels = 0 then
+ Pixels := Random(8);
+ with OwnerLabel do
+ case FDirection of
+ 0:
+ if (Left - Pixels <= 0) or (Top + Height + Pixels >= FParent.ClientHeight) then
+ begin
+ FDirection := Random(4);
+ // Pixels := Random(8);
+ end
+ else
+ begin
+ Left := Left - Pixels;
+ Top := Top + Pixels;
+ end;
+ 1:
+ if (Top + Height + Pixels >= FParent.ClientHeight) or
+ (Left + Width + Pixels >= FParent.ClientWidth) then
+ begin
+ FDirection := Random(4);
+ // Pixels := Random(8);
+ end
+ else
+ begin
+ Top := Top + Pixels;
+ Left := Left + Pixels;
+ end;
+ 2:
+ if (Left - Pixels <= 0) or (Top - Pixels <= 0) then
+ begin
+ FDirection := Random(4);
+ // Pixels := Random(8);
+ end
+ else
+ begin
+ Left := Left - Pixels;
+ Top := Top - Pixels;
+ end;
+ 3:
+ if (Left + Width + Pixels > FParent.ClientWidth) or (Top - Pixels <= 0) then
+ begin
+ FDirection := Random(4);
+ // Pixels := Random(8);
+ end
+ else
+ begin
+ Left := Left + Pixels;
+ Top := Top - Pixels;
+ end;
+ end;
+ FTimer.Enabled := True;
+end;
+
+procedure TJvLabelBounce.SetInterval(const Value: Cardinal);
+begin
+ if FInterval <> Value then
+ begin
+ Suspend;
+ FInterval := Value;
+ if FInterval <= 0 then
+ FInterval := 20;
+ Resume;
+ end;
+end;
+
+procedure TJvLabelBounce.SetPixels(const Value: Integer);
+begin
+ if FPixels <> Value then
+ begin
+ Suspend;
+ FPixels := Value;
+ if FPixels <= 0 then
+ FPixels := 6;
+ Resume;
+ end;
+end;
+
+procedure TJvLabelBounce.Start;
+begin
+ if OwnerLabel.ComponentState * [csLoading, csDestroying] <> [] then
+ Exit;
+ FParent := OwnerLabel.Parent;
+ if FParent = nil then
+ NoOwnerLabelParent(ClassName);
+ inherited Start;
+ FOriginalRect := OwnerLabel.BoundsRect;
+ Randomize;
+ if FTimer = nil then
+ begin
+ FTimer := TTimer.Create(nil);
+ FTimer.Enabled := False;
+ FTimer.OnTimer := @DoTimerEvent;
+ end;
+ FTimer.Interval := Interval;
+ FTimer.Enabled := True;
+end;
+
+procedure TJvLabelBounce.Stop;
+begin
+ FreeAndNil(FTimer);
+ if not IsRectEmpty(FOriginalRect) then
+ OwnerLabel.BoundsRect := FOriginalRect;
+ inherited Stop;
+end;
+
+//=== { TJvLabelScroll } =====================================================
+
+constructor TJvLabelScroll.Create(ALabel: TJvCustomBehaviorLabel);
+begin
+ inherited Create(ALabel);
+ FInterval := 50;
+ FDirection := sdLeftToRight;
+end;
+
+procedure TJvLabelScroll.DoTimerEvent(Sender: TObject);
+var
+ Tmp: TCaption;
+begin
+ FTimer.Enabled := False;
+ if OwnerLabel.Caption <> '' then
+ begin
+ Tmp := OwnerLabel.EffectText;
+ if FDirection = sdLeftToRight then
+ Tmp := Tmp[Length(Tmp)] + Copy(Tmp, 1, Length(Tmp) - 1)
+ else
+ Tmp := Copy(Tmp, 2, Length(Tmp) - 1) + Tmp[1];
+ OwnerLabel.EffectText := Tmp;
+ OwnerLabel.Repaint;
+ end;
+ FTimer.Enabled := True;
+end;
+
+procedure TJvLabelScroll.SetDirection(const Value: TJvLabelScrollDirection);
+begin
+ if FDirection <> Value then
+ begin
+ Suspend;
+ FDirection := Value;
+ Resume;
+ end;
+end;
+
+procedure TJvLabelScroll.SetInterval(const Value: Cardinal);
+begin
+ if FInterval <> Value then
+ begin
+ Suspend;
+ FInterval := Value;
+ Resume;
+ end;
+end;
+
+procedure TJvLabelScroll.SetPadding(Value: Boolean);
+var
+ Tmp: TCaption;
+begin
+ FPadding := Value;
+ Tmp := '';
+ while OwnerLabel.Canvas.TextWidth(Tmp) < OwnerLabel.Width do
+ Tmp := Tmp + ' ';
+ if Value then
+ OwnerLabel.EffectText := OwnerLabel.Caption + Tmp
+ else
+ OwnerLabel.EffectText := OwnerLabel.Caption;
+end;
+
+procedure TJvLabelScroll.Start;
+begin
+ inherited Start;
+ if OwnerLabel.ComponentState * [csLoading, csDestroying] <> [] then
+ Exit;
+ if FTimer = nil then
+ begin
+ FTimer := TTimer.Create(nil);
+ FTimer.Enabled := False;
+ FTimer.OnTimer := @DoTimerEvent;
+ end;
+ FTimer.Interval := Interval;
+ SetPadding(Padding);
+ OwnerLabel.UseEffectText := True;
+ FTimer.Enabled := True;
+end;
+
+procedure TJvLabelScroll.Stop;
+begin
+ FreeAndNil(FTimer);
+ OwnerLabel.UseEffectText := False;
+ inherited Stop;
+end;
+
+//=== { TJvLabelAppear } =====================================================
+
+constructor TJvLabelAppear.Create(ALabel: TJvCustomBehaviorLabel);
+begin
+ inherited Create(ALabel);
+ FDelay := 100;
+ FInterval := 20;
+ FPixels := 3;
+ FAppearFrom := drFromRight;
+end;
+
+procedure TJvLabelAppear.DoTimerEvent(Sender: TObject);
+var
+ FWidth, FHeight: Integer;
+ FSuspend: Boolean;
+begin
+ FWidth := FOriginalRect.Right - FOriginalRect.Left;
+ FHeight := FOriginalRect.Bottom - FOriginalRect.Top;
+ FSuspend := False;
+ if FFirst then
+ begin
+ case FAppearFrom of
+ drFromRight:
+ begin
+ OwnerLabel.Left := FParent.ClientWidth;
+ OwnerLabel.Width := 0;
+ end;
+ drFromLeft:
+ OwnerLabel.Left := -OwnerLabel.Width;
+ drFromTop:
+ OwnerLabel.Top := -OwnerLabel.Height;
+ drFromBottom:
+ begin
+ OwnerLabel.Top := FParent.ClientHeight;
+ OwnerLabel.Height := 0;
+ end;
+ end;
+ OwnerLabel.Visible := True;
+ FFirst := False;
+ end;
+
+ case FAppearFrom of
+ drFromRight:
+ begin
+ if Abs(OwnerLabel.Left - FOriginalRect.Left) < Pixels then
+ begin
+ OwnerLabel.Left := FOriginalRect.Left;
+ FSuspend := True;
+ end
+ else
+ OwnerLabel.Left := OwnerLabel.Left - Pixels;
+ if OwnerLabel.Width <> FWidth then
+ begin
+ if OwnerLabel.Left + FWidth < FParent.ClientWidth then
+ OwnerLabel.Width := FWidth
+ else
+ OwnerLabel.Width := FParent.ClientWidth - OwnerLabel.Left - 2;
+ end;
+ end;
+ drFromLeft:
+ if Abs(OwnerLabel.Left - FOriginalRect.Left) < Pixels then
+ begin
+ OwnerLabel.Left := FOriginalRect.Left;
+ FSuspend := True;
+ end
+ else
+ OwnerLabel.Left := OwnerLabel.Left + Pixels;
+ drFromTop:
+ if Abs(OwnerLabel.Top - FOriginalRect.Top) < Pixels then
+ begin
+ OwnerLabel.Top := FOriginalRect.Top;
+ FSuspend := True;
+ end
+ else
+ OwnerLabel.Top := OwnerLabel.Top + Pixels;
+ drFromBottom:
+ begin
+ if Abs(OwnerLabel.Top - FOriginalRect.Top) < Pixels then
+ begin
+ OwnerLabel.Top := FOriginalRect.Top;
+ FSuspend := True;
+ end
+ else
+ OwnerLabel.Top := OwnerLabel.Top - Pixels;
+ if OwnerLabel.Height <> FHeight then
+ begin
+ if OwnerLabel.Top + FHeight < FParent.ClientHeight then
+ OwnerLabel.Height := FHeight
+ else
+ OwnerLabel.Height := FParent.ClientHeight - OwnerLabel.Top - 2;
+ end;
+ end;
+ end;
+ FTimer.Interval := Interval;
+ if FSuspend then
+ Active := False
+ else
+ FTimer.Enabled := True;
+end;
+
+procedure TJvLabelAppear.SetDelay(const Value: Cardinal);
+begin
+ if FDelay <> Value then
+ begin
+ Suspend;
+ FDelay := Value;
+ Resume;
+ end;
+end;
+
+procedure TJvLabelAppear.SetInterval(const Value: Cardinal);
+begin
+ if FInterval <> Value then
+ begin
+ Suspend;
+ FInterval := Value;
+ Resume;
+ end;
+end;
+
+procedure TJvLabelAppear.Start;
+begin
+ if OwnerLabel.ComponentState * [csLoading, csDestroying] <> [] then
+ Exit;
+ FParent := OwnerLabel.Parent;
+ if FParent = nil then
+ NoOwnerLabelParent(ClassName);
+ inherited Start;
+ if FTimer = nil then
+ begin
+ FTimer := TTimer.Create(nil);
+ FTimer.Enabled := False;
+ FTimer.OnTimer := @DoTimerEvent;
+ end;
+ FTimer.Interval := Delay;
+ FFirst := True;
+ FOriginalRect := OwnerLabel.BoundsRect;
+ FTimer.Enabled := True;
+end;
+
+procedure TJvLabelAppear.Stop;
+begin
+ FreeAndNil(FTimer);
+ if not IsRectEmpty(FOriginalRect) then
+ OwnerLabel.BoundsRect := FOriginalRect;
+ inherited Stop;
+end;
+
+//=== { TJvLabelTyping } =====================================================
+
+constructor TJvLabelTyping.Create(ALabel: TJvCustomBehaviorLabel);
+begin
+ inherited Create(ALabel);
+ FInterval := 100;
+ FMakeErrors := True;
+end;
+
+procedure TJvLabelTyping.DoTimerEvent(Sender: TObject);
+var
+ Tmp: TCaption;
+ I: Integer;
+begin
+ FTimer.Enabled := False;
+ if FTextPos <= Length(OwnerLabel.Caption) then
+ begin
+ Tmp := Copy(OwnerLabel.Caption, 1, FTextPos - 1);
+ I := Random(10);
+ if (I = 7) and MakeErrors then
+ Tmp := Tmp + Char(Ord(OwnerLabel.Caption[FTextPos]) - Random(10))
+ else
+ Tmp := Tmp + OwnerLabel.Caption[FTextPos];
+ if (MakeErrors) and (I <> 7) then
+ FTimer.Interval := Interval
+ else
+ FTimer.Interval := Interval * 2;
+ OwnerLabel.EffectText := Tmp;
+ OwnerLabel.Repaint;
+ Inc(FTextPos);
+ FTimer.Enabled := True;
+ end
+ else
+ Active := False;
+end;
+
+procedure TJvLabelTyping.SetInterval(const Value: Cardinal);
+begin
+ if FInterval <> Value then
+ begin
+ Suspend;
+ FInterval := Value;
+ Resume;
+ end;
+end;
+
+procedure TJvLabelTyping.SetMakeErrors(const Value: Boolean);
+begin
+ if FMakeErrors <> Value then
+ begin
+ Suspend;
+ FMakeErrors := Value;
+ Resume;
+ end;
+end;
+
+procedure TJvLabelTyping.Start;
+begin
+ inherited Start;
+ if OwnerLabel.ComponentState * [csLoading, csDestroying] <> [] then
+ Exit;
+ if FTimer = nil then
+ begin
+ FTimer := TTimer.Create(nil);
+ FTimer.Enabled := False;
+ FTimer.OnTimer := @DoTimerEvent;
+ end;
+ FTimer.Interval := Interval;
+ Randomize;
+ OwnerLabel.EffectText := '';
+ OwnerLabel.UseEffectText := True;
+ FTextPos := 1;
+ FTimer.Enabled := True;
+end;
+
+procedure TJvLabelTyping.Stop;
+begin
+ FreeAndNil(FTimer);
+ OwnerLabel.UseEffectText := False;
+ inherited Stop;
+end;
+
+//=== { TJvLabelSpecial } ====================================================
+
+constructor TJvLabelSpecial.Create(ALabel: TJvCustomBehaviorLabel);
+begin
+ inherited Create(ALabel);
+ FInterval := 20;
+end;
+
+procedure TJvLabelSpecial.DoTimerEvent(Sender: TObject);
+begin
+ FTimer.Enabled := False;
+ if FTextPos < Length(OwnerLabel.Caption) then
+ begin
+ if FCharValue > Ord(OwnerLabel.Caption[FTextPos]) then
+ begin
+ Inc(FTextPos);
+ FCharValue := 32;
+ end;
+ OwnerLabel.EffectText := Copy(OwnerLabel.Caption, 1, FTextPos) + Char(FCharValue);
+ OwnerLabel.Repaint;
+ Inc(FCharValue);
+ FTimer.Enabled := True;
+ end
+ else
+ Active := False;
+end;
+
+procedure TJvLabelSpecial.SetInterval(const Value: Cardinal);
+begin
+ if FInterval <> Value then
+ begin
+ Suspend;
+ FInterval := Value;
+ Resume;
+ end;
+end;
+
+procedure TJvLabelSpecial.Start;
+begin
+ inherited Start;
+ if OwnerLabel.ComponentState * [csLoading, csDestroying] <> [] then
+ Exit;
+ if FTimer = nil then
+ begin
+ FTimer := TTimer.Create(nil);
+ FTimer.Enabled := False;
+ FTimer.OnTimer := @DoTimerEvent;
+ end;
+ FTextPos := 1;
+ FCharValue := 32;
+ OwnerLabel.EffectText := '';
+ OwnerLabel.UseEffectText := True;
+ FTimer.Interval := Interval;
+ FTimer.Enabled := True;
+end;
+
+procedure TJvLabelSpecial.Stop;
+begin
+ FreeAndNil(FTimer);
+ OwnerLabel.UseEffectText := False;
+ inherited Stop;
+end;
+
+//=== { TJvLabelCodeBreaker } ================================================
+
+constructor TJvLabelCodeBreaker.Create(ALabel: TJvCustomBehaviorLabel);
+begin
+ inherited Create(ALabel);
+ FInterval := 10;
+end;
+
+procedure TJvLabelCodeBreaker.DoTimer(Sender: TObject);
+begin
+ FTimer.Enabled := False;
+ if (FCurrentPos > Length(FScratchPad)) or (FCurrentPos > Length(DecodedText)) then
+ begin
+ OwnerLabel.EffectText := DecodedText;
+ OwnerLabel.Repaint;
+ Active := False;
+ OwnerLabel.UseEffectText := False;
+ Exit;
+ end
+ else
+ if FScratchPad[FCurrentPos] <> DecodedText[FCurrentPos] then
+ begin
+ FScratchPad[FCurrentPos] := Char(32 + Random(Ord(DecodedText[FCurrentPos]) + 10));
+ // OwnerLabel.EffectText := Copy(OwnerLabel.Caption, 1, FCurrentPos - 1) +
+ // FScratchPad[FCurrentPos] + Copy(OwnerLabel.Caption, FCurrentPos + 1, MaxInt);
+ // (p3) this is the same without the copying...
+ OwnerLabel.EffectText := FScratchPad;
+ OwnerLabel.Repaint;
+ end
+ else
+ Inc(FCurrentPos);
+ // (p3) this seems unnecessary since we have an Interval property
+// Sleep(FInterval);
+ FTimer.Enabled := True;
+end;
+
+procedure TJvLabelCodeBreaker.SetInterval(const Value: Integer);
+begin
+ if FInterval <> Value then
+ begin
+ Suspend;
+ FInterval := Value;
+ Resume;
+ end;
+end;
+
+procedure TJvLabelCodeBreaker.Start;
+begin
+ inherited Start;
+ FCurrentPos := 1;
+ if (Interval > 0) and (OwnerLabel.Caption <> '') and (DecodedText <> '') then
+ begin
+ FScratchPad := OwnerLabel.Caption;
+ FTimer := TTimer.Create(nil);
+ FTimer.Enabled := False;
+ FTimer.OnTimer := @DoTimer;
+ FTimer.Interval := Interval;
+ FTimer.Enabled := True;
+ OwnerLabel.UseEffectText := True;
+ end
+ else
+ Active := False;
+end;
+
+procedure TJvLabelCodeBreaker.Stop;
+begin
+ FreeAndNil(FTimer);
+ OwnerLabel.Caption := OwnerLabel.EffectText;
+ OwnerLabel.UseEffectText := False;
+ inherited Stop;
+end;
+
+finalization
+ FreeAndNil(AllBehaviorOptions);
+
+end.