unit Translate; { [Translate] [1.1] Delphi 2005 December 2005 LICENSE The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at "http://www.mozilla.org/MPL/" Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language governing rights and limitations under the License. The Original Code is "[translate.pas]". The Initial Developer of the Original Code is Martin Holmes (Victoria, BC, Canada, "http://www.mholmes.com/"). Copyright (C) 2005 Martin Holmes and the University of Victoria Computing and Media Centre. The code was co-developed for university and personal projects, and rights are shared by Martin Holmes and the University of Victoria. All Rights Reserved. } { Written by Martin Holmes, Fall 2005. This form, along with the associated mdhTranslate library, provides introspection for the application, exposing its strings (in the form of control captions, hints etc.) for translation into another language. It uses a TVirtualTreeView as its core control. Dependencies: VirtualTreeView (Mike Lischke) TntUnicodeControls (Troy Wolbrink) FormState for saving size/position etc. } interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, TntForms, StdCtrls, TntStdCtrls, ComCtrls, TntComCtrls, TntMenus, TypInfo, VirtualTrees, VersionInfo, mdhTranslate, ExtCtrls, TntExtCtrls, TntDialogs, AppEvnts, Buttons, TntButtons, FormState, StdActns, ActnList, TntActnList, ImgList, Menus, ToolWin, TntSysUtils, Clipbrd, IconsIncluder; //This is the record used to point to the full class type TufrmTranslate = class(TTntForm) aeTranslate: TApplicationEvents; utbrTranslate: TTntToolBar; umnuTranslate: TTntMainMenu; upnEditing: TTntPanel; umsgItemTextModified: TTntLabel; ugbCurrentItem: TTntGroupBox; ustItemHint: TTntStaticText; ustItemCaption: TTntStaticText; ubnCancel: TTntBitBtn; umCaption: TTntMemo; ubnSaveChanges: TTntBitBtn; uspTranslate: TTntSplitter; upnVSTTranslate: TTntPanel; vstTranslate: TVirtualStringTree; umnFile: TTntMenuItem; umnEdit: TTntMenuItem; umnUndo: TTntMenuItem; N1: TTntMenuItem; mnuCut: TTntMenuItem; mnuCopy: TTntMenuItem; mnuPaste: TTntMenuItem; mnuDelete: TTntMenuItem; N2: TTntMenuItem; mnuSelectAll: TTntMenuItem; utbSep1: TTntToolButton; utbUndo: TTntToolButton; utbCut: TTntToolButton; utbCopy: TTntToolButton; utbPaste: TTntToolButton; utbDelete: TTntToolButton; utbSelectAll: TTntToolButton; umsgSaveInterfaceChanges: TTntLabel; udlgSaveTranslation: TTntSaveDialog; umTitle: TTntMemo; ustItemTitle: TTntStaticText; ualTranslate: TTntActionList; aNewTranslation: TTntAction; aOpenTranslation: TTntAction; aSaveTranslation: TTntAction; aSaveAsTranslation: TTntAction; udlgLoadTranslation: TTntOpenDialog; utbNewTranslation: TTntToolButton; utnOpenTranslation: TTntToolButton; utbSaveTranslation: TTntToolButton; utbSaveAsTranslation: TTntToolButton; umnNewTranslation: TTntMenuItem; umnOpenTranslation: TTntMenuItem; umnSaveTranslation: TTntMenuItem; umnSaveAsTranslation: TTntMenuItem; umsgUnableToReadTranslationFile: TTntStaticText; uedSearchString: TTntEdit; ubnFind: TTntBitBtn; ubnFindNext: TTntBitBtn; aFindNext: TTntAction; aFind: TTntAction; umHint: TTntMemo; aEditUndo: TTntAction; aEditCut: TTntAction; aEditCopy: TTntAction; aEditPaste: TTntAction; aEditDelete: TTntAction; aEditSelectAll: TTntAction; aSaveItemChanges: TTntAction; aCancelChanges: TTntAction; aCloseWindow: TTntAction; utbSep2: TTntToolButton; utbClose: TTntToolButton; N3: TTntMenuItem; umnCloseWindow: TTntMenuItem; procedure aCloseWindowExecute(Sender: TObject); procedure TntFormCloseQuery(Sender: TObject; var CanClose: Boolean); procedure aCancelChangesExecute(Sender: TObject); procedure aSaveItemChangesExecute(Sender: TObject); procedure aEditSelectAllExecute(Sender: TObject); procedure aEditDeleteExecute(Sender: TObject); procedure aEditPasteExecute(Sender: TObject); procedure aEditCopyExecute(Sender: TObject); procedure aEditCutExecute(Sender: TObject); procedure aEditUndoExecute(Sender: TObject); procedure aFindNextExecute(Sender: TObject); procedure uedSearchStringChange(Sender: TObject); procedure aFindExecute(Sender: TObject); procedure aSaveAsTranslationExecute(Sender: TObject); procedure aSaveTranslationExecute(Sender: TObject); procedure aOpenTranslationExecute(Sender: TObject); procedure aNewTranslationExecute(Sender: TObject); procedure upnEditingDblClick(Sender: TObject); procedure umHintChange(Sender: TObject); procedure aeTranslateIdle(Sender: TObject; var Done: Boolean); procedure vstTranslateFocusChanging(Sender: TBaseVirtualTree; OldNode, NewNode: PVirtualNode; OldColumn, NewColumn: TColumnIndex; var Allowed: Boolean); procedure vstTranslateFocusChanged(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex); procedure TntFormShow(Sender: TObject); procedure TntFormDestroy(Sender: TObject); procedure TntFormCreate(Sender: TObject); procedure vstTranslateGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; var CellText: WideString); procedure vstTranslateGetNodeDataSize(Sender: TBaseVirtualTree; var NodeDataSize: Integer); private ComponentPath: string; FVersionInfo: TAppVersionInfo; NodeDataModified: Boolean; FFormStateSaver: TFormStateSaver; procedure DisplayNode(NodeToDisplay: PVirtualNode); procedure StashNode(NodeToStash: PVirtualNode); function Save: Boolean; function SaveChanges: Boolean; function SaveAs: Boolean; procedure ClearTextBoxes; { Private declarations } public AppRef: TAppReflection; CurrFileName: WideString; Modified: Boolean; { Public declarations } end; var ufrmTranslate: TufrmTranslate; implementation {$R *.dfm} procedure TufrmTranslate.vstTranslateGetNodeDataSize(Sender: TBaseVirtualTree; var NodeDataSize: Integer); begin NodeDataSize := SizeOf(rComponentReflection); end; procedure TufrmTranslate.vstTranslateGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; var CellText: WideString); var NodeRec: ^rComponentReflection; begin NodeRec := Sender.GetNodeData(Node); if NodeRec.CompRef = nil then CellText := 'nil' else CellText := NodeRec.CompRef.Name; end; procedure TufrmTranslate.TntFormCreate(Sender: TObject); var TranslationDir: WideString; begin Icon := Application.Icon; FVersionInfo := TAppVersionInfo.Create; CurrFileName := ''; Modified := False; TranslationDir := WideExtractFilePath(Application.ExeName) + 'translations\'; udlgLoadTranslation.InitialDir := TranslationDir; udlgSaveTranslation.InitialDir := TranslationDir; end; procedure TufrmTranslate.TntFormDestroy(Sender: TObject); begin AppRef.Free; FreeAndNil(FVersionInfo); FreeAndNil(FFormStateSaver); end; procedure TufrmTranslate.TntFormShow(Sender: TObject); begin FFormStateSaver := TFormStateSaver.Create(Self, True, True, True, False, False, False, False, False, True); AppRef := TAppReflection.Create; AppRef.VST := vstTranslate; AppRef.WriteToVST; ClearTextBoxes; end; procedure TufrmTranslate.vstTranslateFocusChanged(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex); begin if Node <> nil then DisplayNode(Node); end; procedure TufrmTranslate.DisplayNode(NodeToDisplay: PVirtualNode); var NodeRec: ^rComponentReflection; begin if NodeToDisplay <> nil then begin NodeRec := vstTranslate.GetNodeData(NodeToDisplay); with TComponentReflection(NodeRec.CompRef) do begin umHint.Text := Hint; umCaption.Text := Caption; umTitle.Text := Title; umHint.Enabled := HasHint; umCaption.Enabled := HasCaption; umTitle.Enabled := HasTitle; ustItemHint.Enabled := HasHint; ustItemCaption.Enabled := HasCaption; ustItemTitle.Enabled := HasTitle; end; end; NodeDataModified := False; end; procedure TufrmTranslate.StashNode(NodeToStash: PVirtualNode); var NodeRec: ^rComponentReflection; begin if NodeToStash <> nil then begin NodeRec := vstTranslate.GetNodeData(NodeToStash); with TComponentReflection(NodeRec.CompRef) do begin Hint := umHint.Text; Caption := umCaption.Text; Title := umTitle.Text; Modified := True; end; end; NodeDataModified := False; end; procedure TufrmTranslate.vstTranslateFocusChanging(Sender: TBaseVirtualTree; OldNode, NewNode: PVirtualNode; OldColumn, NewColumn: TColumnIndex; var Allowed: Boolean); begin if NodeDataModified = True then begin WideShowMessage(umsgItemTextModified.Caption); Allowed := False; end; end; procedure TufrmTranslate.aeTranslateIdle(Sender: TObject; var Done: Boolean); var IsEdit: Boolean; HasSelection: Boolean; HasText: Boolean; boolCanUndo: Boolean; begin ubnSaveChanges.Enabled := NodeDataModified; ubnCancel.Enabled := NodeDataModified; aFind.Enabled := (Length(uedSearchString.Text) > 0) and not NodeDataModified; if NodeDataModified then aFindNext.Enabled := False; IsEdit := ((ActiveControl is TTntEdit) or (ActiveControl is TTntMemo)); if IsEdit then begin if (ActiveControl is TTntEdit) then with (ActiveControl as TTntEdit) do begin HasSelection := (SelLength > 0); boolCanUndo := CanUndo; HasText := (Length(Text) > 0); end; if (ActiveControl is TTntMemo) then with (ActiveControl as TTntMemo) do begin HasSelection := (SelLength > 0); boolCanUndo := CanUndo; HasText := (Length(Text) > 0); end; aEditUndo.Enabled := boolCanUndo; aEditCut.Enabled := HasSelection; aEditCopy.Enabled := HasSelection; aEditPaste.Enabled := Clipboard.HasFormat(CF_TEXT); aEditDelete.Enabled := HasSelection; aEditSelectAll.Enabled := HasText; end else begin aEditUndo.Enabled := False; aEditCut.Enabled := False; aEditCopy.Enabled := False; aEditPaste.Enabled := False; aEditDelete.Enabled := False; aEditSelectAll.Enabled := False; end; end; procedure TufrmTranslate.umHintChange(Sender: TObject); begin NodeDataModified := True; end; procedure TufrmTranslate.upnEditingDblClick(Sender: TObject); begin // AppRef.WriteToGUI; // SetWideStrProp(TObject(umnFile), 'caption', 'Test'); end; function TufrmTranslate.SaveChanges: Boolean; var Response: integer; begin Result := False;//default Response := WideMessageDlg(umsgSaveInterfaceChanges.Caption, mtConfirmation, mbYesNoCancel, 0); case Response of mrYes: Result := Save; mrNo: Result := True; mrCancel: Result := False; end; end; function TufrmTranslate.SaveAs: Boolean; begin Result := False; //default if udlgSaveTranslation.Execute then begin CurrFileName := udlgSaveTranslation.FileName; try AppRef.WriteToXMLFile(CurrFileName); Result := True; Modified := False; except end; end; end; function TufrmTranslate.Save: Boolean; begin Result := False;//default if FileExists(CurrFileName) then begin try AppRef.WriteToXMLFile(CurrFileName); Modified := False; Result := True; except end; end else Result := SaveAs; end; procedure TufrmTranslate.aNewTranslationExecute(Sender: TObject); begin if not Modified or SaveChanges then begin CurrFileName := ''; //Just destroy and recreate the AppRef object, and it will be refreshed //from the GUI AppRef.Free; AppRef := TAppReflection.Create; AppRef.VST := vstTranslate; AppRef.WriteToVST; ClearTextBoxes; Modified := False; end; end; procedure TufrmTranslate.aOpenTranslationExecute(Sender: TObject); begin if not Modified or SaveChanges then begin if udlgLoadTranslation.Execute then begin try AppRef.ReadFromXMLFile(udlgLoadTranslation.FileName); except WideMessageDlg(umsgUnableToReadTranslationFile.Caption, mtWarning, [mbOK], 0); Exit; end; CurrFileName := udlgLoadTranslation.FileName; AppRef.WriteToVST; ClearTextBoxes; Modified := False; end; end; end; procedure TufrmTranslate.aSaveTranslationExecute(Sender: TObject); begin Save; end; procedure TufrmTranslate.aSaveAsTranslationExecute(Sender: TObject); begin if FileExists(CurrFileName) then udlgSaveTranslation.FileName := CurrFileName; if udlgSaveTranslation.Execute then begin try AppRef.WriteToXMLFile(udlgSaveTranslation.FileName); except Exit; end; CurrFileName := udlgSaveTranslation.FileName; Modified := False; end; end; procedure TufrmTranslate.ClearTextBoxes; begin umHint.Text := ''; umCaption.Text := ''; umTitle.Text := ''; umHint.Enabled := False; ustItemHint.Enabled := False; umCaption.Enabled := False; ustItemCaption.Enabled := False; umTitle.Enabled := False; ustItemTitle.Enabled := False; NodeDataModified := False; end; procedure TufrmTranslate.aFindExecute(Sender: TObject); var CompRef: TComponentReflection; begin CompRef := AppRef.Find(uedSearchString.Text); if CompRef <> nil then begin vstTranslate.FocusedNode := CompRef.PVSTNode; vstTranslate.Selected[CompRef.PVSTNode] := True; aFindNext.Enabled := True; end; end; procedure TufrmTranslate.uedSearchStringChange(Sender: TObject); begin aFindNext.Enabled := False; end; procedure TufrmTranslate.aFindNextExecute(Sender: TObject); var CompRef: TComponentReflection; begin CompRef := AppRef.FindNext(uedSearchString.Text); if CompRef <> nil then begin vstTranslate.FocusedNode := CompRef.PVSTNode; vstTranslate.Selected[CompRef.PVSTNode] := True; end; end; procedure TufrmTranslate.aEditUndoExecute(Sender: TObject); begin if ActiveControl is TTntEdit then (ActiveControl as TTntEdit).Perform(EM_UNDO, 0, 0); if ActiveControl is TTntMemo then (ActiveControl as TTntMemo).Perform(EM_UNDO, 0, 0); end; procedure TufrmTranslate.aEditCutExecute(Sender: TObject); begin if ActiveControl is TTntEdit then (ActiveControl as TTntEdit).CutToClipboard; if ActiveControl is TTntMemo then (ActiveControl as TTntMemo).CutToClipboard; end; procedure TufrmTranslate.aEditCopyExecute(Sender: TObject); begin if ActiveControl is TTntEdit then (ActiveControl as TTntEdit).CopyToClipboard; if ActiveControl is TTntMemo then (ActiveControl as TTntMemo).CopyToClipboard; end; procedure TufrmTranslate.aEditPasteExecute(Sender: TObject); begin if ActiveControl is TTntEdit then (ActiveControl as TTntEdit).PasteFromClipboard; if ActiveControl is TTntMemo then (ActiveControl as TTntMemo).PasteFromClipboard; end; procedure TufrmTranslate.aEditDeleteExecute(Sender: TObject); begin if ActiveControl is TTntEdit then (ActiveControl as TTntEdit).SelText := ''; if ActiveControl is TTntMemo then (ActiveControl as TTntMemo).SelText := ''; end; procedure TufrmTranslate.aEditSelectAllExecute(Sender: TObject); begin if ActiveControl is TTntEdit then (ActiveControl as TTntEdit).SelectAll; if ActiveControl is TTntMemo then (ActiveControl as TTntMemo).SelectAll; end; procedure TufrmTranslate.aSaveItemChangesExecute(Sender: TObject); begin StashNode(vstTranslate.FocusedNode); end; procedure TufrmTranslate.aCancelChangesExecute(Sender: TObject); begin DisplayNode(vstTranslate.FocusedNode); end; procedure TufrmTranslate.TntFormCloseQuery(Sender: TObject; var CanClose: Boolean); begin CanClose := (not Modified) or (SaveChanges); end; procedure TufrmTranslate.aCloseWindowExecute(Sender: TObject); begin Close; end; end.