991 lines
25 KiB
ObjectPascal
991 lines
25 KiB
ObjectPascal
{-----------------------------------------------------------------------------
|
|
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: JvID3v2Editor.PAS, released on 2003-04-16.
|
|
|
|
The Initial Developer of the Original Code is Remko Bonte [remkobonte att myrealbox dott com]
|
|
Portions created by Remko Bonte are Copyright (C) 2003 Remko Bonte.
|
|
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.sourceforge.net
|
|
|
|
Known Issues:
|
|
-----------------------------------------------------------------------------}
|
|
// $Id: JvID3v2EditorForm.pas 10610 2006-05-19 13:35:08Z elahn $
|
|
|
|
unit JvID3v2EditorForm;
|
|
|
|
{$I jvcl.inc}
|
|
|
|
interface
|
|
|
|
{ Most code is copied from DSDesign.pas }
|
|
|
|
uses
|
|
Classes, Windows, Messages, Forms, StdCtrls, ExtCtrls, Menus, Controls,
|
|
{$IFDEF COMPILER6_UP}
|
|
DesignEditors, DesignIntf, DesignMenus, DesignWindows,
|
|
{$ELSE}
|
|
DsgnIntf, DsgnWnds,
|
|
{$ENDIF COMPILER6_UP}
|
|
JvID3v2Base, JvID3v2Types, JvDsgnTypes;
|
|
|
|
type
|
|
TSelectionProc = function(AFrame: TJvID3Frame): Boolean of object;
|
|
|
|
TFSDesigner = class;
|
|
|
|
TJvID3FramesEditor = class(TDesignWindow)
|
|
FrameListBox: TListBox;
|
|
LocalMenu: TPopupMenu;
|
|
NewItem: TMenuItem;
|
|
N1: TMenuItem;
|
|
DeleteItem: TMenuItem;
|
|
SelectAllItem: TMenuItem;
|
|
procedure FormCreate(Sender: TObject);
|
|
procedure ListBoxClick(Sender: TObject);
|
|
procedure ListBoxKeyDown(Sender: TObject; var Key: Word;
|
|
Shift: TShiftState);
|
|
procedure ListBoxDragDrop(Sender, Source: TObject; X, Y: Integer);
|
|
procedure ListBoxDragOver(Sender, Source: TObject; X, Y: Integer;
|
|
State: TDragState; var Accept: Boolean);
|
|
procedure FormDestroy(Sender: TObject);
|
|
procedure NewFrameClick(Sender: TObject);
|
|
procedure DeleteClick(Sender: TObject);
|
|
procedure SelectAllClick(Sender: TObject);
|
|
private
|
|
FFSDesigner: TFSDesigner;
|
|
FController: TJvID3Controller;
|
|
FFocusRectItem: Integer;
|
|
FMinWidth: Integer;
|
|
FMinHeight: Integer;
|
|
procedure MoveFrames(MoveOffset: Integer);
|
|
procedure RemoveFrames;
|
|
procedure SelectAll;
|
|
procedure RestoreSelection(var Selection: TStringList;
|
|
ItemIndex, TopIndex: Integer; RestoreUpdate: Boolean);
|
|
procedure SaveSelection(var Selection: TStringList;
|
|
var ItemIndex, TopIndex: Integer; NoUpdate: Boolean);
|
|
procedure SetController(Value: TJvID3Controller);
|
|
procedure UpdateDisplay;
|
|
procedure UpdateCaption;
|
|
procedure UpdateFrameList;
|
|
procedure UpdateSelection;
|
|
procedure WMGetMinMaxInfo(var Msg: TWMGetMinMaxInfo); message WM_GETMINMAXINFO;
|
|
protected
|
|
procedure Activated; override;
|
|
function UniqueName(Component: TComponent): string; override;
|
|
public
|
|
function ForEachSelection(Proc: TSelectionProc): Boolean;
|
|
function DoNewFrame: TJvID3Frame;
|
|
{$IFDEF COMPILER5}
|
|
procedure SelectionChanged(ASelection: TDesignerSelectionList); override;
|
|
procedure EditAction(Action: TEditAction); override;
|
|
procedure ComponentDeleted(Component: IPersistent); override;
|
|
procedure FormModified; override;
|
|
{$ELSE}
|
|
function EditAction(Action: TEditAction): Boolean; override;
|
|
procedure ItemDeleted(const ADesigner: IDesigner; AItem: TPersistent); override;
|
|
procedure SelectionChanged(const ADesigner: IDesigner; const ASelection: IDesignerSelections); override;
|
|
procedure ItemsModified(const Designer: IDesigner); override;
|
|
{$ENDIF COMPILER5}
|
|
property Controller: TJvID3Controller read FController write SetController;
|
|
end;
|
|
|
|
TJvID3ControllerEditor = class(TComponentEditor)
|
|
protected
|
|
procedure Commit;
|
|
procedure RemoveTag;
|
|
public
|
|
procedure ExecuteVerb(Index: Integer); override;
|
|
function GetVerb(Index: Integer): string; override;
|
|
function GetVerbCount: Integer; override;
|
|
end;
|
|
|
|
TFSDesigner = class(TJvID3ControllerDesigner)
|
|
private
|
|
FFramesEditor: TJvID3FramesEditor;
|
|
function GetFrameDescription(const FrameID: TJvID3FrameID): string;
|
|
public
|
|
destructor Destroy; override;
|
|
procedure ID3Event(Event: TJvID3Event; Info: Longint); override;
|
|
property FramesEditor: TJvID3FramesEditor read FFramesEditor;
|
|
property FrameDescription[const FrameID: TJvID3FrameID]: string read GetFrameDescription;
|
|
end;
|
|
|
|
TJvID3FileInfoEditor = class(TClassProperty)
|
|
public
|
|
procedure Edit; override;
|
|
function GetAttributes: TPropertyAttributes; override;
|
|
end;
|
|
|
|
procedure ShowFramesEditor(Designer: IJvFormDesigner; AController: TJvID3Controller);
|
|
function CreateFramesEditor(Designer: IJvFormDesigner;
|
|
AController: TJvID3Controller; var Shared: Boolean): TJvID3FramesEditor;
|
|
procedure ShowFileInfo(AController: TJvID3Controller);
|
|
|
|
implementation
|
|
|
|
uses
|
|
Dialogs,
|
|
Math, SysUtils,
|
|
JvID3v2DefineForm, JvTypes, JvDsgnConsts;
|
|
|
|
|
|
{$R *.dfm}
|
|
|
|
type
|
|
TJvID3ControllerAccess = class(TJvID3Controller);
|
|
|
|
const
|
|
cFrameDescriptions: array [TJvID3FrameID] of string =
|
|
(
|
|
RsfiErrorFrame,
|
|
RsfiPaddingFrame,
|
|
RsfiNoFrame,
|
|
RsfiAudioCrypto,
|
|
RsfiPicture,
|
|
RsfiAudioSeekPoint,
|
|
RsfiComment,
|
|
RsfiCommercial,
|
|
RsfiCryptoReg,
|
|
RsfiEqualization2,
|
|
RsfiEqualization,
|
|
RsfiEventTiming,
|
|
RsfiGeneralObject,
|
|
RsfiGroupingReg,
|
|
RsfiInvolvedPeople,
|
|
RsfiLinkedInfo,
|
|
RsfiCDID,
|
|
RsfiMPEGLookup,
|
|
RsfiOwnership,
|
|
RsfiPrivate,
|
|
RsfiPlayCounter,
|
|
RsfiPopularimeter,
|
|
RsfiPositionsync,
|
|
RsfiBufferSize,
|
|
RsfiVolumeAdj2,
|
|
RsfiVolumeAdj,
|
|
RsfiReverb,
|
|
RsfiSeekFrame,
|
|
RsfiSignature,
|
|
RsfiSyncedLyrics,
|
|
RsfiSyncedTempo,
|
|
RsfiAlbum,
|
|
RsfiBPM,
|
|
RsfiComposer,
|
|
RsfiContentType,
|
|
RsfiCopyright,
|
|
RsfiDate,
|
|
RsfiEncodingTime,
|
|
RsfiPlaylistDelay,
|
|
RsfiOrigReleaseTime,
|
|
RsfiRecordingTime,
|
|
RsfiReleaseTime,
|
|
RsfiTaggingTime,
|
|
RsfiInvolvedPeople2,
|
|
RsfiEncodedBy,
|
|
RsfiLyricist,
|
|
RsfiFileType,
|
|
RsfiTime,
|
|
RsfiContentGroup,
|
|
RsfiTitle,
|
|
RsfiSubTitle,
|
|
RsfiInitialKey,
|
|
RsfiLanguage,
|
|
RsfiSongLen,
|
|
RsfiMusicianCreditList,
|
|
RsfiMediaType,
|
|
RsfiMood,
|
|
RsfiOrigAlbum,
|
|
RsfiOrigFileName,
|
|
RsfiOrigLyricist,
|
|
RsfiOrigArtist,
|
|
RsfiOrigYear,
|
|
RsfiFileOwner,
|
|
RsfiLeadArtist,
|
|
RsfiBand,
|
|
RsfiConductor,
|
|
RsfiMixArtist,
|
|
RsfiPartInSet,
|
|
RsfiProducedNotice,
|
|
RsfiPublisher,
|
|
RsfiTrackNum,
|
|
RsfiRecordingDates,
|
|
RsfiNetRadioStation,
|
|
RsfiNetRadioOwner,
|
|
RsfiSize,
|
|
RsfiAlbumSortOrder,
|
|
RsfiPerformerSortOrder,
|
|
RsfiTitleSortOrder,
|
|
RsfiISRC,
|
|
RsfiEncoderSettings,
|
|
RsfiSetSubTitle,
|
|
RsfiUserText,
|
|
RsfiYear,
|
|
RsfiUniqueFileID,
|
|
RsfiTermsOfUse,
|
|
RsfiUnsyncedLyrics,
|
|
RsfiWWWCommercialInfo,
|
|
RsfiWWWCopyright,
|
|
RsfiWWWAudioFile,
|
|
RsfiWWWArtist,
|
|
RsfiWWWAudioSource,
|
|
RsfiWWWRadioPage,
|
|
RsfiWWWPayment,
|
|
RsfiWWWPublisher,
|
|
RsfiWWWUser,
|
|
RsfiMetaCrypto,
|
|
RsfiMetaCompression
|
|
);
|
|
|
|
procedure ShowFramesEditor(Designer: IJvFormDesigner; AController: TJvID3Controller);
|
|
var
|
|
FramesEditor: TJvID3FramesEditor;
|
|
VShared: Boolean;
|
|
begin
|
|
FramesEditor := CreateFramesEditor(Designer, AController, VShared);
|
|
if FramesEditor <> nil then
|
|
FramesEditor.Show;
|
|
end;
|
|
|
|
function CreateFramesEditor(Designer: IJvFormDesigner;
|
|
AController: TJvID3Controller; var Shared: Boolean): TJvID3FramesEditor;
|
|
begin
|
|
Shared := True;
|
|
if AController.Designer <> nil then
|
|
Result := (AController.Designer as TFSDesigner).FFramesEditor
|
|
else
|
|
begin
|
|
Result := TJvID3FramesEditor.Create(Application);
|
|
Result.Designer := Designer;
|
|
Result.Controller := AController;
|
|
Shared := False;
|
|
end;
|
|
end;
|
|
|
|
procedure ShowFileInfo(AController: TJvID3Controller);
|
|
const
|
|
cVersion: array [TJvMPEGVersion] of string =
|
|
(RsMPEG25, RsMPEGUnknown, RsMPEG20, RsMPEG10);
|
|
cLayer: array [TJvMPEGLayer] of string =
|
|
(RsLayerUnknown, RsLayer3, RsLayer2, RsLayer1);
|
|
cChannelMode: array [TJvMPEGChannelMode] of string =
|
|
(RsChannelModeStereo, RsChannelModeJointStereo,
|
|
RsChannelModeDualChannel, RsChannelModeMono);
|
|
cEmphasis: array [TJvMPEGEmphasis] of string =
|
|
(RsEmphasisNone, RsEmphasisMicrosec, RsEmphasisUnknown, RsEmphasisCCITTJ17);
|
|
cBool: array [Boolean] of string =
|
|
(RsBoolNo, RsBoolYes);
|
|
cVbr: array [Boolean] of string =
|
|
(RsVbrNo, RsVbrVbr);
|
|
var
|
|
Msg: string;
|
|
SavedActive: Boolean;
|
|
begin
|
|
SavedActive := AController.Active;
|
|
try
|
|
with TJvID3ControllerAccess(AController) do
|
|
begin
|
|
if FileName = '' then
|
|
begin
|
|
MessageDlg(RsID3Err_NoFileSpecified, mtError, [mbOK], 0);
|
|
Exit;
|
|
end;
|
|
|
|
if not FileExists(FileName) then
|
|
begin
|
|
MessageDlg(Format(RSID3Err_FileDoesNotExists, [FileName]),
|
|
mtError, [mbOK], 0);
|
|
Exit;
|
|
end;
|
|
|
|
Active := True;
|
|
|
|
with FileInfo do
|
|
begin
|
|
if not IsValid then
|
|
begin
|
|
MessageDlg(RSID3Err_NoValidMPEGTag, mtError, [mbOK], 0);
|
|
Exit;
|
|
end;
|
|
|
|
Msg := Format(RsIDV2FileInfoFmt, [FileSize, HeaderFoundAt, LengthInSec,
|
|
cVersion[Version], cLayer[Layer], Bitrate, cVbr[IsVbr], FrameCount,
|
|
SamplingRateFrequency, cChannelMode[ChannelMode],
|
|
cBool[mbProtection in Bits], cBool[mbCopyrighted in Bits],
|
|
cBool[mbOriginal in Bits], cEmphasis[Emphasis]]);
|
|
end;
|
|
end;
|
|
|
|
{ We don't use MessageDlg now, because we want a custom caption }
|
|
with CreateMessageDialog(Msg, mtCustom, [mbOK]) do
|
|
try
|
|
Position := poScreenCenter;
|
|
Caption := RsIDV2FileInfoCaption;
|
|
ShowModal;
|
|
finally
|
|
Free;
|
|
end;
|
|
finally
|
|
AController.Active := SavedActive;
|
|
end;
|
|
end;
|
|
|
|
//=== { TJvID3FrameEditor } ==================================================
|
|
|
|
procedure TJvID3FramesEditor.Activated;
|
|
begin
|
|
{$IFDEF COMPILER6_UP}
|
|
Designer.Activate;
|
|
{$ENDIF COMPILER6_UP}
|
|
try
|
|
UpdateSelection;
|
|
except
|
|
FrameListBox.Items.Clear;
|
|
end;
|
|
end;
|
|
|
|
{$IFDEF COMPILER5}
|
|
procedure TJvID3FramesEditor.ComponentDeleted(Component: IPersistent);
|
|
var
|
|
P: TPersistent;
|
|
begin
|
|
P := ExtractPersistent(Component);
|
|
if P = Controller then
|
|
Controller := nil
|
|
else
|
|
if (P is TJvID3Frame) and (TJvID3Frame(P).Controller = Controller) then
|
|
UpdateDisplay;
|
|
end;
|
|
{$ENDIF COMPILER5}
|
|
|
|
function TJvID3FramesEditor.DoNewFrame: TJvID3Frame;
|
|
var
|
|
DefineFrame: TJvID3DefineDlg;
|
|
begin
|
|
Result := nil;
|
|
DefineFrame := TJvID3DefineDlg.Create(Application);
|
|
try
|
|
DefineFrame.FSDesigner := FFSDesigner;
|
|
DefineFrame.Designer := Designer;
|
|
DefineFrame.Controller := Controller;
|
|
if DefineFrame.ShowModal = mrOk then
|
|
begin
|
|
Result := DefineFrame.Frame;
|
|
if Visible then
|
|
UpdateDisplay;
|
|
Designer.Modified;
|
|
end;
|
|
finally
|
|
DefineFrame.Release;
|
|
end;
|
|
end;
|
|
|
|
{$IFDEF COMPILER6_UP}
|
|
function TJvID3FramesEditor.EditAction(Action: TEditAction): Boolean;
|
|
{$ELSE}
|
|
procedure TJvID3FramesEditor.EditAction(Action: TEditAction);
|
|
{$ENDIF COMPILER6_UP}
|
|
begin
|
|
{$IFDEF COMPILER6_UP}
|
|
Result := True;
|
|
{$ENDIF COMPILER6_UP}
|
|
case Action of
|
|
{eaCut: Cut;
|
|
eaCopy: Copy;
|
|
eaPaste: Paste;}
|
|
eaDelete:
|
|
RemoveFrames;
|
|
eaSelectAll:
|
|
begin
|
|
SelectAll;
|
|
UpdateSelection;
|
|
end;
|
|
{$IFDEF COMPILER6_UP}
|
|
else
|
|
Result := False;
|
|
{$ENDIF COMPILER6_UP}
|
|
end;
|
|
end;
|
|
|
|
function TJvID3FramesEditor.ForEachSelection(Proc: TSelectionProc): Boolean;
|
|
var
|
|
Frame: TJvID3Frame;
|
|
I: Integer;
|
|
begin
|
|
Result := False;
|
|
with FrameListBox do
|
|
for I := 0 to Items.Count - 1 do
|
|
if Selected[I] then
|
|
begin
|
|
Frame := TJvID3Frame(Items.Objects[I]);
|
|
if (Frame <> nil) and not Proc(Frame) then
|
|
Exit;
|
|
end;
|
|
Result := True;
|
|
end;
|
|
|
|
{$IFDEF COMPILER6_UP}
|
|
procedure TJvID3FramesEditor.ItemDeleted(const ADesigner: IDesigner; AItem: TPersistent);
|
|
begin
|
|
if AItem = Controller then
|
|
Controller := nil
|
|
else
|
|
if (AItem is TJvID3Frame) and (TJvID3Frame(AItem).Controller = Controller) then
|
|
UpdateDisplay;
|
|
end;
|
|
{$ENDIF COMPILER6_UP}
|
|
|
|
{$IFDEF COMPILER6_UP}
|
|
procedure TJvID3FramesEditor.ItemsModified(const Designer: IDesigner);
|
|
{$ELSE}
|
|
procedure TJvID3FramesEditor.FormModified;
|
|
{$ENDIF COMPILER6_UP}
|
|
begin
|
|
UpdateCaption;
|
|
end;
|
|
|
|
procedure TJvID3FramesEditor.MoveFrames(MoveOffset: Integer);
|
|
var
|
|
I, E: Integer;
|
|
begin
|
|
try
|
|
FFSDesigner.BeginDesign;
|
|
try
|
|
with FrameListBox do
|
|
begin
|
|
I := 0;
|
|
E := Items.Count;
|
|
if MoveOffset > 0 then
|
|
begin
|
|
I := E - 1;
|
|
E := -1;
|
|
end;
|
|
while I <> E do
|
|
begin
|
|
if Selected[I] then
|
|
with TJvID3Frame(Items.Objects[I]) do
|
|
Index := Index + MoveOffset;
|
|
Inc(I, -MoveOffset);
|
|
end;
|
|
end;
|
|
finally
|
|
FFSDesigner.EndDesign;
|
|
end;
|
|
finally
|
|
UpdateDisplay;
|
|
Designer.Modified;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvID3FramesEditor.RemoveFrames;
|
|
var
|
|
I, Focused: Integer;
|
|
begin
|
|
try
|
|
FFSDesigner.BeginDesign;
|
|
try
|
|
Focused := FrameListBox.ItemIndex;
|
|
with FrameListBox do
|
|
for I := Items.Count - 1 downto 0 do
|
|
if Selected[I] then
|
|
TJvID3Frame(Items.Objects[I]).Free;
|
|
finally
|
|
FFSDesigner.EndDesign;
|
|
Designer.Modified;
|
|
end;
|
|
finally
|
|
UpdateDisplay;
|
|
end;
|
|
if Focused <> -1 then
|
|
begin
|
|
Focused := Min(Focused, FrameListBox.Items.Count - 1);
|
|
FrameListBox.ItemIndex := Focused;
|
|
FrameListBox.Selected[Focused] := True;
|
|
UpdateSelection;
|
|
end;
|
|
FrameListBox.SetFocus;
|
|
end;
|
|
|
|
procedure TJvID3FramesEditor.RestoreSelection(var Selection: TStringList;
|
|
ItemIndex, TopIndex: Integer; RestoreUpdate: Boolean);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
try
|
|
with FrameListBox do
|
|
for I := 0 to Items.Count - 1 do
|
|
Selected[I] := Selection.IndexOf(TComponent(Items.Objects[I]).Name) <> -1;
|
|
if TopIndex <> -1 then
|
|
FrameListBox.TopIndex := TopIndex;
|
|
if ItemIndex <> -1 then
|
|
FrameListBox.ItemIndex := ItemIndex;
|
|
finally
|
|
if RestoreUpdate then
|
|
FrameListBox.Items.EndUpdate;
|
|
FrameListBox.Invalidate;
|
|
Selection.Free;
|
|
Selection := nil;
|
|
UpdateSelection;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvID3FramesEditor.SaveSelection(var Selection: TStringList;
|
|
var ItemIndex, TopIndex: Integer; NoUpdate: Boolean);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
{ Name of a frame is unique, thus fill Selection with these names
|
|
of frames that are selected }
|
|
Selection := TStringList.Create;
|
|
try
|
|
ItemIndex := FrameListBox.ItemIndex;
|
|
TopIndex := FrameListBox.TopIndex;
|
|
with FrameListBox do
|
|
for I := 0 to Items.Count - 1 do
|
|
if Selected[I] then
|
|
Selection.Add(TComponent(Items.Objects[I]).Name);
|
|
if NoUpdate then
|
|
FrameListBox.Items.BeginUpdate;
|
|
except
|
|
Selection.Free;
|
|
Selection := nil;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvID3FramesEditor.SelectAll;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
with FrameListBox do
|
|
for I := 0 to Items.Count - 1 do
|
|
Selected[I] := True;
|
|
end;
|
|
|
|
{$IFDEF COMPILER6_UP}
|
|
procedure TJvID3FramesEditor.SelectionChanged(const ADesigner: IDesigner;
|
|
const ASelection: IDesignerSelections);
|
|
{$ELSE}
|
|
procedure TJvID3FramesEditor.SelectionChanged(ASelection: TDesignerSelectionList);
|
|
{$ENDIF COMPILER6_UP}
|
|
var
|
|
I: Integer;
|
|
S: Boolean;
|
|
|
|
function InSelection(Component: TComponent): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Result := True;
|
|
if ASelection <> nil then
|
|
with ASelection do
|
|
for I := 0 to Count - 1 do
|
|
if Component = Items[I] then
|
|
Exit;
|
|
Result := False;
|
|
end;
|
|
|
|
begin
|
|
with FrameListBox do
|
|
for I := 0 to Items.Count - 1 do
|
|
begin
|
|
S := InSelection(TComponent(Items.Objects[I]));
|
|
if Selected[I] <> S then
|
|
Selected[I] := S;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvID3FramesEditor.SetController(Value: TJvID3Controller);
|
|
begin
|
|
if FController <> Value then
|
|
begin
|
|
if FController <> nil then
|
|
FreeAndNil(FFSDesigner);
|
|
FController := Value;
|
|
if FController <> nil then
|
|
begin
|
|
FFSDesigner := TFSDesigner.Create(Value);
|
|
FFSDesigner.FFramesEditor := Self;
|
|
UpdateDisplay;
|
|
end
|
|
else
|
|
begin
|
|
if not (csDestroying in ComponentState) then
|
|
Release;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TJvID3FramesEditor.UniqueName(Component: TComponent): string;
|
|
var
|
|
FrameName: string;
|
|
begin
|
|
if Component is TJvID3Frame then
|
|
FrameName := TJvID3Frame(Component).FrameName
|
|
else
|
|
FrameName := '';
|
|
Result := CreateUniqueName(Controller, FrameName,
|
|
TJvID3FrameClass(Component.ClassType), Component)
|
|
end;
|
|
|
|
procedure TJvID3FramesEditor.UpdateCaption;
|
|
const
|
|
cFrameEditor = '%s%s%s';
|
|
var
|
|
NewCaption: string;
|
|
begin
|
|
if (Controller <> nil) and (Controller.Owner <> nil) then
|
|
NewCaption := Format(cFrameEditor,
|
|
[Controller.Owner.Name, '.', Controller.Name]);
|
|
if Caption <> NewCaption then
|
|
Caption := NewCaption;
|
|
end;
|
|
|
|
procedure TJvID3FramesEditor.UpdateDisplay;
|
|
begin
|
|
UpdateFrameList;
|
|
UpdateCaption;
|
|
UpdateSelection;
|
|
end;
|
|
|
|
procedure TJvID3FramesEditor.UpdateFrameList;
|
|
var
|
|
ItemIndex, TopIndex: Integer;
|
|
Selection: TStringList;
|
|
EnableList: Boolean;
|
|
I: Integer;
|
|
Frame: TJvID3Frame;
|
|
FrameName: string;
|
|
begin
|
|
SaveSelection(Selection, ItemIndex, TopIndex, True);
|
|
try
|
|
FrameListBox.Clear;
|
|
EnableList := False;
|
|
try
|
|
if Controller = nil then
|
|
Exit;
|
|
for I := 0 to Controller.Frames.Count - 1 do
|
|
begin
|
|
Frame := Controller.Frames[I];
|
|
if not (csDestroying in Frame.ComponentState) then
|
|
begin
|
|
FrameName := Frame.FrameName;
|
|
if FrameName = '' then
|
|
FrameName := Format('<%s>', [Controller.Frames[I].Name]);
|
|
FrameName := FrameName + ' - ' + cFrameDescriptions[Frame.FrameID];
|
|
FrameListBox.Items.AddObject(FrameName, Frame);
|
|
end;
|
|
end;
|
|
|
|
EnableList := True;
|
|
finally
|
|
FrameListBox.Enabled := EnableList;
|
|
end;
|
|
finally
|
|
RestoreSelection(Selection, ItemIndex, TopIndex, True)
|
|
end;
|
|
end;
|
|
|
|
procedure TJvID3FramesEditor.UpdateSelection;
|
|
var
|
|
I: Integer;
|
|
Frame: TJvID3Frame;
|
|
{$IFDEF COMPILER6_UP}
|
|
ComponentList: IDesignerSelections;
|
|
{$ELSE}
|
|
ComponentList: TDesignerSelectionList;
|
|
{$ENDIF COMPILER6_UP}
|
|
begin
|
|
if Active then
|
|
begin
|
|
{$IFDEF COMPILER6_UP}
|
|
ComponentList := TDesignerSelections.Create;
|
|
{$ELSE}
|
|
ComponentList := TDesignerSelectionList.Create;
|
|
{$ENDIF COMPILER6_UP}
|
|
try
|
|
with FrameListBox do
|
|
for I := 0 to Items.Count - 1 do
|
|
if Selected[I] then
|
|
begin
|
|
Frame := TJvID3Frame(Items.Objects[I]);
|
|
if Frame <> nil then
|
|
ComponentList.Add(Frame);
|
|
end;
|
|
if ComponentList.Count = 0 then
|
|
ComponentList.Add(Controller);
|
|
except
|
|
{$IFDEF COMPILER5}
|
|
// In D6 up it's an interface, so no need to free up
|
|
ComponentList.Free;
|
|
{$ENDIF COMPILER5}
|
|
raise;
|
|
end;
|
|
{$IFDEF COMPILER5}
|
|
SetSelection(ComponentList);
|
|
{$ELSE}
|
|
Designer.SetSelections(ComponentList);
|
|
{$ENDIF COMPILER5}
|
|
end;
|
|
end;
|
|
|
|
procedure TJvID3FramesEditor.WMGetMinMaxInfo(var Msg: TWMGetMinMaxInfo);
|
|
begin
|
|
inherited;
|
|
with Msg.MinMaxInfo^.ptMinTrackSize do
|
|
begin
|
|
X := FMinWidth;
|
|
Y := FMinHeight;
|
|
end;
|
|
end;
|
|
|
|
//=== { TJvID3ControllerEditor } =============================================
|
|
|
|
procedure TJvID3ControllerEditor.Commit;
|
|
begin
|
|
if MessageDlg(RsCommit, mtConfirmation, mbOKCancel, 0) = mrOk then
|
|
TJvID3Controller(Component).Commit;
|
|
end;
|
|
|
|
procedure TJvID3ControllerEditor.ExecuteVerb(Index: Integer);
|
|
begin
|
|
case Index of
|
|
0:
|
|
ShowFramesEditor(Designer, TJvID3Controller(Component));
|
|
1:
|
|
RemoveTag;
|
|
2:
|
|
ShowFileInfo(TJvID3Controller(Component));
|
|
3:
|
|
Commit;
|
|
end;
|
|
end;
|
|
|
|
function TJvID3ControllerEditor.GetVerb(Index: Integer): string;
|
|
begin
|
|
case Index of
|
|
0:
|
|
Result := RSID3FrameEditorTag;
|
|
1:
|
|
Result := RSID3RemoveTag;
|
|
2:
|
|
Result := RSID3FileInfoTag;
|
|
3:
|
|
Result := RSID3CommitTag;
|
|
end;
|
|
end;
|
|
|
|
function TJvID3ControllerEditor.GetVerbCount: Integer;
|
|
begin
|
|
Result := 3;
|
|
|
|
with TJvID3Controller(Component) do
|
|
if Active and Modified then
|
|
Inc(Result);
|
|
end;
|
|
|
|
procedure TJvID3FramesEditor.FormCreate(Sender: TObject);
|
|
begin
|
|
FMinWidth := Width;
|
|
FMinHeight := Height;
|
|
end;
|
|
|
|
procedure TJvID3ControllerEditor.RemoveTag;
|
|
begin
|
|
with TJvID3Controller(Component) do
|
|
begin
|
|
if FileName = '' then
|
|
begin
|
|
MessageDlg(RsID3Err_NoFileSpecified, mtError, [mbOK], 0);
|
|
Exit;
|
|
end;
|
|
|
|
if not FileExists(FileName) then
|
|
begin
|
|
MessageDlg(Format(RSID3Err_FileDoesNotExists, [FileName]), mtError, [mbOK], 0);
|
|
Exit;
|
|
end;
|
|
|
|
if MessageDlg(RSID3RemoveTagConfirmation, mtConfirmation, mbOKCancel, 0) = mrOk then
|
|
Erase;
|
|
end;
|
|
end;
|
|
|
|
//=== { TFSDesigner } ========================================================
|
|
|
|
destructor TFSDesigner.Destroy;
|
|
var
|
|
F: TJvID3FramesEditor;
|
|
begin
|
|
if FFramesEditor <> nil then
|
|
begin
|
|
F := FFramesEditor;
|
|
FFramesEditor := nil;
|
|
F.FFSDesigner := nil;
|
|
{ (rb) DSDesign.pas uses Release, but that gave problems, with recompiling }
|
|
F.Free;
|
|
end;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TJvID3FramesEditor.ListBoxClick(Sender: TObject);
|
|
begin
|
|
UpdateSelection;
|
|
end;
|
|
|
|
function TFSDesigner.GetFrameDescription(const FrameID: TJvID3FrameID): string;
|
|
begin
|
|
Result := cFrameDescriptions[FrameID];
|
|
end;
|
|
|
|
procedure TFSDesigner.ID3Event(Event: TJvID3Event; Info: Longint);
|
|
begin
|
|
if Event in [ideFrameListChange, ideID3Change] then
|
|
FFramesEditor.UpdateFrameList;
|
|
end;
|
|
|
|
procedure TJvID3FramesEditor.ListBoxKeyDown(Sender: TObject; var Key: Word;
|
|
Shift: TShiftState);
|
|
begin
|
|
case Key of
|
|
VK_INSERT:
|
|
NewFrameClick(Self);
|
|
VK_DELETE:
|
|
RemoveFrames;
|
|
VK_UP:
|
|
if (ssCtrl in Shift) and (Sender = FrameListBox) then
|
|
MoveFrames(-1)
|
|
else
|
|
Exit;
|
|
VK_DOWN:
|
|
if (ssCtrl in Shift) and (Sender = FrameListBox) then
|
|
MoveFrames(1)
|
|
else
|
|
Exit;
|
|
else
|
|
Exit;
|
|
end;
|
|
Key := 0;
|
|
end;
|
|
|
|
procedure TJvID3FramesEditor.ListBoxDragDrop(Sender, Source: TObject;
|
|
X, Y: Integer);
|
|
var
|
|
F: TJvID3Frame;
|
|
I: Integer;
|
|
begin
|
|
try
|
|
FFSDesigner.BeginDesign;
|
|
try
|
|
with FrameListBox do
|
|
begin
|
|
F := TJvID3Frame(Items.Objects[ItemAtPos(Point(X, Y), True)]);
|
|
for I := 0 to Items.Count - 1 do
|
|
if Selected[I] then
|
|
TJvID3Frame(Items.Objects[I]).Index := F.Index;
|
|
end;
|
|
finally
|
|
FFSDesigner.EndDesign;
|
|
end;
|
|
finally
|
|
UpdateDisplay;
|
|
Designer.Modified;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvID3FramesEditor.ListBoxDragOver(Sender, Source: TObject;
|
|
X, Y: Integer; State: TDragState; var Accept: Boolean);
|
|
var
|
|
Item: Integer;
|
|
|
|
procedure DrawRect(Item: Integer);
|
|
begin
|
|
if Item <> -1 then
|
|
with FrameListBox do
|
|
Canvas.DrawFocusRect(ItemRect(Item));
|
|
FFocusRectItem := Item;
|
|
end;
|
|
|
|
begin
|
|
Item := FrameListBox.ItemAtPos(Point(X, Y), False);
|
|
Accept := (Source = FrameListBox) and
|
|
(Item >= 0) and (Item < FrameListBox.Items.Count) and
|
|
not FrameListBox.Selected[Item];
|
|
if State = dsDragEnter then
|
|
FFocusRectItem := -1;
|
|
if (State = dsDragLeave) or not Accept then
|
|
Item := -1;
|
|
DrawRect(FFocusRectItem);
|
|
DrawRect(Item);
|
|
end;
|
|
|
|
procedure TJvID3FramesEditor.FormDestroy(Sender: TObject);
|
|
begin
|
|
if FFSDesigner <> nil then
|
|
begin
|
|
{ Destroy the designer if the editor is destroyed }
|
|
FFSDesigner.FFramesEditor := nil;
|
|
FFSDesigner.Free;
|
|
FFSDesigner := nil;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvID3FramesEditor.NewFrameClick(Sender: TObject);
|
|
var
|
|
Selection: TStringList;
|
|
Frame: TJvID3Frame;
|
|
begin
|
|
Frame := DoNewFrame;
|
|
if Frame <> nil then
|
|
begin
|
|
Selection := TStringList.Create;
|
|
try
|
|
Selection.Add(Frame.Name);
|
|
finally
|
|
RestoreSelection(Selection, -1, -1, False);
|
|
end;
|
|
end;
|
|
FrameListBox.SetFocus;
|
|
end;
|
|
|
|
procedure TJvID3FramesEditor.DeleteClick(Sender: TObject);
|
|
begin
|
|
RemoveFrames;
|
|
end;
|
|
|
|
procedure TJvID3FramesEditor.SelectAllClick(Sender: TObject);
|
|
begin
|
|
SelectAll;
|
|
UpdateSelection;
|
|
end;
|
|
|
|
//=== { TJvID3FileInfoEditor } ===============================================
|
|
|
|
procedure TJvID3FileInfoEditor.Edit;
|
|
var
|
|
P: TPersistent;
|
|
begin
|
|
P := TPersistent(GetComponent(0));
|
|
if P is TJvID3Controller then
|
|
ShowFileInfo(TJvID3Controller(P));
|
|
end;
|
|
|
|
function TJvID3FileInfoEditor.GetAttributes: TPropertyAttributes;
|
|
begin
|
|
Result := [paDialog];
|
|
end;
|
|
|
|
end.
|
|
|