unit fTemplateEditor; {The OwnerScan conditional compile varaible was created because there were too many things that needed to be done to incorporate the viewing of other user's personal templates by clinical coordinators. These include: Changing the Personal tree. expanding entirely new personal list when personal list changes when click on stop editing shared button, and personal is for someone else, need to resync to personal list. HOT HEYS NOT YET ASSIGNED: JFKQRUVZ } {$DEFINE OwnerScan} {$UNDEF OwnerScan} interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, StdCtrls, ComCtrls, ORCtrls, Buttons, Mask, ORFn, ORNet, uTemplates, Menus, ImgList, Clipbrd, ToolWin, MenuBar, TypInfo, MSXML_TLB; type TTemplateTreeControl = (tcDel, tcUp, tcDown, tcLbl, tcCopy); TTemplateTreeType = (ttShared, ttPersonal); TfrmTemplateEditor = class(TForm) splMain: TSplitter; pnlBottom: TORAutoPanel; btnApply: TButton; btnCancel: TButton; btnOK: TButton; pnlBoilerplate: TPanel; reBoil: TRichEdit; pnlTop: TPanel; pnlRightTop: TPanel; splProperties: TSplitter; pnlCopyBtns: TPanel; sbCopyLeft: TBitBtn; sbCopyRight: TBitBtn; lblCopy: TLabel; splMiddle: TSplitter; pnlShared: TPanel; lblShared: TLabel; tvShared: TORTreeView; pnlSharedBottom: TPanel; sbShUp: TBitBtn; sbShDown: TBitBtn; sbShDelete: TBitBtn; cbShHide: TCheckBox; pnlSharedGap: TPanel; pnlPersonal: TPanel; lblPersonal: TLabel; tvPersonal: TORTreeView; pnlPersonalBottom: TPanel; sbPerUp: TBitBtn; sbPerDown: TBitBtn; sbPerDelete: TBitBtn; cbPerHide: TCheckBox; pnlPersonalGap: TPanel; popTemplates: TPopupMenu; mnuCollapseTree: TMenuItem; mnuFindTemplates: TMenuItem; popBoilerplate: TPopupMenu; mnuBPInsertObject: TMenuItem; mnuBPErrorCheck: TMenuItem; mnuBPSpellCheck: TMenuItem; pnlGroupBP: TPanel; reGroupBP: TRichEdit; lblGroupBP: TLabel; splBoil: TSplitter; pnlGroupBPGap: TPanel; tmrAutoScroll: TTimer; popGroup: TPopupMenu; mnuGroupBPCopy: TMenuItem; mnuBPCut: TMenuItem; N2: TMenuItem; mnuBPCopy: TMenuItem; mnuBPPaste: TMenuItem; N4: TMenuItem; mnuGroupBPSelectAll: TMenuItem; mnuBPSelectAll: TMenuItem; N6: TMenuItem; mnuNodeCopy: TMenuItem; mnuNodePaste: TMenuItem; mnuNodeDelete: TMenuItem; N8: TMenuItem; mnuBPUndo: TMenuItem; cbEditShared: TCheckBox; pnlProperties: TPanel; gbProperties: TGroupBox; lblName: TLabel; lblLines: TLabel; cbExclude: TORCheckBox; cbActive: TCheckBox; edtGap: TCaptionEdit; udGap: TUpDown; edtName: TCaptionEdit; mnuMain: TMainMenu; mnuEdit: TMenuItem; mnuUndo: TMenuItem; N9: TMenuItem; mnuCut: TMenuItem; mnuCopy: TMenuItem; mnuPaste: TMenuItem; mnuSelectAll: TMenuItem; N11: TMenuItem; mnuInsertObject: TMenuItem; mnuErrorCheck: TMenuItem; mnuSpellCheck: TMenuItem; N13: TMenuItem; mnuGroupBoilerplate: TMenuItem; mnuGroupCopy: TMenuItem; mnuGroupSelectAll: TMenuItem; mnuTemplate: TMenuItem; mnuTCopy: TMenuItem; mnuTPaste: TMenuItem; mnuTDelete: TMenuItem; N12: TMenuItem; pnlShSearch: TPanel; btnShFind: TORAlignButton; edtShSearch: TCaptionEdit; cbShMatchCase: TCheckBox; cbShWholeWords: TCheckBox; pnlPerSearch: TPanel; btnPerFind: TORAlignButton; edtPerSearch: TCaptionEdit; cbPerMatchCase: TCheckBox; cbPerWholeWords: TCheckBox; mnuFindShared: TMenuItem; mnuFindPersonal: TMenuItem; N3: TMenuItem; mnuShCollapse: TMenuItem; mnuPerCollapse: TMenuItem; pnlMenuBar: TPanel; lblPerOwner: TLabel; cboOwner: TORComboBox; btnNew: TORAlignButton; pnlMenu: TPanel; mbMain: TMenuBar; mnuNewTemplate: TMenuItem; Bevel1: TBevel; mnuNodeNew: TMenuItem; mnuBPCheckGrammar: TMenuItem; mnuCheckGrammar: TMenuItem; N1: TMenuItem; N7: TMenuItem; N14: TMenuItem; mnuSort: TMenuItem; N15: TMenuItem; mnuNodeSort: TMenuItem; mnuTry: TMenuItem; mnuBPTry: TMenuItem; mnuAutoGen: TMenuItem; mnuNodeAutoGen: TMenuItem; pnlNotes: TPanel; reNotes: TRichEdit; splNotes: TSplitter; lblNotes: TLabel; popNotes: TPopupMenu; mnuNotesUndo: TMenuItem; MenuItem2: TMenuItem; mnuNotesCut: TMenuItem; mnuNotesCopy: TMenuItem; mnuNotesPaste: TMenuItem; MenuItem6: TMenuItem; mnuNotesSelectAll: TMenuItem; MenuItem8: TMenuItem; mnuNotesGrammar: TMenuItem; mnuNotesSpelling: TMenuItem; cbNotes: TCheckBox; gbDialogProps: TGroupBox; cbDisplayOnly: TCheckBox; cbOneItemOnly: TCheckBox; cbHideItems: TORCheckBox; cbFirstLine: TCheckBox; cbHideDlgItems: TCheckBox; cbIndent: TCheckBox; mnuTools: TMenuItem; mnuEditTemplateFields: TMenuItem; N16: TMenuItem; mnuImportTemplate: TMenuItem; mnuExportTemplate: TMenuItem; mnuBPInsertField: TMenuItem; mnuInsertField: TMenuItem; cbEditUser: TCheckBox; dlgImport: TOpenDialog; dlgExport: TSaveDialog; cbxType: TCaptionComboBox; lblType: TLabel; cbxRemDlgs: TORComboBox; lblRemDlg: TLabel; N17: TMenuItem; mnuTemplateIconLegend: TMenuItem; pnlBP: TPanel; lblBoilerplate: TLabel; cbLongLines: TCheckBox; cbLock: TORCheckBox; mnuRefresh: TMenuItem; lblBoilRow: TLabel; lblGroupRow: TLabel; lblBoilCol: TLabel; lblGroupCol: TLabel; pnlCOM: TPanel; lblCOMParam: TLabel; edtCOMParam: TCaptionEdit; cbxCOMObj: TORComboBox; lblCOMObj: TLabel; pnlLink: TPanel; cbxLink: TORComboBox; lblLink: TLabel; procedure btnNewClick(Sender: TObject); procedure btnApplyClick(Sender: TObject); procedure FormCreate(Sender: TObject); procedure cboOwnerNeedData(Sender: TObject; const StartFrom: String; Direction, InsertAt: Integer); procedure cboOwnerChange(Sender: TObject); procedure tvPersonalExpanding(Sender: TObject; Node: TTreeNode; var AllowExpansion: Boolean); procedure tvSharedExpanding(Sender: TObject; Node: TTreeNode; var AllowExpansion: Boolean); procedure tvTreeGetImageIndex(Sender: TObject; Node: TTreeNode); procedure tvTreeGetSelectedIndex(Sender: TObject; Node: TTreeNode); procedure tvTreeChange(Sender: TObject; Node: TTreeNode); procedure splMainMoved(Sender: TObject); procedure pnlBoilerplateResize(Sender: TObject); procedure edtNameOldChange(Sender: TObject); procedure cbActiveClick(Sender: TObject); procedure cbExcludeClick(Sender: TObject); procedure edtGapChange(Sender: TObject); procedure tvTreeEnter(Sender: TObject); procedure tvTreeNodeEdited(Sender: TObject; Node: TTreeNode; var S: String); procedure cbShHideClick(Sender: TObject); procedure cbPerHideClick(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure sbMoveUpClick(Sender: TObject); procedure sbMoveDownClick(Sender: TObject); procedure sbDeleteClick(Sender: TObject); procedure tvTreeDragging(Sender: TObject; Node: TTreeNode; var CanDrag: Boolean); procedure tvTreeDragOver(Sender, Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean); procedure tvTreeDragDrop(Sender, Source: TObject; X, Y: Integer); procedure sbCopyLeftClick(Sender: TObject); procedure sbCopyRightClick(Sender: TObject); procedure reBoilChange(Sender: TObject); procedure cbEditSharedClick(Sender: TObject); procedure popTemplatesPopup(Sender: TObject); procedure mnuCollapseTreeClick(Sender: TObject); procedure mnuFindTemplatesClick(Sender: TObject); procedure btnFindClick(Sender: TObject); procedure edtSearchChange(Sender: TObject); procedure edtShSearchEnter(Sender: TObject); procedure edtShSearchExit(Sender: TObject); procedure edtPerSearchEnter(Sender: TObject); procedure edtPerSearchExit(Sender: TObject); procedure btnOKClick(Sender: TObject); procedure FormShow(Sender: TObject); procedure mnuBPInsertObjectClick(Sender: TObject); procedure mnuBPErrorCheckClick(Sender: TObject); procedure popBoilerplatePopup(Sender: TObject); procedure btnCancelClick(Sender: TObject); procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean); procedure mnuBPSpellCheckClick(Sender: TObject); procedure splBoilMoved(Sender: TObject); procedure edtGapKeyPress(Sender: TObject; var Key: Char); procedure edtNameExit(Sender: TObject); procedure tmrAutoScrollTimer(Sender: TObject); procedure tvTreeStartDrag(Sender: TObject; var DragObject: TDragObject); procedure tvTreeEndDrag(Sender, Target: TObject; X, Y: Integer); procedure mnuGroupBPCopyClick(Sender: TObject); procedure popGroupPopup(Sender: TObject); procedure mnuBPCutClick(Sender: TObject); procedure mnuBPCopyClick(Sender: TObject); procedure mnuBPPasteClick(Sender: TObject); procedure mnuGroupBPSelectAllClick(Sender: TObject); procedure mnuBPSelectAllClick(Sender: TObject); procedure mnuNodeDeleteClick(Sender: TObject); procedure mnuNodeCopyClick(Sender: TObject); procedure mnuNodePasteClick(Sender: TObject); procedure mnuBPUndoClick(Sender: TObject); procedure tvTreeKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); procedure mnuEditClick(Sender: TObject); procedure mnuGroupBoilerplateClick(Sender: TObject); procedure cbShFindOptionClick(Sender: TObject); procedure cbPerFindOptionClick(Sender: TObject); procedure mnuTemplateClick(Sender: TObject); procedure mnuFindSharedClick(Sender: TObject); procedure mnuFindPersonalClick(Sender: TObject); procedure mnuShCollapseClick(Sender: TObject); procedure mnuPerCollapseClick(Sender: TObject); procedure pnlShSearchResize(Sender: TObject); procedure pnlPerSearchResize(Sender: TObject); procedure pnlPropertiesResize(Sender: TObject); procedure mbMainResize(Sender: TObject); procedure mnuBPCheckGrammarClick(Sender: TObject); procedure mnuSortClick(Sender: TObject); procedure pnlBoilerplateCanResize(Sender: TObject; var NewWidth, NewHeight: Integer; var Resize: Boolean); procedure mnuBPTryClick(Sender: TObject); procedure mnuAutoGenClick(Sender: TObject); procedure reNotesChange(Sender: TObject); procedure mnuNotesUndoClick(Sender: TObject); procedure mnuNotesCutClick(Sender: TObject); procedure mnuNotesCopyClick(Sender: TObject); procedure mnuNotesPasteClick(Sender: TObject); procedure mnuNotesSelectAllClick(Sender: TObject); procedure mnuNotesGrammarClick(Sender: TObject); procedure mnuNotesSpellingClick(Sender: TObject); procedure popNotesPopup(Sender: TObject); procedure cbNotesClick(Sender: TObject); procedure cbDisplayOnlyClick(Sender: TObject); procedure cbFirstLineClick(Sender: TObject); procedure cbOneItemOnlyClick(Sender: TObject); procedure cbHideDlgItemsClick(Sender: TObject); procedure cbHideItemsClick(Sender: TObject); procedure cbIndentClick(Sender: TObject); procedure mnuToolsClick(Sender: TObject); procedure mnuEditTemplateFieldsClick(Sender: TObject); procedure mnuBPInsertFieldClick(Sender: TObject); procedure mnuExportTemplateClick(Sender: TObject); procedure mnuImportTemplateClick(Sender: TObject); procedure cbxTypeDrawItem(Control: TWinControl; Index: Integer; Rect: TRect; State: TOwnerDrawState); procedure cbxTypeChange(Sender: TObject); procedure cbxRemDlgsChange(Sender: TObject); procedure mnuTemplateIconLegendClick(Sender: TObject); procedure cbLongLinesClick(Sender: TObject); procedure cbLockClick(Sender: TObject); procedure mnuRefreshClick(Sender: TObject); procedure reResizeRequest(Sender: TObject; Rect: TRect); procedure reBoilSelectionChange(Sender: TObject); procedure reGroupBPSelectionChange(Sender: TObject); procedure cbxCOMObjChange(Sender: TObject); procedure edtCOMParamChange(Sender: TObject); procedure cbxLinkNeedData(Sender: TObject; const StartFrom: String; Direction, InsertAt: Integer); procedure cbxLinkChange(Sender: TObject); procedure cbxLinkSynonymCheck(Sender: TObject; const Text: String; var IsSynonym: Boolean); procedure reBoilKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState); procedure reBoilKeyPress(Sender: TObject; var Key: Char); procedure reBoilKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); private FLastRect: TRect; FForceContainer: boolean; FSavePause: integer; FCopyNode: TTreeNode; FPasteNode: TTreeNode; FCopying: boolean; FDropNode: TTreeNode; FDropInto: boolean; FDragNode: TTreeNode; FPersonalEmptyNodeCount: integer; FSharedEmptyNodeCount: integer; // FOldPersonalTemplate: TTemplate; FCurrentPersonalUser: Int64; FCanEditPersonal: boolean; FCanEditShared: boolean; FUpdating: boolean; FCurTree: TTreeView; FTreeControl: array[TTemplateTreeType, TTemplateTreeControl] of TControl; FInternalHiddenExpand :boolean; FFindShOn: boolean; FFindShNext: boolean; FLastFoundShNode: TTreeNode; FFindPerOn: boolean; FFindPerNext: boolean; FLastFoundPerNode: TTreeNode; FFirstShow: boolean; FFocusName: boolean; FOK2Close: boolean; FBtnNewNode: TTreeNode; FLastDropNode: TTreeNode; FFromMainMenu: boolean; FMainMenuTree: TTreeView; FDragOverCount: integer; FBPOK: boolean; FImportingFromXML: boolean; FXMLTemplateElement: IXMLDOMNode; FXMLFieldElement: IXMLDOMNode; FCanDoReminders: boolean; FCanDoCOMObjects: boolean; FPersonalObjects: TStringList; FShowingTemplate: TTemplate; FConsultServices: TStringList; FNavigatingTab: boolean; protected procedure UpdateXY(re: TRichEdit; lblX, lblY: TLabel); function IsTemplateLocked(Node: TTreeNode): boolean; procedure RefreshData; procedure ShowTemplateType(Template: TTemplate); procedure DisplayBoilerplate(Node: TTreeNode); procedure NewPersonalUser(UsrIEN: Int64); procedure HideControls; procedure EnableControls(ok, Root: boolean); procedure EnableNavControls; procedure MoveCopyButtons; procedure ShowInfo(Node: TTreeNode); function ChangeTree(NewTree: TTreeView): boolean; procedure Resync(const Templates: array of TTemplate); function AllowMove(ADropNode, ADragNode: TTreeNode): boolean; function CanClone(const Node: TTreeNode): boolean; function Clone(Node: TTreeNode): boolean; procedure SharedEditing; function GetTree: TTreeView; procedure SetFindNext(const Tree: TTreeView; const Value: boolean); function ScanNames: boolean; function PasteOK: boolean; function AutoDel(Template: TTemplate): boolean; procedure cbClick(Sender: TCheckBox; Index: integer); procedure UpdateInsertsDialogs; procedure AutoLongLines(Sender: TObject); procedure UpdatePersonalObjects; procedure UpdateApply(Template: TTemplate); procedure TemplateLocked(Sender: TObject); procedure InitTrees; function GetLinkType(const ANode: TTreeNode): TTemplateLinkType; end; procedure EditTemplates(Form: TForm; NewTemplate: boolean = FALSE; CopiedText: string = ''; Shared: boolean = FALSE); implementation {$R *.DFM} uses dShared, uCore, rTemplates, fTemplateObjects, uSpell, fTemplateView, fTemplateAutoGen, fDrawers, fTemplateFieldEditor, fTemplateFields, XMLUtils, fIconLegend, uReminders, uConst, rCore, rEventHooks, rConsults; const PropText = ' Template Properties '; // GroupTag = 5; BPDisplayOnlyFld = 0; BPFirstLineFld = 1; BPOneItemOnlyFld = 2; BPHideDlgItemsFld = 3; BPHideItemsFld = 4; BPIndentFld = 5; BPLockFld = 6; NoIE5 = 'You must have Internet Explorer 5 or better installed to %s Templates'; NoIE5Header = 'Need Internet Explorer 5'; VK_A = Ord('A'); VK_C = Ord('C'); VK_E = Ord('E'); VK_F = Ord('F'); VK_G = Ord('G'); VK_I = Ord('I'); VK_S = Ord('S'); VK_T = Ord('T'); VK_V = Ord('V'); VK_X = Ord('X'); VK_Z = Ord('Z'); type TTypeIndex = (tiTemplate, tiFolder, tiGroup, tiDialog, tiRemDlg, tiCOMObj); const tiNone = TTypeIndex(-1); // TypeTag: array[TTypeIndex] of integer = (7, 6, 8, -8, 7, 7); ttDialog = TTemplateType(-ord(ttGroup)); TypeTag: array[TTypeIndex] of TTemplateType = (ttDoc, ttClass, ttGroup, ttDialog, ttDoc, ttDoc); ForcedIdx: array[boolean, TTypeIndex] of integer = ((0,1,2,3,4,5),(-1,0,1,2,-1,-1)); IdxForced: array[boolean, 0..5] of TTypeIndex = ((tiTemplate, tiFolder, tiGroup, tiDialog, tiRemDlg, tiCOMObj), (tiFolder, tiGroup, tiDialog, tiNone, tiNone, tiNone)); iMessage = 'This template has one or more new fields, and you are not authorized to create new fields. ' + 'If you continue, the program will import the new template without the new fields. Do you wish ' + 'to do this?'; iMessage2 = 'The imported template fields had XML errors. '; iMessage3 = 'No Fields were imported.'; var frmTemplateObjects: TfrmTemplateObjects = nil; frmTemplateFields: TfrmTemplateFields = nil; procedure EditTemplates(Form: TForm; NewTemplate: boolean = FALSE; CopiedText: string = ''; Shared: boolean = FALSE); var frmTemplateEditor: TfrmTemplateEditor; Drawers: TFrmDrawers; ExpandStr, SelectStr: string; SelNode: TTreeNode; SelShared: boolean; begin if(UserTemplateAccessLevel in [taReadOnly, taNone]) then exit; ExpandStr := ''; SelectStr := ''; Drawers := nil; if(not NewTemplate) and (CopiedText = '') then begin if Form is TfrmDrawers then Drawers := TFrmDrawers(Form) else if IsPublishedProp(Form, 'Drawers') then Drawers := TFrmDrawers(GetOrdProp(Form, 'Drawers')); end; if assigned(Drawers) then begin ExpandStr := Drawers.tvTemplates.GetExpandedIDStr(1, ';'); SelectStr := Drawers.tvTemplates.GetNodeID(TORTreeNode(Drawers.tvTemplates.Selected),1,';'); end; frmTemplateEditor := TfrmTemplateEditor.Create(Application); try with frmTemplateEditor do begin Font := Form.Font; reBoil.Font.Size := Form.Font.Size; reGroupBP.Font.Size := Form.Font.Size; reNotes.Font.Size := Form.Font.Size; dmodShared.ExpandTree(tvShared, ExpandStr, FSharedEmptyNodeCount); SelNode := tvShared.FindPieceNode(SelectStr,1,';'); SelShared := assigned(SelNode); dmodShared.ExpandTree(tvPersonal, ExpandStr, FPersonalEmptyNodeCount); if not SelShared then SelNode := tvPersonal.FindPieceNode(SelectStr,1,';'); if(SelShared and (not Shared)) then Shared := TRUE; if(Shared and (UserTemplateAccessLevel = taEditor)) then begin cbEditShared.Checked := TRUE; ActiveControl := tvShared; if SelShared then tvShared.Selected := SelNode else tvShared.Selected := tvShared.Items.GetFirstNode; end else if(not SelShared) and (assigned(SelNode)) then tvPersonal.Selected := SelNode; if(NewTemplate) then begin btnNewClick(frmTemplateEditor); if(CopiedText <> '') then begin TTemplate(FBtnNewNode.Data).Boilerplate := CopiedText; ShowInfo(FBtnNewNode); end; end; ShowModal; end; finally frmTemplateEditor.Free; end; end; procedure TfrmTemplateEditor.btnNewClick(Sender: TObject); var idx: integer; Tmp, Owner: TTemplate; Node, PNode: TTreeNode; ownr: string; ok: boolean; ACheckBox: TCheckBox; begin if((assigned(FCurTree)) and (assigned(FCurTree.Selected))) then begin if(FCurTree = tvShared) and (FCanEditShared) then ok := TRUE else if(FCurTree = tvPersonal) and (FCanEditPersonal) then ok := TRUE else ok := FALSE; if(ok) then begin Node := FCurTree.Selected; PNode := Node; if(TTemplate(Node.Data).RealType = ttDoc) then PNode := Node.Parent; if CanClone(PNode) then begin Clone(PNode); Owner := TTemplate(PNode.Data); if assigned(Owner) and Owner.CanModify then begin if Node = PNode then idx := 0 else idx := Owner.Items.IndexOf(Node.Data) + 1; if(FCurTree = tvShared) then begin ownr := ''; ACheckBox := cbShHide; end else begin ownr := IntToStr(User.DUZ); ACheckBox := cbPerHide; end; if FImportingFromXML then begin Tmp := TTemplate.CreateFromXML(FXMLTemplateElement, ownr); ACheckBox.Checked := ACheckBox.Checked and Tmp.Active; end else begin Tmp := TTemplate.Create('0^T^A^'+NewTemplateName+'^^^'+ownr); Tmp.BackupItems; Templates.AddObject(Tmp.ID, Tmp); end; btnApply.Enabled := TRUE; if(idx >= Owner.Items.Count) then Owner.Items.Add(Tmp) else Owner.Items.Insert(idx, Tmp); Resync([Owner]); Node := FCurTree.Selected; if(Node.Data <> Tmp) then begin if(TTemplate(Node.Data).RealType = ttDoc) then Node := Node.GetNextSibling else begin Node.Expand(FALSE); Node := Node.GetFirstChild; end; FCurTree.Selected := Node; end; FBtnNewNode := Node; if(FFirstShow) then FFocusName := TRUE else begin edtName.SetFocus; edtName.SelectAll; end; end; end; end; end; end; procedure TfrmTemplateEditor.btnApplyClick(Sender: TObject); begin if(ScanNames) then begin SaveAllTemplates; BtnApply.Enabled := BackupDiffers; if not BtnApply.Enabled then UnlockAllTemplates; end; end; procedure TfrmTemplateEditor.FormCreate(Sender: TObject); begin ResizeAnchoredFormToFont(self); //Now fix everything the resize messed up lblLines.Width := cbLock.Left - lblLines.Left - 15; sbPerDelete.Left := pnlPersonalBottom.ClientWidth - sbPerDelete.Width - 1; sbPerDown.Left := sbPerDelete.Left - sbPerDown.Width - 2; sbPerUp.Left := sbPerDown.Left - sbPerUp.Width - 2; cbPerHide.Width := sbPerUp.Left - 3; btnPerFind.Left := pnlPerSearch.ClientWidth - btnPerFind.Width; FSavePause := Application.HintHidePause; Application.HintHidePause := FSavePause*2; if InteractiveRemindersActive then begin QuickCopy(GetTemplateAllowedReminderDialogs, cbxRemDlgs.Items); FCanDoReminders := (cbxRemDlgs.Items.Count > 0); end else FCanDoReminders := FALSE; QuickCopy(GetAllActiveCOMObjects, cbxCOMObj.Items); FCanDoCOMObjects := (cbxCOMObj.Items.Count > 0); FUpdating := TRUE; FFirstShow := TRUE; FTreeControl[ttShared, tcDel] := sbShDelete; FTreeControl[ttShared, tcUp] := sbShUp; FTreeControl[ttShared, tcDown] := sbShDown; FTreeControl[ttShared, tcLbl] := lblCopy; FTreeControl[ttShared, tcCopy] := sbCopyRight; FTreeControl[ttPersonal, tcDel] := sbPerDelete; FTreeControl[ttPersonal, tcUp] := sbPerUp; FTreeControl[ttPersonal, tcDown] := sbPerDown; FTreeControl[ttPersonal, tcLbl] := lblCopy; FTreeControl[ttPersonal, tcCopy] := sbCopyLeft; dmodShared.InEditor := TRUE; dmodShared.OnTemplateLock := TemplateLocked; gbProperties.Caption := PropText; pnlShSearch.Visible := FALSE; pnlPerSearch.Visible := FALSE; FCanEditPersonal := TRUE; { Don't mess with the order of the following commands! } InitTrees; tvPersonal.Selected := tvPersonal.Items.GetFirstNode; ClearBackup; cboOwner.SelText := MixedCase(User.Name); NewPersonalUser(User.DUZ); cbEditShared.Visible := (UserTemplateAccessLevel = taEditor); FCanEditShared := FALSE; SharedEditing; HideControls; lblCopy.AutoSize := TRUE; lblCopy.AutoSize := FALSE; // resets height based on font lblCopy.Width := pnlCopyBtns.Width + splMiddle.Width; MoveCopyButtons; cbShHide.Checked := TRUE; cbPerHide.Checked := TRUE; BtnApply.Enabled := BackupDiffers; end; procedure TfrmTemplateEditor.HideControls; begin sbCopyRight.Visible := FCanEditPersonal; if(not FCanEditPersonal) then cbPerHide.Checked := TRUE; cbPerHide.Visible := FCanEditPersonal; sbPerDelete.Visible := FCanEditPersonal; sbPerUp.Visible := FCanEditPersonal; sbPerDown.Visible := FCanEditPersonal; tvPersonal.ReadOnly := not FCanEditPersonal; MoveCopyButtons; end; procedure TfrmTemplateEditor.cboOwnerNeedData(Sender: TObject; const StartFrom: String; Direction, InsertAt: Integer); begin // cboOwner.ForDataUse(SubSetOfTemplateOwners(StartFrom, Direction)); end; procedure TfrmTemplateEditor.cboOwnerChange(Sender: TObject); begin NewPersonalUser(cboOwner.ItemIEN); end; procedure TfrmTemplateEditor.NewPersonalUser(UsrIEN: Int64); var NewEdit: boolean; begin FCurrentPersonalUser := UsrIEN; NewEdit := (FCurrentPersonalUser = User.DUZ); if(FCanEditPersonal <> NewEdit) then begin FCanEditPersonal := NewEdit; HideControls; end; end; procedure TfrmTemplateEditor.tvPersonalExpanding(Sender: TObject; Node: TTreeNode; var AllowExpansion: Boolean); begin AllowExpansion := dmodShared.ExpandNode(tvPersonal, Node, FPersonalEmptyNodeCount, not cbPerHide.Checked); if(AllowExpansion and FInternalHiddenExpand) then AllowExpansion := FALSE; end; procedure TfrmTemplateEditor.tvSharedExpanding(Sender: TObject; Node: TTreeNode; var AllowExpansion: Boolean); begin AllowExpansion := dmodShared.ExpandNode(tvShared, Node, FSharedEmptyNodeCount, not cbShHide.Checked); if(AllowExpansion and FInternalHiddenExpand) then AllowExpansion := FALSE; end; procedure TfrmTemplateEditor.tvTreeGetImageIndex(Sender: TObject; Node: TTreeNode); begin Node.ImageIndex := dmodShared.ImgIdx(Node); end; procedure TfrmTemplateEditor.tvTreeGetSelectedIndex(Sender: TObject; Node: TTreeNode); begin Node.SelectedIndex := dmodShared.ImgIdx(Node); end; function TfrmTemplateEditor.IsTemplateLocked(Node: TTreeNode): boolean; var Template: TTemplate; begin Result := FALSE; if assigned(Node) then begin Template := TTemplate(Node.Data); if Template.AutoLock then Result := TRUE else if (Template.PersonalOwner = 0) then begin if RootTemplate.IsLocked then Result := TRUE else begin Result := TTemplate(Node.Data).IsLocked; if (not Result) and assigned(Node.Parent) and (TTemplate(Node.Parent).PersonalOwner = 0) then Result := IsTemplateLocked(Node.Parent); end; end; end; end; procedure TfrmTemplateEditor.tvTreeChange(Sender: TObject; Node: TTreeNode); var ok, Something: boolean; Template: TTemplate; begin ChangeTree(TTreeView(Sender)); Something := assigned(Node); if Something then begin Template := TTemplate(Node.Data); Something := assigned(Template); if Something then begin if(Sender = tvPersonal) then begin ok := FCanEditPersonal; if ok and (Template.PersonalOwner = 0) and IsTemplateLocked(Node) then ok := FALSE; end else ok := FCanEditShared; EnableControls(ok, (Template.RealType in AllTemplateRootTypes)); ShowInfo(Node); end; end; if not Something then begin gbProperties.Caption := PropText; EnableControls(FALSE, FALSE); ShowInfo(nil); end; end; procedure TfrmTemplateEditor.EnableControls(ok, Root: boolean); begin cbLock.Enabled := ok and (FCurTree = tvShared); if(ok and Root) then begin ok := FALSE; lblName.Enabled := TRUE; edtName.Enabled := TRUE; reNotes.ReadOnly := FALSE; end else begin lblName.Enabled := ok; edtName.Enabled := ok; reNotes.ReadOnly := not ok; end; lblNotes.Enabled := (not reNotes.ReadOnly); if(reNotes.ReadOnly) then reNotes.Color := ReadOnlyColor else reNotes.Color := clWindow; cbxType.Enabled := ok; lblType.Enabled := ok; lblRemDlg.Enabled := ok; cbxRemDlgs.Enabled := ok and FCanDoReminders; cbActive.Enabled := ok; cbExclude.Enabled := ok; cbDisplayOnly.Enabled := ok; cbFirstLine.Enabled := ok; cbOneItemOnly.Enabled := ok; cbHideDlgItems.Enabled := ok; cbHideItems.Enabled := ok; cbIndent.Enabled := ok; edtGap.Enabled := ok; udGap.Enabled := ok; udGap.Invalidate; lblLines.Enabled := ok; reBoil.ReadOnly := not ok; if(ok) then reBoil.Color := clWindow else reBoil.Color := ReadOnlyColor; lblLink.Enabled := ok; cbxLink.Enabled := ok; ok := ok and FCanDoCOMObjects; cbxCOMObj.Enabled := ok; lblCOMObj.Enabled := ok; edtCOMParam.Enabled := ok; lblCOMParam.Enabled := ok; UpdateInsertsDialogs; EnableNavControls; end; procedure TfrmTemplateEditor.MoveCopyButtons; var tmpHeight: integer; begin tmpHeight := tvShared.Height; dec(tmpHeight,lblCopy.Height); if(sbCopyLeft.Visible) then dec(tmpHeight, sbCopyLeft.Height+5); if(sbCopyRight.Visible) then dec(tmpHeight, sbCopyRight.Height+5); tmpHeight := (tmpHeight div 2) + tvShared.Top; lblCopy.Top := tmpHeight; inc(tmpHeight,lblCopy.height+5); if(sbCopyLeft.Visible) then begin sbCopyLeft.Top := tmpHeight; inc(tmpHeight, sbCopyLeft.Height+5); end; if(sbCopyRight.Visible) then sbCopyRight.Top := tmpHeight; end; procedure TfrmTemplateEditor.splMainMoved(Sender: TObject); begin MoveCopyButtons; end; procedure TfrmTemplateEditor.ShowInfo(Node: TTreeNode); var OldUpdating, ClearName, ClearRB, ClearAll: boolean; Idx: TTypeIndex; CanDoCOM: boolean; LinkTemplate: TTemplate; lt: TTemplateLinkType; lts: string; i: integer; begin OldUpdating := FUpdating; FUpdating := TRUE; try if(assigned(Node)) then begin FShowingTemplate := TTemplate(Node.Data); with FShowingTemplate do begin ClearName := FALSE; ClearRB := FALSE; ClearAll := FALSE; ShowTemplateType(TTemplate(Node.Data)); lt := GetLinkType(Node); if(lt = ltNone) or (IsReminderDialog and (not (lt in [ltNone, ltTitle]))) then pnlLink.Visible := FALSE else begin pnlLink.Visible := TRUE; pnlLink.Tag := ord(lt); case lt of ltTitle: lts := 'Title'; ltConsult: lts := 'Consult Service'; ltProcedure: lts := 'Procedure'; else lts := ''; end; cbxLink.Clear; if lt = ltConsult then begin cbxLink.LongList := FALSE; if not assigned(FConsultServices) then begin FConsultServices := TStringList.Create; FConsultServices.Assign(LoadServiceListWithSynonyms(1)); SortByPiece(FConsultServices, U, 2); end; for i := 0 to FConsultServices.Count-1 do begin LinkTemplate := GetLinkedTemplate(piece(FConsultServices[i],U,1), ltConsult); if (not assigned(LinkTemplate)) or (LinkTemplate = FShowingTemplate) then cbxLink.Items.Add(FConsultServices[i]); end; end else begin cbxLink.LongList := TRUE; cbxLink.HideSynonyms := TRUE; cbxLink.InitLongList(LinkName); end; cbxLink.SelectByID(LinkIEN); lblLink.Caption := ' Associated ' + lts + ': '; cbxLink.Caption := lblLink.Caption; end; edtName.Text := PrintName; reNotes.Lines.Text := Description; if(PersonalOwner = 0) and (FCurTree = tvShared) and (cbEditShared.Checked) then begin cbLock.Checked := IsLocked; if AutoLock then cbLock.Enabled := FALSE; end else begin cbLock.Checked := IsTemplateLocked(Node); cbLock.Enabled := FALSE; end; CanDoCom := FCanDoCOMObjects and (PersonalOwner = 0); if(RealType in AllTemplateRootTypes) then begin ClearRB := TRUE; ClearAll := TRUE; end else begin case RealType of ttDoc: begin if IsReminderDialog then Idx := tiRemDlg else if IsCOMObject then Idx := tiCOMObj else Idx := tiTemplate; end; ttGroup: begin if(Dialog) then Idx := tiDialog else Idx := tiGroup; end; ttClass: Idx := tiFolder; else Idx := tiNone; end; FForceContainer := ((RealType in [ttGroup, ttClass]) and (Children <> tcNone)); cbxType.Items.Clear; if not FForceContainer then cbxType.Items.Add('Template'); cbxType.Items.Add('Folder'); cbxType.Items.Add('Group Template'); cbxType.Items.Add('Dialog'); if (not FForceContainer) then begin if(FCanDoReminders or CanDoCOM) then cbxType.Items.Add('Reminder Dialog'); if(CanDoCOM) then cbxType.Items.Add('COM Object'); end; cbxType.ItemIndex := ForcedIdx[FForceContainer, Idx]; if(Idx = tiRemDlg) and FCanDoReminders then cbxRemDlgs.SelectByID(ReminderDialogIEN) else begin lblRemDlg.Enabled := FALSE; cbxRemDlgs.Enabled := FALSE; cbxRemDlgs.ItemIndex := -1; end; if (Idx = tiCOMObj) and CanDoCOM then begin pnlCOM.Visible := TRUE; cbxCOMObj.SelectByIEN(COMObject); edtCOMParam.Text := COMParam; end else begin pnlCOM.Visible := FALSE; cbxCOMObj.ItemIndex := -1; edtCOMParam.Text := ''; end; cbActive.Checked := Active; if(RealType in [ttClass, ttGroup]) then cbHideItems.Checked := HideItems else begin cbHideItems.Checked := FALSE; cbHideItems.Enabled := FALSE; end; if((RealType in [ttDoc, ttGroup]) and (assigned(Node.Parent)) and (TTemplate(Node.Parent.Data).RealType = ttGroup) and (not IsReminderDialog) and (not IsCOMObject)) then cbExclude.Checked := Exclude else begin cbExclude.Checked := FALSE; cbExclude.Enabled := FALSE; end; if dmodShared.InDialog(Node) and (not IsReminderDialog) and (not IsCOMObject) then begin cbDisplayOnly.Checked := DisplayOnly; cbFirstLine.Checked := FirstLine; end else begin cbDisplayOnly.Checked := FALSE; cbDisplayOnly.Enabled := FALSE; cbFirstLine.Checked := FALSE; cbFirstLine.Enabled := FALSE; end; if(RealType in [ttGroup, ttClass]) and (Children <> tcNone) and (dmodShared.InDialog(Node)) then begin cbOneItemOnly.Checked := OneItemOnly; cbIndent.Checked := IndentItems; if(RealType = ttGroup) and (Boilerplate <> '') then begin cbHideDlgItems.Checked := HideDlgItems; end else begin cbHideDlgItems.Checked := FALSE; cbHideDlgItems.Enabled := FALSE; end; end else begin cbOneItemOnly.Checked := FALSE; cbOneItemOnly.Enabled := FALSE; cbHideDlgItems.Checked := FALSE; cbHideDlgItems.Enabled := FALSE; cbIndent.Checked := FALSE; cbIndent.Enabled := FALSE; end; if(RealType = ttGroup) then edtGap.Text := IntToStr(Gap) else begin edtGap.Text := '0'; edtGap.Enabled := FALSE; udGap.Enabled := FALSE; udGap.Invalidate; lblLines.Enabled := FALSE; end; DisplayBoilerPlate(Node); end; end; end else begin ClearAll := TRUE; ClearRB := TRUE; ClearName := TRUE; gbProperties.Caption := PropText; end; if(ClearName) then begin edtName.Text := ''; reNotes.Clear; end; if(ClearRB) then begin cbxType.ItemIndex := Ord(tiNone); end; if(ClearAll) then begin cbActive.Checked := FALSE; cbExclude.Checked := FALSE; cbDisplayOnly.Checked := FALSE; cbFirstLine.Checked := FALSE; cbOneItemOnly.Checked := FALSE; cbHideDlgItems.Checked := FALSE; cbHideItems.Checked := FALSE; cbIndent.Checked := FALSE; edtGap.Text := '0'; reBoil.Clear; pnlGroupBP.Visible := FALSE; splBoil.Visible := FALSE; pnlBoilerplateResize(Self); pnlCOM.Visible := FALSE; pnlLink.Visible := FALSE; end; if cbDisplayOnly.Enabled or cbFirstLine.Enabled or cbIndent.Enabled or cbOneItemOnly.Enabled or cbHideDlgItems.Enabled then gbDialogProps.Font.Color := clWindowText else gbDialogProps.Font.Color := clInactiveCaption; finally FUpdating := OldUpdating; end; end; procedure TfrmTemplateEditor.pnlBoilerplateResize(Sender: TObject); var Max: integer; begin if(pnlGroupBP.Visible) and (pnlGroupBP.Height > (pnlBoilerplate.Height-29)) then pnlGroupBP.Height := pnlBoilerplate.Height-29; if cbLongLines.checked then Max := 240 else Max := MAX_ENTRY_WIDTH; LimitEditWidth(reBoil, Max); LimitEditWidth(reNotes, MAX_ENTRY_WIDTH); end; procedure TfrmTemplateEditor.edtNameOldChange(Sender: TObject); var i: integer; Template: TTemplate; DoRefresh: boolean; begin if((not FUpdating) and (assigned(FCurTree)) and (assigned(FCurTree.Selected))) then begin if CanClone(FCurTree.Selected) then begin DoRefresh := Clone(FCurTree.Selected); Template := TTemplate(FCurTree.Selected.Data); if assigned(Template) and Template.CanModify then begin Template.PrintName := edtName.Text; UpdateApply(Template); for i := 0 to Template.Nodes.Count-1 do TTreeNode(Template.Nodes.Objects[i]).Text := Template.PrintName; if(DoRefresh) then begin tvShared.Invalidate; tvPersonal.Invalidate; end; end; end; end; end; procedure TfrmTemplateEditor.cbActiveClick(Sender: TObject); var i: integer; Template: TTemplate; Node: TTreeNode; begin if((not FUpdating) and (assigned(FCurTree)) and (assigned(FCurTree.Selected))) then begin if CanClone(FCurTree.Selected) then begin Clone(FCurTree.Selected); Template := TTemplate(FCurTree.Selected.Data); if assigned(Template) and Template.CanModify then begin Template.Active := cbActive.Checked; UpdateApply(Template); for i := 0 to Template.Nodes.Count-1 do begin Node := TTreeNode(Template.Nodes.Objects[i]); Node.Cut := not Template.Active; end; if(FCurTree = tvShared) then begin cbPerHideClick(Sender); cbShHideClick(Sender); end else begin cbShHideClick(Sender); cbPerHideClick(Sender); end; tvTreeChange(FCurTree, FCurTree.Selected); EnableNavControls; if cbActive.CanFocus then cbActive.SetFocus; end; end; end; end; procedure TfrmTemplateEditor.cbExcludeClick(Sender: TObject); var i: integer; Template: TTemplate; Node: TTreeNode; begin if((not FUpdating) and (assigned(FCurTree)) and (assigned(FCurTree.Selected))) then begin if CanClone(FCurTree.Selected) then begin Clone(FCurTree.Selected); Template := TTemplate(FCurTree.Selected.Data); if assigned(Template) and Template.CanModify then begin Template.Exclude := cbExclude.Checked; UpdateApply(Template); for i := 0 to Template.Nodes.Count-1 do begin Node := TTreeNode(Template.Nodes.Objects[i]); Node.ImageIndex := dmodShared.ImgIdx(Node); Node.SelectedIndex := dmodShared.ImgIdx(Node); end; tvShared.Invalidate; tvPersonal.Invalidate; end; end; end; end; procedure TfrmTemplateEditor.edtGapChange(Sender: TObject); var DoRefresh: boolean; Template: TTemplate; begin if((not FUpdating) and (assigned(FCurTree)) and (assigned(FCurTree.Selected))) then begin if CanClone(FCurTree.Selected) then begin DoRefresh := Clone(FCurTree.Selected); Template := TTemplate(FCurTree.Selected.Data); if assigned(Template) and Template.CanModify then begin Template.Gap := StrToIntDef(edtGap.Text, 0); UpdateApply(Template); DisplayBoilerPlate(FCurTree.Selected); if(DoRefresh) then begin tvShared.Invalidate; tvPersonal.Invalidate; end; end; end; end; end; function TfrmTemplateEditor.ChangeTree(NewTree: TTreeView): boolean; var i: TTemplateTreeControl; begin Result := FALSE; tvShared.HideSelection := TRUE; tvPersonal.HideSelection := TRUE; if(NewTree <> FCurTree) then begin Result := TRUE; if(assigned(FCurTree)) then begin for i := low(TTemplateTreeControl) to high(TTemplateTreeControl) do FTreeControl[TTemplateTreeType(FCurTree.Tag), i].Enabled := FALSE; end; FCurTree := NewTree; end; if(assigned(FCurTree)) then begin FCurTree.HideSelection := FALSE; if(FCurTree = tvPersonal) and (Screen.ActiveControl = tvShared) then tvPersonal.SetFocus else if(FCurTree = tvShared) and (Screen.ActiveControl = tvPersonal) then tvShared.SetFocus; end; end; procedure TfrmTemplateEditor.tvTreeEnter(Sender: TObject); begin if((Sender is TTreeView) and (ChangeTree(TTreeView(Sender)))) then tvTreeChange(Sender, TTreeView(Sender).Selected); end; procedure TfrmTemplateEditor.tvTreeNodeEdited(Sender: TObject; Node: TTreeNode; var S: String); begin FUpdating := TRUE; try edtName.Text := S; finally FUpdating := FALSE; end; edtNameOldChange(edtName); end; procedure TfrmTemplateEditor.cbShHideClick(Sender: TObject); var Node: TTreeNode; begin Node := tvShared.Items.GetFirstNode; while assigned(Node) do begin dmodShared.Resync(Node, not cbShHide.Checked, FSharedEmptyNodeCount); Node := Node.getNextSibling; end; tvTreeChange(tvShared, tvShared.Selected); EnableNavControls; end; procedure TfrmTemplateEditor.cbPerHideClick(Sender: TObject); begin dmodShared.Resync(tvPersonal.Items.GetFirstNode, not cbPerHide.Checked, FPersonalEmptyNodeCount); tvTreeChange(tvPersonal, tvPersonal.Selected); EnableNavControls; end; procedure TfrmTemplateEditor.DisplayBoilerplate(Node: TTreeNode); var OldUpdating, ItemOK, BPOK, LongLines: boolean; i: integer; TmpSL: TStringList; begin OldUpdating := FUpdating; FUpdating := TRUE; try pnlBoilerplateResize(pnlBoilerplate); reBoil.Clear; ItemOK := FALSE; BPOK := TRUE; with Node, TTemplate(Node.Data) do begin if(RealType in [ttDoc, ttGroup]) then begin TmpSL := TStringList.Create; try if(RealType = ttGroup) and (not reBoil.ReadOnly) then begin ItemOK := TRUE; TmpSL.Text := Boilerplate; reGroupBP.Clear; reGroupBP.SelText := FullBoilerplate; end else TmpSL.Text := FullBoilerplate; LongLines := FALSE; for i := 0 to TmpSL.Count-1 do begin if length(TmpSL[i]) > MAX_ENTRY_WIDTH then begin LongLines := TRUE; break; end; end; cbLongLines.Checked := LongLines; reBoil.SelText := TmpSL.Text; finally TmpSL.Free; end; end else begin reBoil.ReadOnly := TRUE; reBoil.Color := ReadOnlyColor; UpdateInsertsDialogs; end; pnlGroupBP.Visible := ItemOK; splBoil.Visible := ItemOK; if(not ItemOK) and (IsReminderDialog or IsCOMObject) then BPOK := FALSE; if(ItemOK) then splBoil.Top := pnlGroupBP.Top - splBoil.Height; pnlBoilerplateResize(Self); pnlBoilerplate.Visible := BPOK; lblBoilerplate.Visible := BPOK; pnlCOM.Visible := (not BPOK) and IsCOMObject; end; finally FUpdating := OldUpdating; end; end; procedure TfrmTemplateEditor.FormDestroy(Sender: TObject); begin KillObj(@FConsultServices); Application.HintHidePause := FSavePause; if(assigned(frmTemplateObjects)) then begin frmTemplateObjects.Free; frmTemplateObjects := nil; end; if(assigned(frmTemplateFields)) then begin frmTemplateFields.Free; frmTemplateFields := nil; end; KillObj(@FPersonalObjects); dmodShared.OnTemplateLock := nil; dmodShared.InEditor := FALSE; RemoveAllNodes; ClearBackup; UnlockAllTemplates; dmodShared.Reload; end; procedure TfrmTemplateEditor.sbMoveUpClick(Sender: TObject); var idx: integer; ChangeLevel: boolean; ParentsParent, ParentNode, Node: TTreeNode; NodeTemplate, ParentTemplate, Template: TTemplate; Hide, First, ok: boolean; begin if((assigned(FCurTree)) and (assigned(FCurTree.Selected)) and (assigned(FCurTree.Selected.Parent))) then begin Node := FCurTree.Selected; NodeTemplate := TTemplate(Node.Data); ParentNode := Node.Parent; Template := TTemplate(ParentNode.Data); idx := Template.Items.IndexOf(NodeTemplate); ChangeLevel := (idx < 1); if(not ChangeLevel) then begin if(TTemplateTreeType(TBitBtn(Sender).Tag) = ttShared) then Hide := cbShHide.Checked else Hide := cbPerHide.Checked; First := TRUE; while(idx > 0) do begin if First then begin ok := FALSE; First := FALSE; if CanClone(ParentNode) then begin if(Clone(ParentNode)) then Template := TTemplate(ParentNode.Data); if Template.CanModify then ok := TRUE; end; end else ok := TRUE; if ok then begin Template.Items.Exchange(idx-1, idx); if(Hide and (not TTemplate(Template.Items[idx]).Active)) then begin dec(idx); ChangeLevel := (idx < 1); end else idx := 0; end else idx := 0; end; end; if(ChangeLevel) then begin ParentsParent := ParentNode.Parent; if(assigned(ParentsParent)) then begin ParentTemplate := TTemplate(ParentsParent.Data); if(ParentTemplate.Items.IndexOf(NodeTemplate) >= 0) then InfoBox(ParentsParent.Text + ' already contains the ' + NodeTemplate.PrintName + ' template.', 'Error', MB_OK or MB_ICONERROR) else begin if CanClone(ParentNode) then begin if(Clone(ParentNode)) then Template := TTemplate(ParentNode.Data); if Template.CanModify and CanClone(ParentsParent) then begin if(Clone(ParentsParent)) then ParentTemplate := TTemplate(ParentsParent.Data); if ParentTemplate.CanModify then begin Template.Items.Delete(idx); idx := ParentTemplate.Items.IndexOf(Template); if(idx >= 0) then begin ParentTemplate.Items.Insert(idx, NodeTemplate); Resync([ParentTemplate, Template]); btnApply.Enabled := TRUE; end; end; end; end; end; end; end else begin Resync([Template]); btnApply.Enabled := TRUE; end; end; end; procedure TfrmTemplateEditor.sbMoveDownClick(Sender: TObject); var max, idx: integer; ChangeLevel: boolean; ParentsParent, ParentNode, Node: TTreeNode; NodeTemplate, ParentTemplate, Template: TTemplate; Hide, First, ok: boolean; begin if((assigned(FCurTree)) and (assigned(FCurTree.Selected)) and (assigned(FCurTree.Selected.Parent))) then begin Node := FCurTree.Selected; NodeTemplate := TTemplate(Node.Data); ParentNode := Node.Parent; Template := TTemplate(ParentNode.Data); idx := Template.Items.IndexOf(NodeTemplate); max := Template.Items.Count-1; ChangeLevel := (idx >= max); if(not ChangeLevel) then begin if(TTemplateTreeType(TBitBtn(Sender).Tag) = ttShared) then Hide := cbShHide.Checked else Hide := cbPerHide.Checked; First := TRUE; while(idx < max) do begin if First then begin ok := FALSE; First := FALSE; if CanClone(ParentNode) then begin if(Clone(ParentNode)) then Template := TTemplate(ParentNode.Data); if Template.CanModify then ok := TRUE; end; end else ok := TRUE; if ok then begin Template.Items.Exchange(idx, idx+1); if(Hide and (not TTemplate(Template.Items[idx]).Active)) then begin inc(idx); ChangeLevel := (idx >= max); end else idx := max; end else idx := max; end; end; if(ChangeLevel) then begin ParentsParent := ParentNode.Parent; if(assigned(ParentsParent)) then begin ParentTemplate := TTemplate(ParentsParent.Data); if(ParentTemplate.Items.IndexOf(NodeTemplate) >= 0) then InfoBox(ParentsParent.Text + ' already contains the ' + NodeTemplate.PrintName + ' template.', 'Error', MB_OK or MB_ICONERROR) else begin if CanClone(ParentNode) then begin if(Clone(ParentNode)) then Template := TTemplate(ParentNode.Data); if Template.CanModify and CanClone(ParentsParent) then begin if(Clone(ParentsParent)) then ParentTemplate := TTemplate(ParentsParent.Data); if ParentTemplate.CanModify then begin Template.Items.Delete(idx); idx := ParentTemplate.Items.IndexOf(Template); if(idx >= 0) then begin if(idx = (ParentTemplate.Items.Count-1)) then ParentTemplate.Items.Add(NodeTemplate) else ParentTemplate.Items.Insert(idx+1, NodeTemplate); Resync([ParentTemplate, Template]); btnApply.Enabled := TRUE; end; end; end; end; end; end; end else begin Resync([Template]); btnApply.Enabled := TRUE; end; end; end; procedure TfrmTemplateEditor.sbDeleteClick(Sender: TObject); var PNode, Node: TTreeNode; Template, Parent: TTemplate; DoIt: boolean; Answer: Word; begin if((assigned(FCurTree)) and (assigned(FCurTree.Selected)) and (assigned(FCurTree.Selected.Parent))) then begin Node := FCurTree.Selected; Template := TTemplate(Node.Data); PNode := Node.Parent; Parent := TTemplate(PNode.Data); if(AutoDel(Template)) then DoIt := TRUE else if(Template.Active) and (cbActive.Checked) then begin DoIt := FALSE; Answer := MessageDlg('Once you delete a template you may not be able to retrieve it.' + CRLF + 'Rather than deleting, you may want to inactivate a template instead.' + CRLF + 'You may inactivate this template by pressing the Ignore button now.' + CRLF + 'Are you sure you want to delete the "' + Node.Text + '" Template?', mtConfirmation, [mbYes, mbNo, mbIgnore], 0); if(Answer = mrYes) then DoIt := TRUE else if(Answer = mrIgnore) then cbActive.Checked := FALSE; end else DoIt := InfoBox('Are you sure you want to delete the "' + Node.Text + '" Template?', 'Confirmation', MB_YESNO or MB_ICONQUESTION) = IDYES; if(DoIt and CanClone(PNode)) then begin if(Clone(PNode)) then Parent := TTemplate(PNode.Data); if assigned(Parent) and Parent.CanModify then begin btnApply.Enabled := TRUE; Parent.RemoveChild(Template); MarkDeleted(Template); Resync([Parent]); tvTreeChange(FCurTree, FCurTree.Selected); end; end; end; end; procedure TfrmTemplateEditor.EnableNavControls; var i: TTemplateTreeControl; AllowUp, AllowDown, AllowSet: boolean; Node: TTreeNode; Tree: TTemplateTreeType; Curok: boolean; OldActiveControl: TControl; begin if(Assigned(FCurTree)) then begin Tree := TTemplateTreeType(FCurTree.Tag); Node := FCurTree.Selected; if(Assigned(Node)) then Curok := (TTemplate(Node.Data).RealType in [ttDoc, ttGroup, ttClass]) else Curok := FALSE; if(Curok) then begin OldActiveControl := ActiveControl; FTreeControl[Tree, tcDel].Enabled := TRUE; AllowSet := FALSE; if(Node.Index > 0) then AllowUp := TRUE else begin AllowUp := AllowMove(Node.Parent.Parent, Node); AllowSet := TRUE; end; FTreeControl[Tree, tcUp].Enabled := AllowUp; AllowDown := AllowUp; if(Node.Index < (Node.Parent.Count-1)) then AllowDown := TRUE else begin if(not AllowSet) then AllowDown := AllowMove(Node.Parent.Parent, Node); end; FTreeControl[Tree, tcDown].Enabled := AllowDown; if not AllowUp and (OldActiveControl = FTreeControl[Tree, tcUp]) then (FTreeControl[Tree, tcDown] as TWinControl).SetFocus; if not AllowDown and (OldActiveControl = FTreeControl[Tree, tcDown]) then (FTreeControl[Tree, tcUp] as TWinControl).SetFocus; FTreeControl[Tree, tcCopy].Enabled := FTreeControl[TTemplateTreeType(1-ord(Tree)), tcDel].Visible; if(FTreeControl[Tree, tcCopy].Enabled) then begin if(Tree = ttShared) then Node := tvPersonal.Selected else Node := tvShared.Selected; if(assigned(Node)) then begin if(TTemplate(Node.Data).RealType = ttDoc) then Node := Node.Parent; FTreeControl[Tree, tcCopy].Enabled := AllowMove(Node, FCurTree.Selected); end else FTreeControl[Tree, tcCopy].Enabled := FALSE; end; FTreeControl[Tree, tcLbl].Enabled := FTreeControl[Tree, tcCopy].Enabled; end else begin for i := low(TTemplateTreeControl) to high(TTemplateTreeControl) do FTreeControl[Tree, i].Enabled := FALSE; end; if(FCurTree = tvShared) and (FCanEditShared) then btnNew.Enabled := TRUE else if(FCurTree = tvPersonal) and (FCanEditPersonal) then btnNew.Enabled := TRUE else btnNew.Enabled := FALSE; end else btnNew.Enabled := FALSE; end; procedure TfrmTemplateEditor.tvTreeDragging(Sender: TObject; Node: TTreeNode; var CanDrag: Boolean); begin CanDrag := (TTemplate(Node.Data).RealType in [ttDoc, ttGroup, ttClass]); if(CanDrag) then FDragNode := Node else FDragNode := nil; end; procedure TfrmTemplateEditor.tvTreeDragOver(Sender, Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean); var TmpNode: TTreeNode; Tree: TTreeView; begin FDropNode := nil; Accept := FALSE; if(Source is TTreeView) and (assigned(FDragNode)) then begin Tree := TTreeView(Sender); FDropNode := Tree.GetNodeAt(X,Y); if(((Tree = tvShared) and (FCanEditShared)) or ((Tree = tvPersonal) and (FCanEditPersonal))) then begin if(assigned(FDropNode)) then begin FDropInto := (TTemplate(FDropNode.Data).RealType in AllTemplateFolderTypes); if(FDropInto) then TmpNode := FDropNode else TmpNode := FDropNode.Parent; Accept := AllowMove(TmpNode, FDragNode); end; end; end; end; procedure TfrmTemplateEditor.tvTreeDragDrop(Sender, Source: TObject; X, Y: Integer); var Src, Template, Item: TTemplate; SIdx, idx: integer; TmpNode: TTreeNode; begin if(assigned(FDragNode)) and (assigned(FDropNode)) and (FDragNode <> FDropNode) then begin Item := TTemplate(FDragNode.Data); if(FDropInto) then begin TmpNode := FDropNode; idx := 0; end else begin TmpNode := FDropNode.Parent; idx := TTemplate(FDropNode.Parent.Data).Items.IndexOf(FDropNode.Data); end; if(AllowMove(TmpNode, FDragNode) and (idx >= 0)) then begin Template := TTemplate(TmpNode.Data); if(Template <> FDragNode.Parent.Data) and (Template.Items.IndexOf(Item) >= 0) then InfoBox(Template.PrintName + ' already contains the ' + Item.PrintName + ' template.', 'Error', MB_OK or MB_ICONERROR) else begin Src := TTemplate(FDragNode.Parent.Data); Sidx := Src.Items.IndexOf(Item); if CanClone(TmpNode) then begin if(Clone(TmpNode)) then Template := TTemplate(TmpNode.Data); if assigned(Template) and Template.CanModify then begin if(Sidx >= 0) and (FDragNode.TreeView = FDropNode.TreeView) and (not FCopying) then // if same tree delete source begin if CanClone(FDragNode.Parent) then begin if(Clone(FDragNode.Parent)) then Src := TTemplate(FDragNode.Parent.Data); if assigned(Src) and Src.CanModify then begin Src.Items.Delete(Sidx); if(Template = Src) then Src := nil; end else Src := nil; end else Src := nil; end else Src := nil; if(idx > 0) then idx := TTemplate(FDropNode.Parent.Data).Items.IndexOf(FDropNode.Data); Template.Items.Insert(idx, Item); if(TTreeView(FDropNode.TreeView) = tvShared) then begin Item.PersonalOwner := 0; tvPersonal.Invalidate; end; TTreeView(FDragNode.TreeView).Selected := FDragNode; TTreeView(FDragNode.TreeView).SetFocus; Resync([Src, Template]); btnApply.Enabled := TRUE; end; end; end; end; end; end; procedure TfrmTemplateEditor.Resync(const Templates: array of TTemplate); var i, j: integer; NodeList: TStringList; TemplateList: TStringList; Node: TTreeNode; tmpl: TTemplate; NodeID: string; begin NodeList := TStringList.Create; try TemplateList := TStringList.Create; try for i := low(Templates) to high(Templates) do begin tmpl := Templates[i]; if(assigned(tmpl)) then begin for j := 0 to tmpl.Nodes.Count-1 do begin Node := TTreeNode(tmpl.Nodes.Objects[j]); if(NodeList.IndexOfObject(Node) < 0) then begin NodeID := IntToStr(Node.Level); NodeID := copy('000',1,4-length(NodeID))+NodeID+U+tmpl.Nodes[j]; TemplateList.AddObject(NodeID,tmpl); NodeList.AddObject(NodeId,Node); end; end; end; end; { By Sorting by Node Level, we prevent a Resync of nodes deeper within the heirchary } NodeList.Sort; for i := 0 to NodeList.Count-1 do begin NodeID := NodeList[i]; Node := TTreeNode(NodeList.Objects[i]); j := TemplateList.IndexOf(NodeID); if(j >= 0) then begin tmpl := TTemplate(TemplateList.Objects[j]); NodeID := Piece(NodeID,U,2); if(tmpl.Nodes.IndexOf(NodeID) >= 0) then begin if(Node.TreeView = tvShared) then dmodShared.Resync(Node, not cbShHide.Checked, FSharedEmptyNodeCount) else if(Node.TreeView = tvPersonal) then dmodShared.Resync(Node, not cbPerHide.Checked, FPersonalEmptyNodeCount); end; end; end; finally TemplateList.Free; end; finally NodeList.Free; end; EnableNavControls; if((assigned(FCurTree)) and (assigned(FCurTree.Selected))) then tvTreeChange(FCurTree, FCurTree.Selected) else tvPersonal.Selected := tvPersonal.Items.GetFirstNode; FCopyNode := nil; end; procedure TfrmTemplateEditor.sbCopyLeftClick(Sender: TObject); begin if(assigned(tvPersonal.Selected)) then begin if(not assigned(tvShared.Selected)) then tvShared.Selected := tvShared.Items.GetFirstNode; FDragNode := tvPersonal.Selected; FDropNode := tvShared.Selected; FDropInto := (TTemplate(FDropNode.Data).RealType in AllTemplateFolderTypes); tvTreeDragDrop(tvPersonal, tvShared, 0,0); end; end; procedure TfrmTemplateEditor.sbCopyRightClick(Sender: TObject); begin if(assigned(tvShared.Selected)) then begin if(not assigned(tvPersonal.Selected)) then tvPersonal.Selected := tvPersonal.Items.GetFirstNode; FDragNode := tvShared.Selected; FDropNode := tvPersonal.Selected; FDropInto := (TTemplate(FDropNode.Data).RealType in AllTemplateFolderTypes); tvTreeDragDrop(tvShared, tvPersonal, 0,0); end; end; function TfrmTemplateEditor.AllowMove(ADropNode, ADragNode: TTreeNode): boolean; var i: integer; TmpNode: TTreeNode; DragTemplate, DropTemplate: TTemplate; begin if(assigned(ADropNode) and assigned(ADragNode)) then begin DropTemplate := TTemplate(ADropNode.Data); DragTemplate := TTemplate(ADragNode.Data); if IsTemplateLocked(ADropNode) then Result := FALSE else Result := (DragTemplate.RealType in [ttDoc, ttGroup, ttClass]); if(Result) then begin if(FCopying) then begin if(DropTemplate.Items.IndexOf(DragTemplate) >= 0) then Result := FALSE; end else if((assigned(ADragNode.Parent)) and (ADropNode <> ADragNode.Parent) and (DropTemplate.Items.IndexOf(DragTemplate) >= 0)) then Result := FALSE; end; if(Result) then begin for i := 0 to DropTemplate.Nodes.Count-1 do begin TmpNode := TTreeNode(DropTemplate.Nodes.Objects[i]); while (Result and (assigned(TmpNode.Parent))) do begin if(TmpNode.Data = DragTemplate) then Result := FALSE else TmpNode := TmpNode.Parent; end; if(not Result) then break; end; end; end else Result := FALSE; end; function TfrmTemplateEditor.Clone(Node: TTreeNode): boolean; var idx: integer; Prnt, OldT, NewT: TTemplate; PNode: TTreeNode; ok: boolean; begin Result := FALSE; if((assigned(Node)) and (TTreeView(Node.TreeView) = tvPersonal)) then begin OldT := TTemplate(Node.Data); if(OldT.PersonalOwner <> User.DUZ) then begin PNode := Node.Parent; Prnt := nil; if (assigned(PNode)) then begin ok := CanClone(PNode); if ok then begin Clone(PNode); Prnt := TTemplate(PNode.Data); ok := Prnt.CanModify; end; end else ok := TRUE; if ok then begin BtnApply.Enabled := TRUE; Result := TRUE; NewT := OldT.Clone(User.DUZ); OldT.RemoveNode(Node); MarkDeleted(OldT); Node.Data := NewT; NewT.AddNode(Node); if(assigned(Prnt)) then begin idx := Prnt.Items.IndexOf(OldT); if(idx >= 0) then Prnt.Items[idx] := NewT; end; tvPersonal.Invalidate; ShowTemplateType(NewT); end; end; end; end; procedure TfrmTemplateEditor.reBoilChange(Sender: TObject); var DoInfo, DoRefresh: boolean; TmpBPlate: string; Template: TTemplate; x: integer; begin if((not FUpdating) and (assigned(FCurTree)) and (assigned(FCurTree.Selected))) then begin Template := TTemplate(FCurTree.Selected.Data); TmpBPlate := reBoil.Lines.Text; if(Template.Boilerplate <> TmpBPlate) then begin if CanClone(FCurTree.Selected) then begin DoRefresh := Clone(FCurTree.Selected); if(DoRefresh) then Template := TTemplate(FCurTree.Selected.Data); if assigned(Template) and Template.CanModify then begin DoInfo := FALSE; if(Template.Boilerplate = '') or (TmpBPlate = '') then DoInfo := TRUE; Template.Boilerplate := TmpBPlate; TTemplate(FCurTree.Selected.Data).Gap := StrToIntDef(edtGap.Text, 0); if(Template.RealType = ttGroup) then begin reGroupBP.Text := Template.FullBoilerplate; end; if(DoRefresh) then begin tvShared.Invalidate; tvPersonal.Invalidate; end; if(DoInfo) then begin x := reBoil.SelStart; ShowInfo(FCurTree.Selected); reBoil.SelStart := x; end; end; end; btnApply.Enabled := TRUE; // reBoil.Lines.Text := Template.Boilerplate; end; end; end; procedure TfrmTemplateEditor.SharedEditing; begin {$IFDEF OwnerScan} lblPerOwner.Visible := FCanEditShared; cboOwner.Visible := FCanEditShared; {$ELSE} lblPerOwner.Visible := FALSE; cboOwner.Visible := FALSE; {$ENDIF} sbCopyLeft.Visible := FCanEditShared; if(not FCanEditShared) then cbShHide.Checked := TRUE; cbShHide.Visible := FCanEditShared; sbShDelete.Visible := FCanEditShared; sbShUp.Visible := FCanEditShared; sbShDown.Visible := FCanEditShared; tvShared.ReadOnly := not FCanEditShared; MoveCopyButtons; tvTreeChange(FCurTree, FCurTree.Selected); end; procedure TfrmTemplateEditor.cbEditSharedClick(Sender: TObject); begin FCanEditShared := cbEditShared.Checked; SharedEditing; end; procedure TfrmTemplateEditor.popTemplatesPopup(Sender: TObject); var Tree: TTreeView; Node: TTreeNode; FindOn: boolean; Txt: string; begin FFromMainMenu := FALSE; Tree := GetTree; Node := Tree.Selected; Tree.Selected := Node; // This line prevents selected from changing after menu closes mnuCollapseTree.Enabled := dmodShared.NeedsCollapsing(Tree); if(Tree = tvShared) then begin Txt := 'Shared'; FindOn := FFindShOn; mnuNodeDelete.Enabled := ((sbShDelete.Visible) and (sbShDelete.Enabled)); end else begin Txt := 'Personal'; FindOn := FFindPerOn; mnuNodeDelete.Enabled := ((sbPerDelete.Visible) and (sbPerDelete.Enabled)); end; mnuFindTemplates.Checked := FindOn; mnuCollapseTree.Caption := 'Collapse '+Txt+' &Tree'; mnuFindTemplates.Caption := '&Find '+Txt+' Templates'; if(assigned(Tree) and assigned(Tree.Selected) and assigned(Tree.Selected.Data)) then begin mnuNodeCopy.Enabled := (TTemplate(Tree.Selected.Data).RealType in [ttDoc, ttGroup, ttClass]); mnuNodeSort.Enabled := (TTemplate(Tree.Selected.Data).RealType in AllTemplateFolderTypes) and (Tree.Selected.HasChildren) and (Tree.Selected.GetFirstChild.GetNextSibling <> nil); end else begin mnuNodeCopy.Enabled := FALSE; mnuNodeSort.Enabled := FALSE; end; FPasteNode := Tree.Selected; mnuNodePaste.Enabled := PasteOK; mnuNodeNew.Enabled := btnNew.Enabled; mnuNodeAutoGen.Enabled := btnNew.Enabled; end; procedure TfrmTemplateEditor.mnuCollapseTreeClick(Sender: TObject); begin if(GetTree = tvShared) then begin tvShared.Selected := tvShared.Items.GetFirstNode; tvShared.FullCollapse; end else begin tvPersonal.Selected := tvShared.Items.GetFirstNode; tvPersonal.FullCollapse; end; end; procedure TfrmTemplateEditor.mnuFindTemplatesClick(Sender: TObject); var Tree: TTreeView; begin Tree := GetTree; if(Tree = tvShared) then begin FFindShOn := not FFindShOn; pnlShSearch.Visible := FFindShOn; if(FFindShOn) then begin edtShSearch.SetFocus; btnShFind.Enabled := (edtShSearch.Text <> ''); end; end else begin FFindPerOn := not FFindPerOn; pnlPerSearch.Visible := FFindPerOn; if(FFindPerOn) then begin edtPerSearch.SetFocus; btnPerFind.Enabled := (edtPerSearch.Text <> ''); end; end; SetFindNext(Tree, FALSE); end; procedure TfrmTemplateEditor.ShowTemplateType(Template: TTemplate); begin if(Template.PersonalOwner > 0) then gbProperties.Caption := 'Personal' else gbProperties.Caption := 'Shared'; gbProperties.Caption := gbProperties.Caption + PropText; end; function TfrmTemplateEditor.GetTree: TTreeView; begin if(FFromMainMenu) then Result := FMainMenuTree else begin if(TTemplateTreeType(PopupComponent(popTemplates, popTemplates).Tag) = ttShared) then Result := tvShared else Result := tvPersonal; end; end; procedure TfrmTemplateEditor.btnFindClick(Sender: TObject); var Found: boolean; edtSearch: TEdit; FindNext: boolean; FindWholeWords: boolean; FindCase: boolean; Tree: TTreeView; LastFoundNode, TmpNode: TTreeNode; S1,S2: string; begin if(TTemplateTreeType(TButton(Sender).Tag) = ttShared) then begin Tree := tvShared; edtSearch := edtShSearch; FindNext := FFindShNext; FindWholeWords := cbShWholeWords.Checked; FindCase := cbShMatchCase.Checked; LastFoundNode := FLastFoundShNode; if(FSharedEmptyNodeCount > 0) then begin FInternalHiddenExpand := TRUE; try tvShared.Items.GetFirstNode.Expand(TRUE); finally FInternalHiddenExpand := FALSE; end; end; end else begin Tree := tvPersonal; edtSearch := edtPerSearch; FindNext := FFindPerNext; FindWholeWords := cbPerWholeWords.Checked; FindCase := cbPerMatchCase.Checked; LastFoundNode := FLastFoundPerNode; if(FPersonalEmptyNodeCount > 0) then begin FInternalHiddenExpand := TRUE; try tvPersonal.Items.GetFirstNode.Expand(TRUE); finally FInternalHiddenExpand := FALSE; end; end; end; if(edtSearch.text <> '') then begin if((FindNext) and assigned (LastFoundNode)) then TmpNode := LastFoundNode.GetNext else TmpNode := Tree.Items.GetFirstNode; Found := FALSE; if(assigned(TmpNode)) then begin S1 := edtSearch.Text; if(not FindCase) then S1 := UpperCase(S1); while (assigned(TmpNode) and (not Found)) do begin S2 := TmpNode.Text; if(not FindCase) then S2 := UpperCase(S2); Found := SearchMatch(S1, S2, FindWholeWords); if(not Found) then TmpNode := TmpNode.GetNext; end; end; if(Found) then begin if(Tree = tvShared) then FLastFoundShNode := TmpNode else FLastFoundPerNode := TmpNode; SetFindNext(Tree, TRUE); Tree.Selected := TmpNode; end else begin if(FindNext) then S1 := '' else S1 := ' "' + edtSearch.Text + '" was not Found.'; SetFindNext(Tree, FALSE); InfoBox('Search Complete.' + S1, 'Information', MB_OK or MB_ICONINFORMATION); end; end; edtSearch.SetFocus; end; procedure TfrmTemplateEditor.edtSearchChange(Sender: TObject); begin if(TTemplateTreeType(TEdit(Sender).Tag) = ttShared) then begin btnShFind.Enabled := (edtShSearch.Text <> ''); SetFindNext(tvShared, FALSE); end else begin btnPerFind.Enabled := (edtPerSearch.Text <> ''); SetFindNext(tvPersonal, FALSE); end; end; procedure TfrmTemplateEditor.SetFindNext(const Tree: TTreeView; const Value: boolean); begin if(Tree = tvShared) then begin if(FFindShNext <> Value) then begin FFindShNext := Value; if(FFindShNext) then btnShFind.Caption := 'Find Next' else btnShFind.Caption := 'Find'; end; end else begin if(FFindPerNext <> Value) then begin FFindPerNext := Value; if(FFindPerNext) then btnPerFind.Caption := 'Find Next' else btnPerFind.Caption := 'Find'; end; end; end; procedure TfrmTemplateEditor.edtShSearchEnter(Sender: TObject); begin btnShFind.Default := TRUE; end; procedure TfrmTemplateEditor.edtShSearchExit(Sender: TObject); begin btnShFind.Default := FALSE; end; procedure TfrmTemplateEditor.edtPerSearchEnter(Sender: TObject); begin btnPerFind.Default := TRUE; end; procedure TfrmTemplateEditor.edtPerSearchExit(Sender: TObject); begin btnPerFind.Default := FALSE; end; procedure TfrmTemplateEditor.btnOKClick(Sender: TObject); begin if(ScanNames) then begin if(SaveAllTemplates) then begin FOK2Close := TRUE; ModalResult := mrOK; end else BtnApply.Enabled := BackupDiffers; end; end; procedure TfrmTemplateEditor.FormShow(Sender: TObject); begin if(FFirstShow) then begin FUpdating := FALSE; FFirstShow := FALSE; if(FFocusName) then begin edtName.SetFocus; edtName.SelectAll; end; pnlBoilerplateResize(Self); end; end; procedure TfrmTemplateEditor.mnuBPInsertObjectClick(Sender: TObject); var i: integer; DoIt: boolean; begin if(not assigned(frmTemplateObjects)) then begin dmodShared.LoadTIUObjects; frmTemplateObjects := TfrmTemplateObjects.Create(Self); DoIt := TRUE; if (UserTemplateAccessLevel <> taEditor) then begin UpdatePersonalObjects; if FPersonalObjects.Count > 0 then begin DoIt := FALSE; for i := 0 to dmodShared.TIUObjects.Count-1 do if FPersonalObjects.IndexOf(Piece(dmodShared.TIUObjects[i],U,2)) >= 0 then frmTemplateObjects.cboObjects.Items.Add(dmodShared.TIUObjects[i]); end; end; if DoIt then frmTemplateObjects.cboObjects.Items.Assign(dmodShared.TIUObjects); frmTemplateObjects.Font := Font; frmTemplateObjects.re := reBoil; frmTemplateObjects.AutoLongLines := AutoLongLines; end; frmTemplateObjects.Show; end; procedure TfrmTemplateEditor.mnuBPErrorCheckClick(Sender: TObject); begin FBPOK := FALSE; if(reBoil.Lines.Count > 0) then begin if(dmodShared.TemplateOK(FCurTree.Selected.Data,'OK')) then begin TestBoilerplate(reBoil.Lines); if(RPCBrokerV.Results.Count > 0) then InfoBox('Boilerplate Contains Errors:'+CRLF+CRLF+ RPCBrokerV.Results.Text, 'Error', MB_OK or MB_ICONERROR) else begin FBPOK := TRUE; if(assigned(Sender)) then InfoBox('No Errors Found in Boilerplate.', 'Information', MB_OK or MB_ICONINFORMATION); end; end; end; end; procedure TfrmTemplateEditor.popBoilerplatePopup(Sender: TObject); var tryOK, ok: boolean; begin ok := not reBoil.ReadOnly; mnuBPInsertObject.Enabled := ok; mnuBPInsertField.Enabled := ok; mnuBPPaste.Enabled := (ok and Clipboard.HasFormat(CF_TEXT)); if(ok) then ok := (reBoil.Lines.Count > 0); tryOK := (reBoil.Lines.Count > 0) or ((pnlGroupBP.Visible) and (reGroupBP.Lines.Count > 0)); mnuBPErrorCheck.Enabled := tryOK; mnuBPTry.Enabled := tryOK; mnuBPSpellCheck.Enabled := ok and SpellCheckAvailable; mnuBPCheckGrammar.Enabled := ok and SpellCheckAvailable; mnuBPCopy.Enabled := (reBoil.SelLength > 0); mnuBPCut.Enabled := (ok and (reBoil.SelLength > 0)); mnuBPSelectAll.Enabled := (reBoil.Lines.Count > 0); mnuBPUndo.Enabled := (reBoil.Perform(EM_CANUNDO, 0, 0) <> 0); end; function TfrmTemplateEditor.ScanNames: boolean; var Errors: TList; msg: string; i: integer; Node: TTreeNode; procedure ScanTree(Tree: TTreeView); begin Node := Tree.Items.GetFirstNode; while (assigned(Node)) do begin if(Node.Text <> EmptyNodeText) and (assigned(Node.Data)) then begin if(BadTemplateName(Node.Text)) then Errors.Add(Node); end; Node := Node.GetNext; end; end; begin Errors := TList.Create; try ScanTree(tvShared); ScanTree(tvPersonal); if(Errors.Count > 0) then begin if(Errors.Count > 1) then msg := IntToStr(Errors.Count) + ' Templates have invalid names' else msg := 'Template has an invalid name'; msg := msg + ': '; for i := 0 to Errors.Count-1 do begin if(i > 0) then msg := msg + ', '; Node := TTreeNode(Errors[i]); msg := msg + Node.Text; Node.MakeVisible; end; msg := msg + '.' + BadNameText; InfoBox(msg, 'Error', MB_OK or MB_ICONERROR); TTreeView(Node.TreeView).Selected := TTreeNode(Errors[0]); end; finally Result := (Errors.Count = 0); Errors.Free; end; end; procedure TfrmTemplateEditor.btnCancelClick(Sender: TObject); begin FOK2Close := TRUE; end; procedure TfrmTemplateEditor.FormCloseQuery(Sender: TObject; var CanClose: Boolean); var ans: word; begin if(not FOK2Close) and (BackupDiffers) then begin ans := InfoBox('Save Changes?', 'Confirmation', MB_YESNOCANCEL or MB_ICONQUESTION); if(ans = IDCANCEL) then CanClose := FALSE else if(ans = IDYES) then begin CanClose := FALSE; if(ScanNames) then begin if(SaveAllTemplates) then CanClose := TRUE else BtnApply.Enabled := BackupDiffers; end; end; end; end; procedure TfrmTemplateEditor.mnuBPSpellCheckClick(Sender: TObject); begin SpellCheckForControl(reBoil); end; procedure TfrmTemplateEditor.splBoilMoved(Sender: TObject); begin pnlBoilerplateResize(Self); end; procedure TfrmTemplateEditor.edtGapKeyPress(Sender: TObject; var Key: Char); begin if(not (Key in ['0','1','2','3'])) then Key := #0; end; procedure TfrmTemplateEditor.edtNameExit(Sender: TObject); var Warn: boolean; begin Warn := (ActiveControl <> btnCancel) and (BadTemplateName(edtName.Text)); if(Warn and ((ActiveControl = sbShDelete) or (ActiveControl = sbPerDelete))) then begin if((assigned(FCurTree)) and (assigned(FCurTree.Selected))) then Warn := not AutoDel(TTemplate(FCurTree.Selected.Data)); end; if(Warn) then begin InfoBox('Template has an invalid name: ' + edtName.Text + '.' + BadNameText, 'Error', MB_OK or MB_ICONERROR); edtName.SetFocus; end; end; procedure TfrmTemplateEditor.tmrAutoScrollTimer(Sender: TObject); const EdgeScroll = 16; var TopNode: TTreeNode; Redraw: boolean; TmpPt: TPoint; ht: THitTests; HPos, RMax: integer; begin if(assigned(FDropNode)) then begin TopNode := FDropNode.TreeView.TopItem; Redraw := FALSE; TmpPt := FDropNode.TreeView.ScreenToClient(Mouse.CursorPos); if(TopNode = FDropNode) and (TopNode <> TTreeView(FDropNode.TreeView).Items.GetFirstNode) then begin FDropNode.TreeView.TopItem := TopNode.GetPrevVisible; Redraw := TRUE; end else begin RMax := FDropNode.TreeView.ClientHeight - EdgeScroll; if((TmpPt.Y > RMax) and (FDropNode.GetNextVisible <> nil)) then begin TORTreeView(FDropNode.TreeView).VertScrollPos := TORTreeView(FDropNode.TreeView).VertScrollPos + 1; Redraw := TRUE; end; end; if(FLastDropNode <> FDropNode) then begin if((assigned(FDropNode)) and (FDropNode.GetNext = nil)) then Redraw := TRUE else if((assigned(FLastDropNode)) and (FLastDropNode.GetNext = nil)) then Redraw := TRUE; FLastDropNode := FDropNode; FDragOverCount := 0; end else begin if(FDropNode.HasChildren) and (not FDropNode.Expanded) then begin ht := FDropNode.TreeView.GetHitTestInfoAt(TmpPt.X, TmpPt.Y); if(htOnButton in ht) then begin inc(FDragOverCount); if(FDragOverCount > 4) then begin TopNode := FDropNode.TreeView.TopItem; FDropNode.Expand(FALSE); FDropNode.TreeView.TopItem := TopNode; FDragOverCount := 0; Redraw := TRUE; end; end else FDragOverCount := 0; end; if(not Redraw) then begin HPos := TORTreeView(FDropNode.TreeView).HorzScrollPos; if(HPos > 0) and (TmpPt.X < EdgeScroll) then begin TORTreeView(FDropNode.TreeView).HorzScrollPos := TORTreeView(FDropNode.TreeView).HorzScrollPos - EdgeScroll; Redraw := TRUE; end else begin RMax := FDropNode.TreeView.ClientWidth - EdgeScroll; if(TmpPt.X > RMax) then begin TORTreeView(FDropNode.TreeView).HorzScrollPos := TORTreeView(FDropNode.TreeView).HorzScrollPos + EdgeScroll; Redraw := TRUE; end; end; end; end; if(Redraw) then begin TmpPt := Mouse.CursorPos; // Wiggling the mouse causes needed windows messages to fire inc(TmpPt.X); Mouse.CursorPos := TmpPt; dec(TmpPt.X); Mouse.CursorPos := TmpPt; FDropNode.TreeView.Invalidate; end; end; end; procedure TfrmTemplateEditor.tvTreeStartDrag(Sender: TObject; var DragObject: TDragObject); begin FDropNode := nil; FLastDropNode := nil; FDragOverCount := 0; tmrAutoScroll.Enabled := TRUE; end; procedure TfrmTemplateEditor.tvTreeEndDrag(Sender, Target: TObject; X, Y: Integer); begin tmrAutoScroll.Enabled := FALSE; end; procedure TfrmTemplateEditor.mnuGroupBPCopyClick(Sender: TObject); begin reGroupBP.CopyToClipboard; end; procedure TfrmTemplateEditor.popGroupPopup(Sender: TObject); begin mnuGroupBPCopy.Enabled := (pnlGroupBP.Visible and (reGroupBP.SelLength > 0)); mnuGroupBPSelectAll.Enabled := (pnlGroupBP.Visible and (reGroupBP.Lines.Count > 0)); end; procedure TfrmTemplateEditor.mnuBPCutClick(Sender: TObject); begin reBoil.CutToClipboard; end; procedure TfrmTemplateEditor.mnuBPCopyClick(Sender: TObject); begin reBoil.CopyToClipboard; end; procedure TfrmTemplateEditor.mnuBPPasteClick(Sender: TObject); begin reBoil.SelText := Clipboard.AsText; end; procedure TfrmTemplateEditor.mnuGroupBPSelectAllClick(Sender: TObject); begin reGroupBP.SelectAll; end; procedure TfrmTemplateEditor.mnuBPSelectAllClick(Sender: TObject); begin reBoil.SelectAll; end; procedure TfrmTemplateEditor.mnuNodeDeleteClick(Sender: TObject); begin if(FCurTree = tvShared) and (sbShDelete.Visible) and (sbShDelete.Enabled) then sbDeleteClick(sbShDelete) else if(FCurTree = tvPersonal) and (sbPerDelete.Visible) and (sbPerDelete.Enabled) then sbDeleteClick(sbPerDelete); end; procedure TfrmTemplateEditor.mnuNodeCopyClick(Sender: TObject); begin if(assigned(FCurTree)) then FCopyNode := FCurTree.Selected else FCopyNode := nil; end; procedure TfrmTemplateEditor.mnuNodePasteClick(Sender: TObject); begin if(PasteOK) then begin FDragNode := FCopyNode; FDropNode := FPasteNode; FDropInto := (TTemplate(FDropNode.Data).RealType in AllTemplateFolderTypes); FCopying := TRUE; try tvTreeDragDrop(tvShared, tvPersonal, 0, 0); finally FCopying := FALSE; end; end; FCopyNode := nil; end; function TfrmTemplateEditor.PasteOK: boolean; var OldCopying: boolean; Node: TTreeNode; begin Result := assigned(FCopyNode) and assigned(FPasteNode); if(Result) then Result := (FTreeControl[TTemplateTreeType(FPasteNode.TreeView.Tag), tcDel].Visible); if(Result) then begin OldCopying := FCopying; FCopying := TRUE; try Node := FPasteNode; if(TTemplate(Node.Data).RealType = ttDoc) then Node := Node.Parent; Result := AllowMove(Node, FCopyNode); finally FCopying := OldCopying; end; end; end; procedure TfrmTemplateEditor.mnuBPUndoClick(Sender: TObject); begin reBoil.Perform(EM_UNDO, 0, 0); end; procedure TfrmTemplateEditor.tvTreeKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); begin if(Key = VK_DELETE) then begin if(Sender = tvShared) then begin if(sbShDelete.Visible and sbShDelete.Enabled) then sbDeleteClick(sbShDelete); end else begin if(sbPerDelete.Visible and sbPerDelete.Enabled) then sbDeleteClick(sbPerDelete); end; end; //Code Added to provide CTRL Key access for 508 compliance GRE 3/03 if (ssCtrl in Shift) and (Key = VK_A) then reBoil.SelectAll else if (ssCtrl in Shift) and (Key = VK_C) then reBoil.CopyToClipboard else if (ssCtrl in Shift) and (Key = VK_E) then mnuBPErrorCheckClick(Self) else if (ssCtrl in Shift) and (Key = VK_F) then mnuBPInsertFieldClick(Self) else if (ssCtrl in Shift) and (Key = VK_G) then GrammarCheckForControl(reBoil) else if (ssCtrl in Shift) and (Key = VK_I) then mnuBPInsertObjectClick(Self) else if (ssCtrl in Shift) and (Key = VK_S) then SpellCheckForControl(reBoil) else if (ssCtrl in Shift) and (Key = VK_T) then mnuBPTryClick(Self) else if (ssCtrl in Shift) and (Key = VK_V) then reBoil.SelText := Clipboard.AsText else if (ssCtrl in Shift) and (Key = VK_X) then reBoil.CutToClipboard else if (ssCtrl in Shift) and (Key = VK_Z) then reBoil.Perform(EM_UNDO, 0, 0); //End of ---- Code Added to provide CTRL Key access for 508 compliance GRE 3/03 end; procedure TfrmTemplateEditor.mnuEditClick(Sender: TObject); var tryOK, ok: boolean; begin if pnlBoilerplate.Visible then begin ok := (not reBoil.ReadOnly); mnuInsertObject.Enabled := ok; mnuInsertField.Enabled := ok; mnuPaste.Enabled := (ok and Clipboard.HasFormat(CF_TEXT)); if(ok) then ok := (reBoil.Lines.Count > 0); tryOK := (reBoil.Lines.Count > 0) or ((pnlGroupBP.Visible) and (reGroupBP.Lines.Count > 0)); mnuErrorCheck.Enabled := tryOK; mnuTry.Enabled := tryOK; mnuSpellCheck.Enabled := ok and SpellCheckAvailable; mnuCheckGrammar.Enabled := ok and SpellCheckAvailable; mnuCopy.Enabled := (reBoil.SelLength > 0); mnuCut.Enabled := (ok and (reBoil.SelLength > 0)); mnuSelectAll.Enabled := (reBoil.Lines.Count > 0); mnuUndo.Enabled := (reBoil.Perform(EM_CANUNDO, 0, 0) <> 0); mnuGroupBoilerplate.Enabled := pnlGroupBP.Visible; end else begin mnuInsertObject.Enabled := FALSE; mnuInsertField.Enabled := FALSE; mnuPaste.Enabled := FALSE; mnuErrorCheck.Enabled := FALSE; mnuTry.Enabled := FALSE; mnuSpellCheck.Enabled := FALSE; mnuCheckGrammar.Enabled := FALSE; mnuCopy.Enabled := FALSE; mnuCut.Enabled := FALSE; mnuSelectAll.Enabled := FALSE; mnuUndo.Enabled := FALSE; mnuGroupBoilerplate.Enabled := FALSE; end; end; procedure TfrmTemplateEditor.mnuGroupBoilerplateClick(Sender: TObject); begin mnuGroupCopy.Enabled := (pnlGroupBP.Visible and (reGroupBP.SelLength > 0)); mnuGroupSelectAll.Enabled := (pnlGroupBP.Visible and (reGroupBP.Lines.Count > 0)); end; procedure TfrmTemplateEditor.cbShFindOptionClick(Sender: TObject); begin SetFindNext(tvShared, FALSE); if(pnlShSearch.Visible) then edtShSearch.SetFocus; end; procedure TfrmTemplateEditor.cbPerFindOptionClick(Sender: TObject); begin SetFindNext(tvPersonal, FALSE); if(pnlPerSearch.Visible) then edtPerSearch.SetFocus; end; procedure TfrmTemplateEditor.mnuTemplateClick(Sender: TObject); var Tree: TTreeView; begin FFromMainMenu := TRUE; Tree := FCurTree; if(assigned(Tree) and assigned(Tree.Selected)) then begin if(Tree = tvShared) then mnuTDelete.Enabled := ((sbShDelete.Visible) and (sbShDelete.Enabled)) else mnuTDelete.Enabled := ((sbPerDelete.Visible) and (sbPerDelete.Enabled)); if(assigned(Tree) and assigned(Tree.Selected) and assigned(Tree.Selected.Data)) then begin mnuTCopy.Enabled := (TTemplate(Tree.Selected.Data).RealType in [ttDoc, ttGroup, ttClass]); mnuSort.Enabled := (TTemplate(Tree.Selected.Data).RealType in AllTemplateFolderTypes) and (Tree.Selected.HasChildren) and (Tree.Selected.GetFirstChild.GetNextSibling <> nil); end else begin mnuTCopy.Enabled := FALSE; mnuSort.Enabled := FALSE; end; FPasteNode := Tree.Selected; mnuTPaste.Enabled := PasteOK; end else begin mnuTCopy.Enabled := FALSE; mnuTPaste.Enabled := FALSE; mnuTDelete.Enabled := FALSE; mnuSort.Enabled := FALSE; end; mnuNewTemplate.Enabled := btnNew.Enabled; mnuAutoGen.Enabled := btnNew.Enabled; mnuFindShared.Checked := FFindShOn; mnuFindPersonal.Checked := FFindPerOn; mnuShCollapse.Enabled := dmodShared.NeedsCollapsing(tvShared); mnuPerCollapse.Enabled := dmodShared.NeedsCollapsing(tvPersonal); end; procedure TfrmTemplateEditor.mnuFindSharedClick(Sender: TObject); begin FMainMenuTree := tvShared; mnuFindTemplatesClick(tvShared); end; procedure TfrmTemplateEditor.mnuFindPersonalClick(Sender: TObject); begin FMainMenuTree := tvPersonal; mnuFindTemplatesClick(tvPersonal); end; procedure TfrmTemplateEditor.mnuShCollapseClick(Sender: TObject); begin FMainMenuTree := tvShared; mnuCollapseTreeClick(tvShared); end; procedure TfrmTemplateEditor.mnuPerCollapseClick(Sender: TObject); begin FMainMenuTree := tvPersonal; mnuCollapseTreeClick(tvPersonal); end; procedure TfrmTemplateEditor.pnlShSearchResize(Sender: TObject); begin if((cbShMatchCase.Width + cbShWholeWords.Width) > pnlShSearch.Width) then cbShWholeWords.Left := cbShMatchCase.Width else cbShWholeWords.Left := pnlShSearch.Width - cbShWholeWords.Width; end; procedure TfrmTemplateEditor.pnlPerSearchResize(Sender: TObject); begin if((cbPerMatchCase.Width + cbPerWholeWords.Width) > pnlPerSearch.Width) then cbPerWholeWords.Left := cbPerMatchCase.Width else cbPerWholeWords.Left := pnlPerSearch.Width - cbPerWholeWords.Width; end; procedure TfrmTemplateEditor.pnlPropertiesResize(Sender: TObject); begin btnNew.Width := pnlProperties.Width; end; procedure TfrmTemplateEditor.mbMainResize(Sender: TObject); begin pnlMenu.Width := mbMain.Width + 3; end; procedure TfrmTemplateEditor.mnuBPCheckGrammarClick(Sender: TObject); begin GrammarCheckForControl(reBoil); end; procedure TfrmTemplateEditor.mnuSortClick(Sender: TObject); var Tree: TTreeView; begin Tree := FCurTree; if(assigned(Tree) and assigned(Tree.Selected) and Tree.Selected.HasChildren) then begin TTemplate(Tree.Selected.Data).SortChildren; Resync([TTemplate(Tree.Selected.Data)]); btnApply.Enabled := TRUE; end; end; procedure TfrmTemplateEditor.pnlBoilerplateCanResize(Sender: TObject; var NewWidth, NewHeight: Integer; var Resize: Boolean); begin if(NewHeight < 40) then Resize := FALSE; end; function TfrmTemplateEditor.AutoDel(Template: TTemplate): boolean; begin if(assigned(Template)) then Result := (((Template.ID = '0') or (Template.ID = '')) and (Template.PrintName = NewTemplateName) and (Template.Boilerplate = '')) else Result := FALSE; end; procedure TfrmTemplateEditor.mnuBPTryClick(Sender: TObject); var R: TRect; Move: boolean; tmpl: TTemplate; txt: String; begin mnuBPErrorCheckClick(nil); if(FBPOK) or (reBoil.Lines.Count = 0) then begin Move := assigned(frmTemplateView); if(Move) then begin R := frmTemplateView.BoundsRect; frmTemplateView.Free; frmTemplateView := nil; end; tmpl := TTemplate(FCurTree.Selected.Data); tmpl.TemplatePreviewMode := TRUE; // Prevents "Are you sure?" dialog when canceling txt := tmpl.Text; if(not tmpl.DialogAborted) then ShowTemplateData(Self, tmpl.PrintName ,txt); if(Move) then frmTemplateView.BoundsRect := R; tmpl.TemplatePreviewMode := FALSE; end; end; procedure TfrmTemplateEditor.mnuAutoGenClick(Sender: TObject); var AName, AText: string; begin dmodShared.LoadTIUObjects; UpdatePersonalObjects; GetAutoGenText(AName, AText, FPersonalObjects); if(AName <> '') and (AText <> '') then begin btnNewClick(Self); TTemplate(FBtnNewNode.Data).PrintName := AName; TTemplate(FBtnNewNode.Data).Boilerplate := AText; ShowInfo(FBtnNewNode); edtNameOldChange(Self); end; end; procedure TfrmTemplateEditor.reNotesChange(Sender: TObject); var Template: TTemplate; DoRefresh: boolean; begin if((not FUpdating) and (assigned(FCurTree)) and (assigned(FCurTree.Selected))) then begin if CanClone(FCurTree.Selected) then begin DoRefresh := Clone(FCurTree.Selected); Template := TTemplate(FCurTree.Selected.Data); if assigned(Template) and Template.CanModify then begin Template.Description := reNotes.Lines.Text; UpdateApply(Template); if(DoRefresh) then begin tvShared.Invalidate; tvPersonal.Invalidate; end; end; end; btnApply.Enabled := TRUE; // reNotes.Lines.Text := Template.Description; end; end; procedure TfrmTemplateEditor.mnuNotesUndoClick(Sender: TObject); begin reNotes.Perform(EM_UNDO, 0, 0); end; procedure TfrmTemplateEditor.mnuNotesCutClick(Sender: TObject); begin reNotes.CutToClipboard; end; procedure TfrmTemplateEditor.mnuNotesCopyClick(Sender: TObject); begin reNotes.CopyToClipboard; end; procedure TfrmTemplateEditor.mnuNotesPasteClick(Sender: TObject); begin reNotes.SelText := Clipboard.AsText; end; procedure TfrmTemplateEditor.mnuNotesSelectAllClick(Sender: TObject); begin reNotes.SelectAll; end; procedure TfrmTemplateEditor.mnuNotesGrammarClick(Sender: TObject); begin GrammarCheckForControl(reNotes); end; procedure TfrmTemplateEditor.mnuNotesSpellingClick(Sender: TObject); begin SpellCheckForControl(reNotes); end; procedure TfrmTemplateEditor.popNotesPopup(Sender: TObject); var ok: boolean; begin ok := not reNotes.ReadOnly; mnuNotesPaste.Enabled := (ok and Clipboard.HasFormat(CF_TEXT)); if(ok) then ok := (reNotes.Lines.Count > 0); mnuNotesSpelling.Enabled := ok and SpellCheckAvailable; mnuNotesGrammar.Enabled := ok and SpellCheckAvailable; mnuNotesCopy.Enabled := (reNotes.SelLength > 0); mnuNotesCut.Enabled := (ok and (reNotes.SelLength > 0)); mnuNotesSelectAll.Enabled := (reNotes.Lines.Count > 0); mnuNotesUndo.Enabled := (reNotes.Perform(EM_CANUNDO, 0, 0) <> 0); end; procedure TfrmTemplateEditor.cbNotesClick(Sender: TObject); begin pnlNotes.Visible := cbNotes.Checked; splNotes.Visible := cbNotes.Checked; splNotes.Top := pnlNotes.Top-3; pnlBoilerplateResize(Self); end; procedure TfrmTemplateEditor.cbDisplayOnlyClick(Sender: TObject); begin cbClick(TCheckBox(Sender), BPDisplayOnlyFld); end; procedure TfrmTemplateEditor.cbFirstLineClick(Sender: TObject); begin cbClick(TCheckBox(Sender), BPFirstLineFld); end; procedure TfrmTemplateEditor.cbOneItemOnlyClick(Sender: TObject); begin cbClick(TCheckBox(Sender), BPOneItemOnlyFld); end; procedure TfrmTemplateEditor.cbHideDlgItemsClick(Sender: TObject); begin cbClick(TCheckBox(Sender), BPHideDlgItemsFld); end; procedure TfrmTemplateEditor.cbHideItemsClick(Sender: TObject); begin cbClick(TCheckBox(Sender), BPHideItemsFld); end; procedure TfrmTemplateEditor.cbClick(Sender: TCheckBox; Index: integer); var Template: TTemplate; begin if((not FUpdating) and (assigned(FCurTree)) and (assigned(FCurTree.Selected))) then begin if CanClone(FCurTree.Selected) then begin Clone(FCurTree.Selected); Template := TTemplate(FCurTree.Selected.Data); if assigned(Template) and Template.CanModify then begin case Index of BPDisplayOnlyFld: Template.DisplayOnly := Sender.Checked; BPFirstLineFld: Template.FirstLine := Sender.Checked; BPOneItemOnlyFld: Template.OneItemOnly := Sender.Checked; BPHideDlgItemsFld: Template.HideDlgItems := Sender.Checked; BPHideItemsFld: Template.HideItems := Sender.Checked; BPIndentFld: Template.IndentItems := Sender.Checked; BPLockFld: Template.Lock := Sender.Checked; end; UpdateApply(Template); end; end; end; end; procedure TfrmTemplateEditor.cbIndentClick(Sender: TObject); begin cbClick(TCheckBox(Sender), BPIndentFld); end; procedure TfrmTemplateEditor.mnuToolsClick(Sender: TObject); begin mnuEditTemplateFields.Enabled := CanEditTemplateFields; mnuImportTemplate.Enabled := btnNew.Enabled; mnuExportTemplate.Enabled := (assigned(FCurTree) and assigned(FCurTree.Selected) and assigned(FCurTree.Selected.Data)); end; procedure TfrmTemplateEditor.mnuEditTemplateFieldsClick(Sender: TObject); begin if assigned(frmTemplateObjects) then frmTemplateObjects.Hide; if assigned(frmTemplateFields) then frmTemplateFields.Hide; if EditDialogFields and assigned(frmTemplateFields) then FreeAndNil(frmTemplateFields); end; procedure TfrmTemplateEditor.mnuBPInsertFieldClick(Sender: TObject); begin if(not assigned(frmTemplateFields)) then begin frmTemplateFields := TfrmTemplateFields.Create(Self); frmTemplateFields.Font := Font; frmTemplateFields.re := reBoil; frmTemplateFields.AutoLongLines := AutoLongLines; end; frmTemplateFields.Show; end; procedure TfrmTemplateEditor.UpdateInsertsDialogs; begin if assigned(frmTemplateObjects) then frmTemplateObjects.UpdateStatus; if assigned(frmTemplateFields) then frmTemplateFields.UpdateStatus; end; procedure TfrmTemplateEditor.mnuExportTemplateClick(Sender: TObject); var Tmpl, Flds: TStringList; i: integer; XMLDoc: IXMLDOMDocument; err: boolean; begin err := FALSE; if(assigned(FCurTree) and assigned(FCurTree.Selected) and assigned(FCurTree.Selected.Data)) then begin dlgExport.FileName := ValidFileName(TTemplate(FCurTree.Selected.Data).PrintName); if dlgExport.Execute then begin Tmpl := TStringList.Create; try Flds := TStringList.Create; try Tmpl.Add('<'+XMLHeader+'>'); if TTemplate(FCurTree.Selected.Data).CanExportXML(Tmpl, Flds, 2) then begin if (Flds.Count > 0) then begin ExpandEmbeddedFields(Flds); Flds.Assign(ExportTemplateFields(Flds)); for i := 0 to Flds.Count-1 do Flds[i] := ' ' + Flds[i]; Tmpl.AddStrings(Flds); end; {if} Tmpl.Add(''); try XMLDoc := CoDOMDocument.Create; try XMLDoc.preserveWhiteSpace := TRUE; XMLDoc.LoadXML(Tmpl.Text); XMLDoc.Save(dlgExport.FileName); finally XMLDoc := nil; end; except InfoBox(Format(NoIE5, ['Export']), NoIE5Header, MB_OK); err := TRUE; end; if not err then InfoBox('Template ' + TTemplate(FCurTree.Selected.Data).PrintName + ' Exported.', 'Template Exported', MB_OK); end; finally Flds.Free; end; finally Tmpl.Free; end; end; end; end; procedure TfrmTemplateEditor.mnuImportTemplateClick(Sender: TObject); const Filter1 = 'Template Files|*.txml'; WordFilter = '|Word Documents|*.doc;*.dot'; Filter2 = '|XML Files|*.xml|All Files|*.*'; var XMLDoc: IXMLDOMDocument; RootElement: IXMLDOMElement; ImportedTemplate: TTemplate; AppData, Flds, ResultSet: TStringList; tmp,j,p3: string; err, ok, changes, xmlerr: boolean; i: integer; choice: word; procedure ClearFields; begin Flds.Text := ''; ResultSet.Text := ''; end; begin tmp := Filter1; err := FALSE; if WordImportActive then tmp := tmp + WordFilter; tmp := tmp + Filter2; dlgImport.Filter := tmp; if btnNew.Enabled and dlgImport.Execute then begin tmp := ExtractFileExt(dlgImport.FileName); if(WordImportActive and ((CompareText(tmp,'.doc') = 0) or (CompareText(tmp,'.dot') = 0))) then AppData := TStringList.Create else AppData := nil; try try XMLDoc := CoDOMDocument.Create; except InfoBox(Format(NoIE5, ['Import']), NoIE5Header, MB_OK); exit; end; try if assigned(AppData) then begin try ok := GetXMLFromWord(dlgImport.FileName, AppData); except ok := FALSE; err := TRUE; end; end else ok := TRUE; if ok and assigned(XMLDoc) then begin XMLDoc.preserveWhiteSpace := TRUE; if assigned(AppData) then XMLDoc.LoadXML(AppData.Text) else XMLDoc.Load(dlgImport.FileName); RootElement := XMLDoc.DocumentElement; if not assigned(RootElement) then XMLImportError(0); try if(RootElement.tagName <> XMLHeader)then XMLImportError(0) else begin ImportedTemplate := nil; FXMLTemplateElement := FindXMLElement(RootElement, XMLTemplateTag); if assigned(FXMLTemplateElement) then begin FXMLFieldElement := FindXMLElement(RootElement, XMLTemplateFieldsTag); if(assigned(FXMLFieldElement)) then begin Flds := TStringList.Create; ResultSet := TStringList.Create; try Flds.Text := FXMLFieldElement.Get_XML; choice := IDOK; changes := FALSE; Application.ProcessMessages; if not BuildTemplateFields(Flds) then //Calls RPC to transfer all field XML choice := IDCANCEL; //for processing Flds.Text := ''; Application.ProcessMessages; if choice = IDOK then CheckTemplateFields(Flds); if Flds.Count > 0 then begin for i := 1 to Flds.Count do begin j := piece(Flds[i-1],U,2); if (j = '0') or (j = '2') then begin p3 := piece(Flds[i-1],U,3); if p3 = 'XML FORMAT ERROR' then choice := IDCANCEL; changes := TRUE; if j = '2' then begin j := Flds[i-1]; SetPiece(j,U,2,'1'); Flds[i-1] := j end; end; end; end else choice := IDCANCEL; if choice <> IDOK then InfoBox(iMessage2+iMessage3, 'Error', MB_OK or MB_ICONERROR) else if (not CanEditTemplateFields) AND changes {(there is at least one new field)} then begin choice := InfoBox(iMessage, 'Warning', MB_OKCANCEL or MB_ICONWARNING); Flds.Text := ''; end; if choice <> IDCANCEL then begin FImportingFromXML := TRUE; try btnNewClick(Self); ImportedTemplate := TTemplate(FBtnNewNode.Data); finally FImportingFromXML := FALSE; end; {try} Application.ProcessMessages; if assigned(ImportedTemplate) and (Flds.Count > 0) then if not ImportLoadedFields(ResultSet) then begin InfoBox(iMessage2+iMessage3, 'Error', MB_OK or MB_ICONERROR); ClearFields; choice := IDCANCEL; end;//if if Flds.Count = 0 then choice := IDCANCEL; end {if choice <> mrCancel} else ClearFields; xmlerr := FALSE; if (Flds.Count > 0) and (ResultSet.Count > 0) and (Flds.Count = ResultSet.Count) then for i := 0 to Flds.Count-1 do begin if piece(ResultSet[i],U,2) = '0' then begin j := piece(Flds[i],U,1) + U + '0' + U + piece(ResultSet[i],U,3); Flds[i] := j; end end else xmlerr := TRUE; if xmlerr and (choice <> IDCANCEL) then begin InfoBox(iMessage2, 'Warning', MB_OK or MB_ICONWARNING); ClearFields; end; i := 0; while (i < Flds.Count) do begin if Piece(Flds[i], U, 2) <> '0' then Flds.Delete(i) else inc(i); end;//while if(Flds.Count > 0) then begin if assigned(frmTemplateFields) then FreeAndNil(frmTemplateFields); ImportedTemplate.UpdateImportedFieldNames(Flds); if not assigned(AppData) then begin for i := 0 to Flds.Count-1 do Flds[i] := ' Field "' + Piece(Flds[i],U,1) + '" has been renamed to "'+ Piece(Flds[i],U,3) + '"'; if Flds.Count = 1 then tmp := 'A template field has' else tmp := IntToStr(Flds.Count) + ' template fields have'; Flds.Insert(0,tmp + ' been imported with the same name as'); Flds.Insert(1,'existing template fields, but with different field definitions.'); Flds.Insert(2,'These imported template fields have been renamed as follows:'); Flds.Insert(3,''); InfoBox(Flds.Text, 'Information', MB_OK or MB_ICONINFORMATION); end; end; finally Flds.Free; ResultSet.Free; end; end else {There are no fields to consider...} begin FImportingFromXML := TRUE; try btnNewClick(Self); ImportedTemplate := TTemplate(FBtnNewNode.Data); finally FImportingFromXML := FALSE; end; {try} end; end; if assigned(ImportedTemplate) then ShowInfo(FBtnNewNode); end; finally RootElement := nil; end; end; finally XMLDoc := nil; end; finally if assigned(AppData) then begin AppData.Free; if err then InfoBox('An error occured while Importing Word Document. Make sure Word is closed and try again.','Import Error', MB_OK); end; end; end; end; procedure TfrmTemplateEditor.cbxTypeDrawItem(Control: TWinControl; Index: Integer; Rect: TRect; State: TOwnerDrawState); var ImgIdx: integer; begin cbxType.Canvas.FillRect(Rect); case IdxForced[FForceContainer, Index] of tiTemplate: ImgIdx := 4; tiFolder: ImgIdx := 3; tiGroup: ImgIdx := 5; tiDialog: ImgIdx := 23; tiRemDlg: ImgIdx := 27; tiCOMObj: ImgIdx := 28; else ImgIdx := ord(tiNone); end; if ImgIdx >= 0 then dmodShared.imgTemplates.Draw(cbxType.Canvas, Rect.Left+1, Rect.Top+1, ImgIdx); if Index >= 0 then cbxType.Canvas.TextOut(Rect.Left+21, Rect.Top+2, cbxType.Items[Index]); end; procedure TfrmTemplateEditor.cbxTypeChange(Sender: TObject); var i,tg: integer; Template: TTemplate; ttyp: TTemplateType; Node: TTreeNode; idx: TTypeIndex; begin if((not FUpdating) and (assigned(FCurTree)) and (assigned(FCurTree.Selected))) then begin tg := cbxType.ItemIndex; if tg >= 0 then begin if CanClone(FCurTree.Selected) then begin idx := IdxForced[FForceContainer, tg]; if(idx = tiRemDlg) and (not (GetLinkType(FCurTree.Selected) in [ltNone, ltTitle])) then begin FUpdating := TRUE; try cbxType.ItemIndex := ord(tiTemplate); finally FUpdating := FALSE; end; ShowMessage('Can not assign a Reminder Dialog to a Reason for Request'); end else begin Clone(FCurTree.Selected); Template := TTemplate(FCurTree.Selected.Data); if assigned(Template) and Template.CanModify then begin ttyp := TypeTag[idx]; if(not FForceContainer) or (not (idx in [tiTemplate, tiRemDlg])) then begin if(ttyp = ttDialog) then begin Template.Dialog := TRUE; ttyp := ttGroup; end else Template.Dialog := FALSE; Template.RealType := ttyp; if(Template.RealType = ttDoc) and (idx = tiRemDlg) then Template.IsReminderDialog := TRUE else Template.IsReminderDialog := FALSE; if(Template.RealType = ttDoc) and (idx = tiCOMObj) then Template.IsCOMObject := TRUE else Template.IsCOMObject := FALSE; UpdateApply(Template); end; for i := 0 to Template.Nodes.Count-1 do begin Node := TTreeNode(Template.Nodes.Objects[i]); Node.ImageIndex := dmodShared.ImgIdx(Node); Node.SelectedIndex := dmodShared.ImgIdx(Node); end; tvShared.Invalidate; tvPersonal.Invalidate; Node := FCurTree.Selected; tvTreeChange(TTreeView(Node.TreeView), Node); end; end; end; end; end; end; procedure TfrmTemplateEditor.cbxRemDlgsChange(Sender: TObject); var Template: TTemplate; begin if((not FUpdating) and (assigned(FCurTree)) and (assigned(FCurTree.Selected)) and FCanDoReminders) then begin if CanClone(FCurTree.Selected) then begin Clone(FCurTree.Selected); Template := TTemplate(FCurTree.Selected.Data); if assigned(Template) and Template.CanModify then begin if cbxRemDlgs.ItemIndex < 0 then Template.ReminderDialog := '' else Template.ReminderDialog := cbxRemDlgs.Items[cbxRemDlgs.ItemIndex]; UpdateApply(Template); end; end; end; end; procedure TfrmTemplateEditor.mnuTemplateIconLegendClick(Sender: TObject); begin ShowIconLegend(ilTemplates, TRUE); end; procedure TfrmTemplateEditor.cbLongLinesClick(Sender: TObject); begin pnlBoilerplateResize(Self); pnlBoilerplateResize(Self); // Second Call is Needed! end; procedure TfrmTemplateEditor.AutoLongLines(Sender: TObject); begin cbLongLines.Checked := TRUE; end; procedure TfrmTemplateEditor.UpdatePersonalObjects; var i: integer; begin if not assigned(FPersonalObjects) then begin FPersonalObjects := TStringList.Create; GetAllowedPersonalObjects; for i := 0 to RPCBrokerV.Results.Count-1 do FPersonalObjects.Add(Piece(RPCBrokerV.Results[i],U,1)); FPersonalObjects.Sorted := TRUE; end; end; (*function TfrmTemplateEditor.ModifyAllowed(const Node: TTreeNode): boolean; var tmpl: TTemplate; function GetFirstPersonalNode(Node: TTreeNode): TTreeNode; begin Result := Node; if assigned(Node.Parent) and (TTemplate(Node.Data).PersonalOwner <> User.DUZ) then Result := GetFirstPersonalNode(Node.Parent); end; begin if(assigned(Node)) then begin if (TTreeView(Node.TreeView) = tvPersonal) then Result := TTemplate(GetFirstPersonalNode(Node).Data).CanModify else Result := TRUE; end else Result := FALSE; if Result then begin tmpl := TTemplate(Node.Data); if (tmpl.PersonalOwner = 0) or (tmpl.PersonalOwner = User.DUZ) then Result := tmpl.CanModify; end; end; *) { Returns TRUE if Cloning is not needed or if Cloning is needed and the top personal Node in the tree is locked. } function TfrmTemplateEditor.CanClone(const Node: TTreeNode): boolean; var Template: TTemplate; function GetFirstPersonalNode(Node: TTreeNode): TTreeNode; begin Result := Node; if assigned(Node.Parent) and (TTemplate(Node.Data).PersonalOwner <> User.DUZ) then Result := GetFirstPersonalNode(Node.Parent); end; begin if(assigned(Node)) and assigned(Node.Data) then begin if (TTreeView(Node.TreeView) = tvPersonal) then begin Template := TTemplate(Node.Data); if Template.IsCOMObject or (Template.FileLink <> '') then Result := FALSE else Result := TTemplate(GetFirstPersonalNode(Node).Data).CanModify end else Result := TRUE; end else Result := FALSE; end; procedure TfrmTemplateEditor.UpdateApply(Template: TTemplate); begin if(not btnApply.Enabled) then btnApply.Enabled := Template.Changed; end; procedure TfrmTemplateEditor.TemplateLocked(Sender: TObject); begin Resync([TTemplate(Sender)]); ShowMessage(Format(TemplateLockedText, [TTemplate(Sender).PrintName])); end; procedure TfrmTemplateEditor.cbLockClick(Sender: TObject); begin cbClick(TCheckBox(Sender), BPLockFLD); end; procedure TfrmTemplateEditor.mnuRefreshClick(Sender: TObject); begin if btnApply.Enabled then begin if InfoBox('All changes must be saved before you can Refresh. Save Changes?', 'Confirmation', MB_YESNO or MB_ICONQUESTION) <> IDYES then exit; end; btnApplyClick(Sender); if BtnApply.Enabled then InfoBox('Save not completed - unable to refresh.', 'Error', MB_OK or MB_ICONERROR) else RefreshData; end; procedure TfrmTemplateEditor.RefreshData; var exp1, exp2, s1, s2, t1, t2: string; focus: TWinControl; begin focus := FCurTree; exp1 := tvShared.GetExpandedIDStr(1, ';'); exp2 := tvPersonal.GetExpandedIDStr(1, ';'); s1 := tvShared.GetNodeID(TORTreeNode(tvShared.Selected),1,';'); s2 := tvPersonal.GetNodeID(TORTreeNode(tvPersonal.Selected),1,';'); t1 := tvShared.GetNodeID(TORTreeNode(tvShared.TopItem),1,';'); t2 := tvPersonal.GetNodeID(TORTreeNode(tvPersonal.TopItem),1,';'); tvPersonal.Items.BeginUpdate; try tvShared.Items.BeginUpdate; try ReleaseTemplates; tvPersonal.Items.Clear; tvShared.Items.Clear; InitTrees; tvShared.SetExpandedIDStr(1, ';', exp1); tvShared.TopItem := tvShared.FindPieceNode(t1,1,';'); tvShared.Selected := tvShared.FindPieceNode(s1,1,';'); tvPersonal.SetExpandedIDStr(1, ';', exp2); tvPersonal.TopItem := tvPersonal.FindPieceNode(t2,1,';'); tvPersonal.Selected := tvPersonal.FindPieceNode(s2,1,';'); finally tvShared.Items.EndUpdate; end; finally tvPersonal.Items.EndUpdate; end; ActiveControl := focus; end; procedure TfrmTemplateEditor.InitTrees; begin LoadTemplateData; if(not assigned(RootTemplate)) then SaveTemplate(AddTemplate('0^R^A^Shared Templates'),-1); if(not assigned(MyTemplate)) then AddTemplate('0^P^A^My Templates^^^'+IntToStr(User.DUZ)); dmodShared.AddTemplateNode(tvPersonal, FPersonalEmptyNodeCount, MyTemplate); dmodShared.AddTemplateNode(tvShared, FSharedEmptyNodeCount, RootTemplate); if (UserTemplateAccessLevel = taEditor) then begin if CanEditLinkType(ttTitles) then dmodShared.AddTemplateNode(tvShared, FSharedEmptyNodeCount, TitlesTemplate); if CanEditLinkType(ttConsults) then dmodShared.AddTemplateNode(tvShared, FSharedEmptyNodeCount, ConsultsTemplate); if CanEditLinkType(ttProcedures) then dmodShared.AddTemplateNode(tvShared, FSharedEmptyNodeCount, ProceduresTemplate); end; end; procedure TfrmTemplateEditor.reResizeRequest(Sender: TObject; Rect: TRect); var R: TRect; begin R := TRichEdit(Sender).ClientRect; if (FLastRect.Right <> R.Right) or (FLastRect.Bottom <> R.Bottom) or (FLastRect.Left <> R.Left) or (FLastRect.Top <> R.Top) then begin FLastRect := R; pnlBoilerplateResize(Self); end; end; procedure TfrmTemplateEditor.reBoilSelectionChange(Sender: TObject); begin UpdateXY(reBoil, lblBoilCol, lblBoilRow); end; procedure TfrmTemplateEditor.reGroupBPSelectionChange(Sender: TObject); begin UpdateXY(reGroupBP, lblGroupCol, lblGroupRow); end; procedure TfrmTemplateEditor.UpdateXY(re: TRichEdit; lblX, lblY: TLabel); var p: TPoint; begin p := re.CaretPos; lblY.Caption := 'Line: ' + inttostr(p.y + 1); lblX.Caption := 'Column: ' + inttostr(p.x + 1); end; procedure TfrmTemplateEditor.cbxCOMObjChange(Sender: TObject); var Template: TTemplate; begin if((not FUpdating) and (assigned(FCurTree)) and (assigned(FCurTree.Selected)) and FCanDoCOMObjects and (FCurTree = tvShared)) then begin Template := TTemplate(FCurTree.Selected.Data); if assigned(Template) and Template.CanModify then begin if cbxCOMObj.ItemIndex < 0 then Template.COMObject := 0 else Template.COMObject := cbxCOMObj.ItemID; UpdateApply(Template); end; end; end; procedure TfrmTemplateEditor.edtCOMParamChange(Sender: TObject); var Template: TTemplate; begin if((not FUpdating) and (assigned(FCurTree)) and (assigned(FCurTree.Selected)) and FCanDoCOMObjects and (FCurTree = tvShared)) then begin Template := TTemplate(FCurTree.Selected.Data); if assigned(Template) and Template.CanModify then begin Template.COMParam := edtCOMParam.Text; UpdateApply(Template); end; end; end; function TfrmTemplateEditor.GetLinkType(const ANode: TTreeNode): TTemplateLinkType; var Node: TTreeNode; begin Result := ltNone; if assigned(ANode) then begin if(not assigned(ANode.Data)) or (TTemplate(ANode.Data).RealType <> ttClass) then begin Node := ANode.Parent; repeat if assigned(Node) and assigned(Node.Data) then begin if (TTemplate(Node.Data).FileLink <> '') then Node := nil else if (TTemplate(Node.Data).RealType in AllTemplateLinkTypes) then begin case TTemplate(Node.Data).RealType of ttTitles: Result := ltTitle; ttConsults: Result := ltConsult; ttProcedures: Result := ltProcedure; end; end else Node := Node.Parent; end else Node := nil; until(Result <> ltNone) or (not assigned(Node)); end; end; end; procedure TfrmTemplateEditor.cbxLinkNeedData(Sender: TObject; const StartFrom: String; Direction, InsertAt: Integer); var tmpSL: TStringList; i: integer; tmp: string; begin tmpSL := TStringList.Create; try case TTemplateLinkType(pnlLink.Tag) of ltTitle: tmpSL.Assign(SubSetOfAllTitles(StartFrom, Direction)); // ltConsult: ltProcedure: begin tmpSL.Assign(SubSetOfProcedures(StartFrom, Direction)); for i := 0 to tmpSL.Count-1 do begin tmp := tmpSL[i]; setpiece(tmp,U,1,piece(piece(tmp,U,4),';',1)); tmpSL[i] := tmp; end; end; end; cbxLink.ForDataUse(tmpSL); finally tmpSL.Free; end; end; procedure TfrmTemplateEditor.cbxLinkChange(Sender: TObject); var Template,LinkTemplate: TTemplate; begin if((not FUpdating) and (assigned(FCurTree)) and (assigned(FCurTree.Selected)) and (FCurTree = tvShared)) then begin Template := TTemplate(FCurTree.Selected.Data); if assigned(Template) and Template.CanModify then begin if cbxLink.ItemIEN > 0 then begin LinkTemplate := GetLinkedTemplate(cbxLink.ItemID, TTemplateLinkType(pnlLink.tag)); if (assigned(LinkTemplate) and (LinkTemplate <> Template)) then begin ShowMessage(GetLinkName(cbxLink.ItemID, TTemplateLinkType(pnlLink.tag)) + ' is already assigned to another template.'); cbxLink.ItemIndex := -1; end; Template.FileLink := ConvertFileLink(cbxLink.ItemID, TTemplateLinkType(pnlLink.tag)); if Template.LinkName <> '' then edtName.Text := copy(Template.LinkName,1,edtName.MaxLength); end else Template.FileLink := ''; UpdateApply(Template); end; end; end; procedure TfrmTemplateEditor.cbxLinkSynonymCheck(Sender: TObject; const Text: String; var IsSynonym: Boolean); var LinkTemplate: TTemplate; var IEN: string; begin IsSynonym := FALSE; if pnlLink.Visible and assigned(FShowingTemplate) then begin IEN := Piece(Text,#9,30); if IEN <> '' then begin LinkTemplate := GetLinkedTemplate(IEN, TTemplateLinkType(pnlLink.Tag)); IsSynonym := (assigned(LinkTemplate) and (LinkTemplate <> FShowingTemplate)); end else IsSynonym := FALSE; end; end; procedure TfrmTemplateEditor.reBoilKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState); begin if FNavigatingTab then begin if ssShift in Shift then FindNextControl(Sender as TWinControl, False, True, False).SetFocus //previous control else if ssCtrl in Shift then FindNextControl(Sender as TWinControl, True, True, False).SetFocus; //next control FNavigatingTab := False; end; if (key = VK_ESCAPE) then begin FindNextControl(Sender as TWinControl, False, True, False).SetFocus; //previous control key := 0; end; end; procedure TfrmTemplateEditor.reBoilKeyPress(Sender: TObject; var Key: Char); begin if FNavigatingTab then Key := #0; //Disable shift-tab processinend; end; procedure TfrmTemplateEditor.reBoilKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); begin //The navigating tab controls were inadvertantently adding tab characters //This should fix it FNavigatingTab := (Key = VK_TAB) and ([ssShift,ssCtrl] * Shift <> []); if FNavigatingTab then Key := 0; end; end.