////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

unit main;

interface

uses
  SysUtils, Forms, msxmldom, Classes, Controls, Dialogs, ToolWin, ComCtrls,
  ExtCtrls, Menus, xmldom, XMLIntf, XMLDoc, ImgList,
  CM2CMLXPlugTypes, CM2GenPlugTypes, CM2VisPlugTypes,
  DesktopImage, GDIPenable, Engine, ObjectInspector, Registry,
  Windows, ActnList, XPMan, AppEvnts, graphics, ProcsAndTypes, lplFindFile,
  tutorialSystem, splash, templatesystem, EditorVariableManager;

type
  TPreFullScreen = record
   Left: Integer;
   Top: Integer;
   Height: Integer;
   Width: Integer;
   WS: TWindowState;
  end;
  ToeMain = class(TForm)
    MainMenu1: TMainMenu;
    File1: TMenuItem;
    Exit1: TMenuItem;
    N1: TMenuItem;
    SaveAs1: TMenuItem;
    Save1: TMenuItem;
    Open1: TMenuItem;
    New1: TMenuItem;
    StatusBar1: TStatusBar;
    ImageList1: TImageList;
    CML: TXMLDocument;
    ScrollBox1: TScrollBox;
    OpenDialog1: TOpenDialog;
    SaveDialog1: TSaveDialog;
    DesktopImage1: TDesktopImage;
    GDIPenable1: TGDIPenable;
    Popup_ScrollBox: TPopupMenu;
    addFormLink: TMenuItem;
    Reloaddesktop1: TMenuItem;
    Popup_FormPanels: TPopupMenu;
    Addvisual1: TMenuItem;
    N2: TMenuItem;
    DeleteForm1: TMenuItem;
    Popup_Visuals: TPopupMenu;
    Addsensor1: TMenuItem;
    N3: TMenuItem;
    Delete1: TMenuItem;
    StartUpTimer: TTimer;
    Debug1: TMenuItem;
    Help1: TMenuItem;
    About1: TMenuItem;
    View1: TMenuItem;
    ObjectInspector1: TMenuItem;
    PluginPalette1: TMenuItem;
    CodeSnippetWindow1: TMenuItem;
    SensorListingWindow1: TMenuItem;
    temp1: TMenuItem;
    PluginParameterDetails1: TMenuItem;
    ActionList1: TActionList;
    FullScreenEdit: TAction;
    Shape1: TShape;
    N4: TMenuItem;
    FullScreenEdit1: TMenuItem;
    XPManifest1: TXPManifest;
    Panel1: TPanel;
    ToolBar1: TToolBar;
    ToolButton1: TToolButton;
    nodetypelist: TImageList;
    N5: TMenuItem;
    N6: TMenuItem;
    Preferences1: TMenuItem;
    ApplicationEvents1: TApplicationEvents;
    N7: TMenuItem;
    Bringtofront1: TMenuItem;
    Sendtoback1: TMenuItem;
    ToolButton2: TToolButton;
    ToolButton3: TToolButton;
    ToolButton4: TToolButton;
    ToolButton5: TToolButton;
    ToolButton6: TToolButton;
    ToolButton7: TToolButton;
    ToolButton8: TToolButton;
    ToolButton9: TToolButton;
    ToolButton10: TToolButton;
    ToolButton12: TToolButton;
    ToolButton13: TToolButton;
    actionOI: TAction;
    actionPluginPalette: TAction;
    actionSnippet: TAction;
    actionSensorListing: TAction;
    actionParameterDetails: TAction;
    N8: TMenuItem;
    Presets: TMenuItem;
    Simple1: TMenuItem;
    Advanced1: TMenuItem;
    Hardcore1: TMenuItem;
    actionSave: TAction;
    actionLoad: TAction;
    actionNew: TAction;
    Reopen1: TMenuItem;
    actionDelete: TAction;
    actionQuit: TAction;
    N9: TMenuItem;
    tutorials1: TMenuItem;
    find: TlplFindFile;
    ObjectTracer1: TMenuItem;
    N10: TMenuItem;
    Extendedhints1: TMenuItem;
    actionCopy: TAction;
    actionPaste: TAction;
    Edit1: TMenuItem;
    Copy1: TMenuItem;
    Paste1: TMenuItem;
    actionCut: TAction;
    Cut1: TMenuItem;
    SSCreationTools1: TMenuItem;
    ShowEventPaths1: TMenuItem;
    N11: TMenuItem;
    ReplaceWith1: TMenuItem;
    N12: TMenuItem;
    N13: TMenuItem;
    Grid2: TMenuItem;
    Show1: TMenuItem;
    SnapTo1: TMenuItem;
    Appearence1: TMenuItem;
    Dots1: TMenuItem;
    Lines1: TMenuItem;
    N14: TMenuItem;
    Grid1: TMenuItem;
    Show2: TMenuItem;
    SnapTo2: TMenuItem;
    Appearance1: TMenuItem;
    Dots2: TMenuItem;
    Lines2: TMenuItem;
    ools1: TMenuItem;
    PlugInManager1: TMenuItem;
    N15: TMenuItem;
    Copy2: TMenuItem;
    Cut2: TMenuItem;
    Paste2: TMenuItem;
    N16: TMenuItem;
    ImportCML1: TMenuItem;
    N17: TMenuItem;
    Copy3: TMenuItem;
    N18: TMenuItem;
    Paste3: TMenuItem;
    Cut3: TMenuItem;
    actionLeft: TAction;
    actionRight: TAction;
    actionUp: TAction;
    actionDown: TAction;
    DumpObjectlist1: TMenuItem;
    ToolButton11: TToolButton;
    ToolButton14: TToolButton;
    ToolButton15: TToolButton;
    ToolButton16: TToolButton;
    N19: TMenuItem;
    BringToFront2: TMenuItem;
    SendToBack2: TMenuItem;
    N20: TMenuItem;
    OptimizeFormSize1: TMenuItem;
    ToolButton17: TToolButton;
    ToolButton18: TToolButton;
    AddToTemplate1: TMenuItem;
    N21: TMenuItem;
    AddToTemplate2: TMenuItem;
    N22: TMenuItem;
    QuickAlign1: TMenuItem;
    QuickResize1: TMenuItem;
    op1: TMenuItem;
    Bottom1: TMenuItem;
    Left1: TMenuItem;
    Right1: TMenuItem;
    StrechHorizontally1: TMenuItem;
    StrechVertically1: TMenuItem;
    actionObjectBrowser: TAction;
    ToolButton19: TToolButton;
    AddEvent1: TMenuItem;
    oggleObjectBrowserWindow1: TMenuItem;
    procedure FormCreate(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure Exit1Click(Sender: TObject);
    procedure DesktopImage1MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
    procedure Reloaddesktop1Click(Sender: TObject);
    procedure DeleteForm1Click(Sender: TObject);
    procedure addFormBtnClick(Sender: TObject);
    procedure StartUpTimerTimer(Sender: TObject);
    procedure ShowfullCML1Click(Sender: TObject);
    procedure About1Click(Sender: TObject);
    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
    procedure FormShow(Sender: TObject);
    procedure FullScreenEditExecute(Sender: TObject);
    procedure addFormLinkClick(Sender: TObject);
    procedure Save1Click(Sender: TObject);
    procedure Open1Click(Sender: TObject);
    procedure ApplicationEvents1Exception(Sender: TObject; E: Exception);
    procedure Bringtofront1Click(Sender: TObject);
    procedure Sendtoback1Click(Sender: TObject);
    procedure ApplicationEvents1Hint(Sender: TObject);
    procedure ToolButton4Click(Sender: TObject);
    procedure ToolButton5Click(Sender: TObject);
    procedure actionOIExecute(Sender: TObject);
    procedure actionPluginPaletteExecute(Sender: TObject);
    procedure actionSnippetExecute(Sender: TObject);
    procedure actionSensorListingExecute(Sender: TObject);
    procedure actionParameterDetailsExecute(Sender: TObject);
    procedure Simple1Click(Sender: TObject);
    procedure Advanced1Click(Sender: TObject);
    procedure Hardcore1Click(Sender: TObject);
    procedure SaveAs1Click(Sender: TObject);
    procedure Preferences1Click(Sender: TObject);
    procedure Delete1Click(Sender: TObject);
    procedure actionDeleteExecute(Sender: TObject);
    procedure findFound(Sender: TObject; Folder: String;
      FileInfo: TSearchRec);
    procedure findComplete(Sender: TObject);
    procedure ObjectTracer1Click(Sender: TObject);
    procedure ApplicationEvents1ShowHint(var HintStr: String;
      var CanShow: Boolean; var HintInfo: THintInfo);
    procedure Extendedhints1Click(Sender: TObject);
    procedure actionCopyExecute(Sender: TObject);
    procedure actionPasteExecute(Sender: TObject);
    procedure actionCutExecute(Sender: TObject);
    procedure ShowEventPaths1Click(Sender: TObject);
    procedure DesktopImage1Click(Sender: TObject);
    procedure Popup_ScrollBoxPopup(Sender: TObject);
    procedure Show1Click(Sender: TObject);
    procedure SnapTo1Click(Sender: TObject);
    procedure Dots1Click(Sender: TObject);
    procedure Lines1Click(Sender: TObject);
    procedure Show2Click(Sender: TObject);
    procedure Popup_FormPanelsPopup(Sender: TObject);
    procedure SnapTo2Click(Sender: TObject);
    procedure Dots2Click(Sender: TObject);
    procedure Lines2Click(Sender: TObject);
    procedure FormMouseWheel(Sender: TObject; Shift: TShiftState;
      WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
    procedure PlugInManager1Click(Sender: TObject);
    procedure ImportCML1Click(Sender: TObject);
    procedure actionLeftExecute(Sender: TObject);
    procedure FormActivate(Sender: TObject);
    procedure actionRightExecute(Sender: TObject);
    procedure actionUpExecute(Sender: TObject);
    procedure actionDownExecute(Sender: TObject);
    procedure DumpObjectlist1Click(Sender: TObject);
    procedure temp1Click(Sender: TObject);
    procedure BringToFront2Click(Sender: TObject);
    procedure SendToBack2Click(Sender: TObject);
    procedure OptimizeFormSize1Click(Sender: TObject);
    procedure Popup_VisualsPopup(Sender: TObject);
    procedure FormResize(Sender: TObject);
    procedure DesktopImage1MouseMove(Sender: TObject; Shift: TShiftState;
      X, Y: Integer);
    procedure actionNewExecute(Sender: TObject);
    procedure AddToTemplate1Click(Sender: TObject);
    procedure AddToTemplate2Click(Sender: TObject);
    procedure Bottom1Click(Sender: TObject);
    procedure Left1Click(Sender: TObject);
    procedure Right1Click(Sender: TObject);
    procedure op1Click(Sender: TObject);
    procedure StrechHorizontally1Click(Sender: TObject);
    procedure StrechVertically1Click(Sender: TObject);
    procedure actionObjectBrowserExecute(Sender: TObject);
    procedure AddEvent1Click(Sender: TObject);
  private
    SS: TSplashScreen;
    PreFullScreen: TPreFullScreen;
    createFormAtX, createFormAtY: integer;
    fGlobalFilename: String;
    procedure LoadPlugins;
    procedure UnloadPlugins;
    procedure SetGlobalFilename(const Value: String);
    function GETCURRENTSELECTNODE: TEdRawNode;
  public
    LoadThisConfig: String;
    RelaunchCore: Boolean;
    PMLocation: String;
    Select: TSelect;
    vpl: TVISPlugInList;
    gpl: TGenPlugInList;
    xpl: TCMLXPlugInList;
    VESL: TVisEditorSupportList;
    GESL: TGenEditorSupportList;
    FESL: TFormEditorSupportList;
    TemplateList: TTemplateList;
    FormMgr: TEdFormMgr;
    VarMgr: TVarMgr;
    Tree: TEdCM2Tree;
    RecentList: TRecentList;
    TutorialList: TTutorialList;
    Clipboard: TClipboard;
    HintTempDisableRollup: boolean;
    Procedure SelectNode(NodeToSelect: TEdRawNode; ForceUpdate: Boolean = False);
    Procedure SaveFormStatus;
    Procedure LoadFormStatus;
    procedure GetTaskBar(var L, T, H, W: Integer);
    Procedure BuildVisPopup;
    Procedure BuildGenPopup;
    Procedure OnPopup_FormsClick(Sender: TObject);
    Procedure OnPopup_VisualsClick(Sender: TObject);
    Procedure OnPopup_ReplaceVisClick(Sender: TObject);
    Procedure AddSensorsToMenu(ParentItem: TMenuItem; PlugName: String; OnClick: TNotifyEvent);
    Procedure UpdateCaption;
    Procedure OnTreeModified(Sender: TObject);
    Procedure PerformSave(AlwaysShowDialog: boolean);
    Procedure PerformLoad(Filename: String = ''; Import: Boolean = false);
    Procedure OnLoadRecent(Filename: String);
    Property GlobalFilename: String read fGlobalFilename write SetGlobalFilename;
    Property CurrentSelectNode: TEdRawNode read GETCURRENTSELECTNODE;
    Procedure AddToSelected(Node: TEdRawNode);
    Procedure OnDrawSelected(Node: TEdRawNode);
    Procedure OnDrawDeSelected(Node: TEdRawNode);
    Procedure OnSelect(NodesToSelect: TEdRawNodes);
    Procedure OnClipboardClear(Sender: TObject);
    Procedure OnClipboardNewAddition(Sender: TObject);
    Procedure SetHotKeyStates(SelectedForm: TForm);
    Procedure SetSnapping;
    Procedure OnVisMenu(Sender: TObject);
    Procedure CreateNewCML(Sender: TObject);
    Procedure InsertTemplate(ToNode: TEdRawNode; TemplateIndex: Integer);
  end;

const
  CMLVERSION = '1.4';
  cVIS = 0;
  cGEN = 1;
  cEX = 2;
  RegLocation = '\Software\The CoolMon Project\CoolMon2\Editor';
  rawText = 'Text';

var
  oeMain: ToeMain;
  firstRun: Boolean = true;
  Options: TOptions; // Global options
  Debug: Boolean = false; // Global debugstate

implementation

uses
  pluginPalette, CodeSnippet, oi, AboutDlg, VarWin,
  AddWin, ParameterDetailsWin, shellapi, Filter,
  fullscreentoolbar, Preferences, lpl_sysutils, popupHint, CM2EditorsupportInterface,
  ComObj, templatedlg, addTemplate, objbrowsewin, addeventwin;

{$R *.dfm}

{------------------------------------------------------------------------------}

procedure ToeMain.LoadPlugins;
begin
  SS.SetLoading('Loading :: Visual Plugins');
  vpl.LoadAll;
  VESL.BuildFromPlugInList(VPL);
  SS.SetLoading('Loading :: General Plugins');
  gpl.LoadAll;
  GESL.BuildFromPlugInList(GPL);
  SS.SetLoading('Loading :: cmlX Plugins');
  xpl.LoadAll;
end;

procedure ToeMain.UnloadPlugins;
begin
  vpl.UnLoadAll;
  gpl.UnloadAll;
  xpl.UnloadAll;
end;

{------------------------------------------------------------------------------}

procedure ToeMain.Exit1Click(Sender: TObject);
Var
 Reg: TRegistry;
 CoreLoc: String;
begin
 If Tree.Modified then begin
  case MessageDlg('Configuration has been changed, Save ?', mtConfirmation, [mbYes, mbNo, mbCancel], 0) of
   mrCancel: exit;
   mrYes: Begin
           PerformSave(false);
          end;
  end;
 end;
 TutorialList.SetTerminate := true;
 GlobalFilename := ''; // This done to let the recent list save the loaded file
 TemplateList.SaveToFolder(PathToOk(ExtractFilePath(ParamStr(0))) + 'templates');
 SaveOptions;
 SaveFormStatus;
 If RelaunchCore then begin
  Reg := TRegistry.Create;
  Reg.RootKey := HKEY_CURRENT_USER;
  If Reg.OpenKey('\Software\The CoolMon Project\CoolMon2\', false) then begin
   CoreLoc := Reg.ReadString('');
  end;
  FreeAndNil(Reg);
  If fileexists(CoreLoc) then begin
   ExecApp(CoreLoc, '"' + LoadThisConfig + '"');
  end;
 end;
 Application.Terminate;
end;

procedure ToeMain.DesktopImage1MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  case Button of
    mbRight: begin
               createFormAtX := X - ScrollBox1.HorzScrollBar.Position;
               createFormAtY := Y - ScrollBox1.VertScrollBar.Position;
               Popup_ScrollBox.Popup(ClientOrigin.X + createFormAtX, ClientOrigin.Y + ToolBar1.Height + createFormAtY);
             end;
  end;
end;

procedure ToeMain.ReloadDesktop1Click(Sender: TObject);
begin
  with DesktopImage1 do
    begin
      ScrollBox1.Color := GetDesktopColor;
      RefreshDesktopImage;
    end;
end;

procedure ToeMain.DeleteForm1Click(Sender: TObject);
Var
 PNode: TEdRawNode;
 FormNode: TEdFormNode;
begin
 If MessageDlg('Are you sure you wish to delete this form ?', mtConfirmation, [mbYes, mbNo], 0) = mrNo then exit;
 PNode := CurrentSelectNode.Parent;
 FormNode := (CurrentSelectNode as TEdFormNode);
 Select.Clear;
 FormNode.DeleteSelf;
 ObjBrowser.LoadFromNode();
 SelectNode(PNode.Parent);
end;

procedure ToeMain.FormCreate(Sender: TObject);
Var
 I: Integer;
 HAndled: Boolean;
begin
  SS := TSplashScreen.Create(nil);
  SS.SetLoading('Loading :: Options');
  SS.Show;
  LoadThisConfig := '';
  RelaunchCore := false;
  For I := 1 to paramcount do begin
   Handled := false;
   If uppercase(ParamStr(I)) = '/DEBUG' then begin
//    Debug := true;
    Debug1.Visible := true;
    Handled := true;
   end;
   if uppercase(ParamStr(I)) = '/NOSPLASH' then begin
    SS.Hide;
    Handled := true;
   end;
   if uppercase(ParamStr(I)) = '/RELAUNCHCORE' then begin
    Handled := true;
    RelaunchCore := true;
   end;
   If not handled then begin
    LoadThisConfig := paramStr(I);
   end;
  end;
  SS.Update;
  InitOptions;
  LoadOptions;
  If Fileexists(PMLocation) then begin
   PlugInManager1.Enabled := True;
  end
   else
  begin
   PlugInManager1.Enabled := false;
  end;
  SS.SetLoading('Loading :: Desktop Image');
  Panel1.ParentBackground := false;
  Panel1.ParentColor := False;
  Panel1.Height := Toolbar1.Height;
  DoubleBuffered := true;
  with DesktopImage1 do begin
   Width := 0;
   Height := Screen.Height;
   For I := 0 to Screen.MonitorCount - 1 do begin
    Width := Width + Screen.Monitors[I].Width;
   end;
   ScrollBox1.Color := GetDesktopColor;
   RefreshDesktopImage;
   GridLineColor := options.Visual.GridColor;
   GridSpaceX := options.visual.GridSpacingX;
   GridSpaceY := options.visual.GridSpacingY;
   ShowGrid := options.visual.ShowGrid;
   ShowDot := options.Visual.ShowDot;
  end;
  SS.SetLoading('Loading :: Form Manager');
  FormMgr := TEdFormMgr.Create(self);
  SS.SetLoading('Loading :: Variable Manager');
  VarMgr := TVarMgr.Create(false);
  SS.SetLoading('Loading :: Creating Plugin Lists');
  FESL := TFormEditorSupportList.Create;
  VESL := TVisEditorSupportList.Create;
  GESL := TGenEditorSupportList.Create;
  vpl := TVisPlugInList.Create;
  gpl := TGenPlugInList.Create(Handle);
  xpl := TCMLxPlugInList.Create(Handle);
  LoadPlugins;
  SS.SetLoading('Loading :: Recent List');
  RecentList := TRecentList.Create(Reopen1, OnLoadRecent, false);
  RecentList.MaxLimit := Options.Files.RecentLength;
  RecentList.LoadFromReg;
  SS.SetLoading('Loading :: Selection Engine');
  Select := TSelect.Create;
  Select.OnDrawSelected := OnDrawSelected;
  Select.OnDrawDeSelected := OnDrawDeSelected;
  Select.OnSelect := OnSelect;
  SS.SetLoading('Loading :: Clipboard System');
  Clipboard := TClipboard.Create;
  Clipboard.OnClear := OnClipboardClear;
  Clipboard.OnNewAddition := OnClipboardNewAddition;
  Clipboard.Clear;
  SS.SetLoading('Loading :: Templates');
  TemplateList := TTemplateList.Create;
  TemplateList.Folder := PathToOk(ExtractFilePath(ParamStr(0))) + 'templates'; // required for the class to be able to delete the template xml file
  If directoryexists(PathToOk(ExtractFilePath(ParamStr(0))) + 'templates') then begin
   TemplateList.LoadFromFolder(PathToOk(ExtractFilePath(ParamStr(0))) + 'templates');
  end;
  SS.SetLoading('Loading :: Tutorials');
  TutorialList := TTutorialList.Create;
  find.Path := extractfilepath(paramstr(0));
  find.Subs := false;
  find.Search;
end;

procedure ToeMain.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  UnloadPlugins;
  FreeAndNil(vpl);
  FreeAndNil(gpl);
  FreeAndNil(xpl);
end;

procedure ToeMain.addFormBtnClick(Sender: TObject);
Var
 FormNode: TEdFormNode;
begin
 FormNode := Tree.GetDisplayNode.AddFormNode;
 SelectNode(FormNode);
 If TutorialList.WaitingForCallback <> '' then begin
  TutorialList.Callback(sender);
 end;
end;

procedure ToeMain.SelectNode(NodeToSelect: TEdRawNode; ForceUpdate: Boolean = False);
Var
 Nodes: TEdRawNodes;
begin
 Select.CurrentSelectedNode := NodeToSelect;
 If ForceUpdate then begin
  If Select.GetSelected(Nodes) then begin
   OnSelect(Nodes);
  end;
 end;
end;

procedure ToeMain.StartUpTimerTimer(Sender: TObject);
Var
 Reg: TRegistry;
 CreateNew: Boolean;
begin
 BuildVisPopup;
 BuildGenPopup;
 SS.SetLoading('Loading :: Default Values');
 GESL.LoadFromFile(PathToOk(Extractfilepath(ParamStr(0))) + 'DVGeneral.xml');
 VESL.LoadFromFile(PathToOk(Extractfilepath(ParamStr(0))) + 'DVVisual.xml');
 FESL.LoadFromFile(PathToOk(ExtractFilePath(ParamStr(0))) + 'DVForm.xml');
 PrefDlg.LoadDefaultPages;
 SS.SetLoading('Loading :: Interface');
 StartUpTimer.Enabled := false;
 ObjectInspector1.Checked := oeInspector.Visible;
 PluginPalette1.Checked := oePlugin.Visible;
 CodeSnippetWindow1.Checked := snipwin.Visible;
 SensorListingWindow1.Checked := VariableWin.Visible;
 SetSnapping;
 CreateNew := true;
 If Options.Files.LoadLastOnStartup then begin
  Reg := TRegistry.Create;
  Reg.RootKey := HKEY_CURRENT_USER;
  If Reg.OpenKey('\Software\The CoolMon Project\CoolMon2', false) then begin
   If reg.ValueExists('LastConfig') then begin
    CreateNew := false;
    PerformLoad(Reg.ReadString('LastConfig'));
   end;
  end;
  FreeAndNil(Reg);
 end;
 If CreateNew then begin
  CreateNewCML(Sender);
 end;
 SS.Hide;
 SS.Update;
 FreeAndnil(SS);
 If loadthisconfig <> '' then begin
  PerformLoad(loadthisconfig, false);
 end;
 self.SetFocus;
end;

procedure ToeMain.ShowfullCML1Click(Sender: TObject);
begin
 SelectNode(tree.root);
end;

procedure ToeMain.About1Click(Sender: TObject);
Var
 About: TAbout;
begin
 About := TAbout.Create(self);
 About.Execute;
 FreeAndNil(About);
end;

procedure ToeMain.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
 CanClose := false;
 Exit1Click(self);
end;

procedure ToeMain.SaveFormStatus;
Var
 Reg: TRegistry;
 I: Integer;
 N: String;
 A, L, W, H, T: Integer;
 WS: Byte;
 Vis: Boolean;
begin
 If Borderstyle = bsNone then begin
  FullScreenEditExecute(self);
 end;
 oeInspector.SetRoll(true);
 oePlugin.SetRoll(true);
 snipwin.SetRoll(true);
 variablewin.SetRoll(true);
 objbrowser.SetRoll(true);
 Reg := TRegistry.Create;
 Reg.RootKey := HKEY_CURRENT_USER;
 Reg.OpenKey(RegLocation, true);
 Reg.WriteString('', paramstr(0));
 Reg.OpenKey(RegLocation + '\Forms', true);
 For I := 0 to Application.ComponentCount - 1 do begin
  If (Application.Components[I] is TForm) then begin
   If (Application.Components[I] as TForm).BorderStyle <> bsDialog then begin
    With (Application.Components[I] as TForm) do begin
     Case WindowState of
      wsMaximized: begin
                    WS := 1;
                    WindowState := wsNormal;
                   end;
      wsMinimized: begin
                    WS := 2;
                    WindowState := wsNormal;
                   end;
      else WS := 0;
     end;
     N := Name;
     L := Left;
     W := Width;
     H := Height;
     T := Top;
     A := AlphaBlendValue;
     Vis := visible;
    end;
    Reg.OpenKey(RegLocation + '\Forms\' + N, true);
    Reg.WriteString('', N);
    Reg.WriteInteger('Left', L);
    Reg.WriteInteger('Height', H);
    Reg.WriteInteger('Top', T);
    Reg.WriteInteger('Width', W);
    Reg.WriteInteger('WindowState', WS);
    Reg.WriteBool('Visible', Vis);
    Reg.WriteInteger('Alpha', A);
   end;
  end;
 end;
 Reg.CloseKey;
 FreeAndNil(Reg);
end;


procedure ToeMain.LoadFormStatus;
Var
 Reg: TRegistry;
 I, II, III: Integer;
 List: TStrings;
begin
 List := TStringList.Create;
 Reg := TRegistry.Create;
 Reg.RootKey := HKEY_CURRENT_USER;
 If Reg.OpenKey(RegLocation + '\Forms', false) then begin
  Reg.GetKeyNames(List);
  For I := 0 to application.ComponentCount - 1 do begin
   If (Application.Components[I] is TForm) then begin
    For II := 0 to List.Count - 1 do begin
     If uppercase((Application.Components[I] as TForm).Name) = uppercase(List[II]) then begin
      // Generally OpenKey should be used in IF THEN because if it doesn't exists it will return false, but
      // since we are using the key we got in the GetKeyNames earlier it cannot be there
      Reg.OpenKey(RegLocation + '\Forms\' + List[II], false);
      With (Application.Components[I] as TForm) do begin
       Left := Reg.ReadInteger('Left');
       Height := Reg.ReadInteger('Height');
       If (application.Components[I] as TForm).Name = 'oePlugin' then begin
        oePlugin.oldHeight := oePlugin.Height;
       end;
       If (application.Components[I] as TForm).Name = 'VariableWin' then begin
        VariableWin.oldHeight := Variablewin.Height;
       end;
       If (application.Components[I] as TForm).Name = 'SnipWin' then begin
        SnipWin.oldHeight := SnipWin.Height;
       end;
       If (application.Components[I] as TForm).Name = 'oeInspector' then begin
        oeInspector.oldHeight := oeInspector.Height;
       end;

       Top := Reg.ReadInteger('Top');
       Width := Reg.ReadInteger('Width');
       Case Reg.ReadInteger('WindowState') of
        1: WindowState := wsMaximized;
        2: WindowState := wsMinimized;
        else WindowState := wsNormal;
       end;
       Visible := Reg.ReadBool('Visible');
       If Reg.ValueExists('Alpha') then begin
        AlphaBlendValue := Reg.ReadInteger('Alpha');
        For III := 0 to ComponentCount - 1 do begin
         If (Components[III] is TTrackbar) then begin
          (Components[III] as TTrackbar).Position := AlphaBlendValue;
         end;
        end;
       end;
      End;
     end;
    end;
   End;
  end;
 End;
 FreeAndNil(List);
 FreeAndNil(Reg);
end;

procedure ToeMain.FormShow(Sender: TObject);
begin
 If firstrun then begin
  FirstRun := False;
  LoadFormStatus;
 end;
end;

procedure ToeMain.FullScreenEditExecute(Sender: TObject);
Var
 L, H, T, W, HR: Integer;
begin
 If BorderStyle = bsSizeAble then begin
  fsToolbar.Visible := true;
  PreFullScreen.WS := WindowState;
  If WindowState = wsMaximized then begin
   WindowState := wsNormal;
  end;
  GetTaskBar(L, T, H, W);
  Shape1.Left := L;
  Shape1.Top := T;
  Shape1.Height := H;
  Shape1.Width := W;
  Shape1.Visible := true;
  StatusBar1.Visible := False;
  PreFullScreen.Left := Left;
  PreFullScreen.Top := Top;
  PreFullScreen.Height := Height;
  PreFullScreen.Width := Width;
  BorderStyle := bsNone;
  HR := Height - ClientHeight;
  Left := 0;
  Top := (HR * (-1)) - Toolbar1.Height;
  ClientHeight := Screen.Height + HR + Toolbar1.Height;
  Width := DesktopImage1.Width;
  WindowState := wsNormal;
  FormStyle := fsStayOnTop;
  ScrollBox1.HorzScrollBar.Visible := False;
  Scrollbox1.VertScrollBar.Visible := False;
  Update;
  FormStyle := fsNormal;
 end
  else
 begin
  fsToolbar.Visible := false;
  Left := PreFullScreen.Left;
  Height := PreFullScreen.Height;
  Width := PreFullScreen.Width;
  Top := PreFullScreen.Top;
  WindowState := PreFullScreen.WS;
  BorderStyle := bsSizeable;
  FormStyle := fsNormal;
  StatusBar1.Visible := true;
  Shape1.Visible := False;
  ScrollBox1.HorzScrollBar.Visible := true;
  Scrollbox1.VertScrollBar.Visible := true;
 end;
 If TutorialList.WaitingForCallback <> '' then begin
  TutorialList.Callback(sender);
 end;
end;

procedure ToeMain.GetTaskBar(var L, T, H, W: Integer);
var
  tabd: TAppBarData;
begin
  L := 0;
  T := 0;
  H := 0;
  W := 0;
  FillChar(tabd, SizeOf(TAppBarData), 0);
  tabd.cbSize := SizeOf(TAppBarData);
  if SHAppBarMessage(ABM_GETTASKBARPOS, Tabd) = 0 then Exit;
  L := Tabd.rc.Left;
  T := Tabd.rc.Top;
  W := Tabd.rc.Right - tabd.rc.Left;
  H := Tabd.rc.Bottom - tabd.rc.Top;
end;

procedure ToeMain.addFormLinkClick(Sender: TObject);
Var
 FormNode: TEdFormNode;
begin
 FormNode := Tree.GetDisplayNode.AddFormNode(createFormAtX, createFormAtY);
 ObjBrowser.LoadFromNode();
 SelectNode(FormNode);
end;

procedure ToeMain.BuildVisPopup;
Var
 I, II: Integer;
 List: TStringList;
 MI, MI2: TMenuItem;
begin
 List := Tstringlist.Create;
 For I := 0 to vpl.Count -1  do begin
  List.Add(vpl[I].name);
 end;
 List.Sort;
 For I := 0 to list.Count - 1 do begin
  MI := TMenuItem.Create(Popup_FormPanels);
  MI2 := TMenuItem.Create(Popup_Visuals);

  MI.Caption := List[I];
  MI2.Caption := List[I];
  MI.OnClick := OnPopup_FormsClick;
  MI2.OnClick := OnPopup_ReplaceVisClick;
  For II := 0 to oePlugin.listVis.Items.Count - 1 do begin
   If oePlugin.listVis.Items[II].Caption = List[I] then begin
//    MI.Caption := MI.Caption + '(Img: ' + InttoStr(II) + ')';
    MI.ImageIndex := oePlugin.listVis.Items[II].ImageIndex;
    MI2.ImageIndex := oePlugin.listVis.Items[II].ImageIndex;
   end;
  end;
  AddVisual1.Add(MI);
  ReplaceWith1.Add(MI2);
 end;
 FreeAndNil(List);
end;

procedure ToeMain.BuildGenPopup;
Var
 I, II: Integer;
 List1: TStringList;
 MILIST2, MIList: array of TMenuItem;
 S: String;
begin
 List1 := TStringlist.Create;
 For I := 0 to gpl.count - 1 do begin
  List1.Add(GPl[I].Name);
 end;
 List1.Sort;
 SetLength(MIList, List1.Count + 1);
 SetLength(MIList2, List1.Count + 1);
 MIList[0] := TMenuItem.Create(Popup_Visuals);
 MIList2[0] := TMenuItem.Create(oeInspector.ContentPopup);
 MIList[0].Caption := rawtext;
 MIList2[0].Caption := rawtext;
 MIList[0].OnClick := OnPopup_visualsclick;
 MIList2[0].OnClick := oeInspector.OnContentMenuClick;
 AddSensor1.Add(MIList[0]);
 OeInspector.ReplaceWith1.Add(MiList2[0]);
 For I := 0 to List1.Count - 1 do begin
  MIList[I] := TMenuItem.Create(Popup_Visuals);
  MIList2[I] := TMenuItem.Create(oeInspector.ContentPopup);
  MIList[I].Caption := List1[I];
  MIList2[I].Caption := List1[I];
  For II := 0 to oePlugin.listGen.Items.Count - 1 do begin
   If oePlugin.ListGen.Items[II].Caption = List1[I] then begin
    MIList[I].ImageIndex := oePlugin.listGen.Items[II].ImageIndex;
    MIList2[I].ImageIndex := oePlugin.listGen.Items[II].ImageIndex;
   end;
  end;
  AddSensor1.Add(MIList[I]);
  OeInspector.ReplaceWith1.Add(MiList2[I]);
 end;
 For I := 0 to AddSensor1.Count - 1 do begin
  S := AddSensor1.ITems[I].Caption;
  S := GetFilt(S, 1, '&') + GetFilt(S, 2, '&');
  AddSensorsToMenu(AddSensor1.Items[I], S, OnPopup_VisualsClick);
 end;
 for I := 0 to oeInspector.ReplaceWith1.Count - 1 do begin
  S := oeInspector.ReplaceWith1.Items[I].Caption;
  S := GetFilt(S, 1, '&') + GetFilt(S, 2, '&');
  AddSensorsToMenu(oeInspector.ReplaceWith1.Items[I], S, oeInspector.OnContentMenuClick);
 end;
 FreeAndnil(List1);
end;

procedure ToeMain.OnPopup_FormsClick(Sender: TObject);
Var
 I: Integer;
 GUID: TGUID;
 Found: Boolean;
 S: String;
begin
 S := (Sender as TMenuItem).Caption;
 S := GetFilt(S, 1, '&') + GetFilt(S, 2, '&');
 Found := False;
 For I := 0 to VPL.Count - 1 do begin
  If VPL[I].Name = S then begin
   Found := true;
   GUID := VPL[I].GUID;
   break;
  end;
 end;
 If not found then exit;
 (CurrentSelectNode as TEdFormNode).AddVisualNode(GUID, (CurrentSelectNode as TEdFormNode).Form.PopupX, (CurrentSelectNode as TEdFormNode).Form.PopupY);
 ObjBrowser.LoadFromNode();
end;

procedure ToeMain.OnPopup_VisualsClick(Sender: TObject);
Var
 I: Integer;
 GUID: TGUID;
 Found: Boolean;
 S, PlugName, PlugSens: String;
 CNode: TEdContentNode;
begin
 S := (Sender as TMenuItem).Caption;
 S := GetFilt(S, 1, '&') + GetFilt(S, 2, '&');
 If uppercase(S) = uppercase(rawtext) then begin
  CNode := (Select.CurrentSelectedNode as TEdVisualNode).GetContentNode;
  Select.CurrentSelectedNode := CNode.Add(ntText);
  oeInspector.Show;
  oeInspector.PageControl1.ActivePageIndex := 0;
  oeInspector.SetFocus;
  oeInspector.listProps.SetFocus;
  ObjBrowser.LoadFromNode();
  exit;
 end;
 PlugSens := (Sender as TMenuItem).Caption;
 PlugSens := GetFilt(PlugSens, 1, '&') + GetFilt(PlugSens, 2, '&');
 PlugName := ((Sender as TMenuItem).Parent as TMenuItem).Caption;
 PlugName := GetFilt(PlugName, 1, '&') + GetFilt(PlugName, 2, '&');
 Found := False;
 For I := 0 to GPL.Count - 1 do begin
  If GPL[I].Name = PlugName then begin
   Found := True;
   GUID := GPL[I].GUID;
   break;
  end;
 end;
 If not found then exit;
 AddSensorDlg.Execute(GUID, (CurrentSelectNode as TEdVisualNode), PlugName, PlugSens);
end;

procedure ToeMain.AddSensorsToMenu(ParentItem: TMenuItem; PlugName: String; OnClick: TNotifyEvent);
Var
 I, II: Integer;
 List2: TStringList;
 MIList: TMenuItem;
begin
  List2 := TStringlist.Create;
  For I := 0 to GPL.Count - 1 do begin
   If GPL[I].Name = PlugName then begin
    For II := 0 to GPL[I].SensorList.Count - 1 do begin
     List2.Add(GPL[I].SensorList[II].Name);
    end;
    List2.Sort;
    For II := 0 to List2.Count -1 do begin
     MIList := TMenuItem.Create(self);
     MIList.Caption := List2[II];
     MIList.OnClick := OnClick;
     ParentItem.Add(MIList);
    end;
    break;
   end;
  end;
  FreeAndnil(List2);
end;

procedure ToeMain.Save1Click(Sender: TObject);
begin
 PerformSave(false);
 If TutorialList.WaitingForCallback <> '' then begin
  TutorialList.Callback(sender);
 end;
end;

procedure ToeMain.Open1Click(Sender: TObject);
begin
 PerformLoad;
 If TutorialList.WaitingForCallback <> '' then begin
  TutorialList.Callback(sender);
 end;
 ObjBrowser.LoadFromNode();
end;


procedure ToeMain.ApplicationEvents1Exception(Sender: TObject;
  E: Exception);
begin
 If E.ClassType = EDOMParseError then begin
  MessageDlg('Your CML config contains a syntax error.'+#13+#10+''+#13+#10+'The XML Engine provided this information:'+#13+#10+ E.Message +#13+#10+''+#13+#10+'Loading Aborted.', mtError, [mbOK], 0);
  exit;
 end;
 MessageDlg('Error: ' + E.ClassName + #13#10 + 'Message: ' + E.Message, mtError, [mbOK], 0);
end;

procedure ToeMain.Bringtofront1Click(Sender: TObject);
Var
 Cnt: Integer;
begin
 (CurrentSelectNode as TEdVisualNode).Visual.BringToFront;
 Cnt := CurrentSelectNode.Parent.Count;
 CurrentSelectNode.Parent.MoveChild(CurrentSelectNode.Index, Cnt-1);
 ObjBrowser.LoadFromNode();
end;

procedure ToeMain.Sendtoback1Click(Sender: TObject);
begin
 (CurrentSelectNode as TEdVisualNode).Visual.SendToBack;
 CurrentSelectNode.Parent.MoveChild(CurrentSelectNode.Index, 0);
 ObjBrowser.LoadFromNode();
end;

procedure ToeMain.ApplicationEvents1Hint(Sender: TObject);
begin
 If oeMain.BorderStyle = bsSizeable then
  statusbar1.Panels[0].Text := Application.Hint
 else
  fsToolbar.statusbar1.Panels[0].Text := Application.Hint;
end;

procedure ToeMain.ToolButton4Click(Sender: TObject);
begin
 Save1Click(self);
end;

procedure ToeMain.ToolButton5Click(Sender: TObject);
begin
 Open1Click(self);
end;

procedure ToeMain.actionOIExecute(Sender: TObject);
begin
 oeInspector.Visible := not oeInspector.Visible;
 If TutorialList.WaitingForCallback <> '' then begin
  TutorialList.Callback(sender);
 end;
end;

procedure ToeMain.actionPluginPaletteExecute(Sender: TObject);
begin
 oePlugin.Visible := not oePlugin.Visible;
 If TutorialList.WaitingForCallback <> '' then begin
  TutorialList.Callback(sender);
 end;
end;

procedure ToeMain.actionSnippetExecute(Sender: TObject);
begin
 SnipWin.Visible := not snipwin.Visible;
 If TutorialList.WaitingForCallback <> '' then begin
  TutorialList.Callback(sender);
 end;
end;

procedure ToeMain.actionSensorListingExecute(Sender: TObject);
begin
 VariableWin.Visible := not VariableWin.Visible;
 If TutorialList.WaitingForCallback <> '' then begin
  TutorialList.Callback(sender);
 end;
end;

procedure ToeMain.actionParameterDetailsExecute(Sender: TObject);
begin
 ParameterDetailsWindow.Visible := not ParameterDetailsWindow.Visible;
 If TutorialList.WaitingForCallback <> '' then begin
  TutorialList.Callback(sender);
 end;
end;

procedure ToeMain.Simple1Click(Sender: TObject);
begin
 oeInspector.Show;
 oePlugin.show;
 SnipWin.hide;
 VariableWin.Hide;
end;

procedure ToeMain.Advanced1Click(Sender: TObject);
begin
 oeInspector.Show;
 oePlugin.show;
 SnipWin.hide;
 VariableWin.show;
end;

procedure ToeMain.Hardcore1Click(Sender: TObject);
begin
 oeInspector.Show;
 oePlugin.show;
 SnipWin.show;
 VariableWin.show;
end;

procedure ToeMain.UpdateCaption;
Var
 S: String;
begin
 S := 'Untitled';
 If GlobalFilename <> '' then begin
  If Options.Files.ShowFullPathInCaption then S := GlobalFilename
  else S := extractfilename(GlobalFilename);
 end;
 Caption := 'Outlaw Ed :: ' + S;
end;

procedure ToeMain.OnTreeModified(Sender: TObject);
begin
 actionSave.Enabled := Tree.Modified;
end;

procedure ToeMain.PerformSave(AlwaysShowDialog: boolean);
Var
 List: TStrings;
begin
 If (globalfilename = '') or (AlwaysShowDialog) then begin
  Savedialog1.InitialDir := Options.Files.DefaultFolder;
  if not savedialog1.execute then exit;
  GlobalFilename := Savedialog1.Filename;
 end;
 Tree.Modified := false;
 UpdateCaption;
 VarMgr.ResetSaveCount;
 List := TStringList.Create;
 List.Text := Tree.Root.WriteXML('');
 if uppercase(extractfileext(GlobalFilename)) <> '.CML' then begin
  GlobalFilename := GlobalFilename + '.cml';
 end;
 List.SaveToFile(GlobalFilename);
 FreeAndNil(List);
end;

procedure ToeMain.SaveAs1Click(Sender: TObject);
begin
 PerformSave(true);
end;

procedure ToeMain.OnLoadRecent(Filename: String);
begin
 PerformLoad(Filename);
 ObjBrowser.LoadFromNode();
end;

procedure ToeMain.SetGlobalFilename(const Value: String);
begin
 If fGlobalFilename <> '' then begin
  RecentList.Add(fGlobalFileName);
  RecentList.SaveToReg;
 end;
 RecentList.BuildMenu;
 fGlobalFilename := Value;
 UpdateCaption;
end;

procedure ToeMain.PerformLoad(Filename: String = ''; Import: Boolean = false);
Var
 ImportName: String;
 ImportNode: IXMLNode;
 I: Integer;
begin
 If not import then begin
  If Assigned(Tree) then begin
   If Tree.Modified then begin
    case MessageDlg('Configuration has been changed, Save ?', mtConfirmation, [mbYes, mbNo, mbCancel], 0) of
     mrCancel: begin
                // Readd the file to the recent list
                If filename <> '' then RecentList.Add(Filename);
                exit;
               end;
    mrYes: Begin
             PerformSave(false);
            end;
    end;
   end;
  end;
 end;
 If filename = '' then begin
  If import then begin
   Opendialog1.Title := 'Import CML File into current Config ...'
  end
   else
  begin
   Opendialog1.Title := 'Load CML Config ...';
  end;
  opendialog1.InitialDir := Options.Files.DefaultFolder;
  if not opendialog1.Execute then exit;
  If not import then begin
   Filename := Opendialog1.filename;
  end
   else
  begin
   ImportName := Opendialog1.filename;
  end;
 end;
 If not import then begin
  If not fileexists(filename) then exit;
 end
  else
 begin
  If not fileexists(importname) then exit;
 end;
 Select.Clear;
 If import then begin
  CML.LoadFromFile(ImportNAme);
 end
  else
 begin
  CML.LoadFromFile(filename);
 end;
 Try
  CML.Active := true;
 except
  On EDOMParseError do begin
  end;
 end;
 If not import then begin
  If Assigned(Tree) then begin
   FreeAndNil(Tree);
  end;
  GlobalFilename := FileName;
  UpdateCaption;
  Tree := TEdCM2Tree.Create(Self, FormMgr, Addr(GPL), Addr(VPL), Addr(XPL));
  Tree.Root := TEdRootNode.Create(Tree, nil);
  Tree.Root.LoadSelf(CML.Node);
 end
  else
 begin
  ImportNode := nil;
  For i := 0 to CML.ChildNodes.Count - 1 do begin
   If uppercase(CML.ChildNodes[I].NodeName) = 'CML' then begin
    ImportNode := CML.ChildNodes[I];
   end;
  end;
  If ImportNode = nil then begin
   MessageDlg('Could not find CML root node in the import file. Nothing has been imported.', mtError, [mbOK], 0);
   exit;
  end;
  For i := 0 to ImportNode.ChildNodes.Count - 1 do begin
   If uppercase(ImportNode.ChildNodes[I].NodeName) = 'DISPLAY' then begin
    ImportNode := ImportNode.ChildNodes[I];
   end;
  end;
  If uppercase(ImportNode.NodeName) <> 'DISPLAY' then begin
   MessageDlg('Could not find Display node in the import file. Nothing has been imported.', mtError, [mbOK], 0);
   exit;
  end;
  Tree.GetDisplayNode.LoadSelf(ImportNode);
 end;
 CML.active := False;
 If not import then begin
  Tree.Modified := falsE;
 end
  else
 begin
  Tree.Modified := true;
 end;
{ *** REMOVED SINCE THERE HASN'T BEEN A USE FOR IT YET ***
 List:= TStringlist.Create;
 List.Text := Tree.root.WriteXML('');
 List.SaveToFile('C:\test.cml');
 FreeAndNil(List);
}
 SelectNode(Tree.Root, true);
 DesktopImage1.Repaint;
end;

procedure ToeMain.Preferences1Click(Sender: TObject);
begin
 PrefDlg.Execute;
end;

procedure ToeMain.Delete1Click(Sender: TObject);
Var
 PNode: TEdRawNode;
 VisNode: TEdVisualNode;
begin
 PNode := CurrentSelectNode.Parent;
 VisNode := (CurrentSelectNode as TEdVisualNode);
 If MessageDlg('Are you sure you wish to delete this visual [' + VisNode.VisualName + '] ?', mtConfirmation, [mbYes, mbNo], 0) = mrNo then exit;
 Select.Clear;
 VisNode.DeleteSelf;
 ObjBrowser.LoadFromNode();
 SelectNode(PNode.Parent);
end;

procedure ToeMain.actionDeleteExecute(Sender: TObject);
Var
 CNode, PNode: TEdRawNode;
 Nodes: TEdRawNodes;
 ItemName, ItemType: String;
 I: integer;
begin
 If Select.Count = 0 then exit;
 If Select.Count = 1 then begin
  CNode := CurrentSelectNode;
  PNode := CNode.Parent;
  Select.Clear;
  Case CNode.NodeType of
   ntForm: begin
            ItemType := 'Form';
            ItemName := (CNode as TEdFormNode).FormName;
           end;
   ntVisual: begin
              ItemType := 'Visual Object';
              ItemName := (CNode as TEdVisualNode).VisualName;
             end;
   ntSensor: begin
             end;
   else Exit;
  end;
  If MessageDlg('Are you sure you wish to delete this ' + ItemType + ' [' + ItemName + ']?', mtConfirmation, [mbYes, mbNo], 0) = mrNo then exit;
  Case CNode.NodeType of
   ntForm: Begin
            (CNode as TEdFormNode).DeleteSelf;
            PNode := PNode.Parent;
           end;
   ntVisual: Begin
              (CNode as TEdVisualNode).DeleteSelf;
              PNode := PNode.Parent;
             end;
   ntSensor: Begin
             end;
  end;
  SelectNode(PNode);
 end
  else
 begin
  If MessageDlg('Are you sure you wish to delete these object ?', mtConfirmation, [mbYes, mbNo], 0) = mrNo then exit;
  Select.GetSelected(Nodes);
  Select.Clear;
  // We need to delete visuals before forms, just in case that a form and it's visuals has been selected
  // if we delete the form first and AV would arise when you then later try to delete the visuals
  For I := 0 to length(Nodes) - 1 do begin
   if Nodes[I].Nodetype = ntVisual then begin
    Nodes[I].DeleteSelf;
   end;
  end;
  For I := 0 to Length(Nodes) - 1 do begin
   If nodes[I].Nodetype = ntForm then begin
    Nodes[I].DeleteSelf;
   end;
  end;
 end;
 ObjBrowser.LoadFromNode();
 If TutorialList.WaitingForCallback <> '' then begin
  TutorialList.Callback(sender);
 end;
end;

function ToeMain.GETCURRENTSELECTNODE: TEdRawNode;
begin
 Result := Select.CurrentSelectedNode;
end;

procedure ToeMain.AddToSelected(Node: TEdRawNode);
begin
 Select.AddToSelect(Node);
end;

procedure ToeMain.OnDrawSelected(Node: TEdRawNode);
begin
 If Node = nil then exit;
 If Node.NodeType = ntForm then begin
  (Node as TEdFormNode).Form.Selected := true;
 end;
 If Node.NodeType = ntVisual then begin
  (Node as TEdVisualNode).Visual.Selected := true;
 end;
end;

procedure ToeMain.OnDrawDeSelected(Node: TEdRawNode);
begin
 If Node = nil then exit;
 If node.NodeType = ntForm then begin
  (Node as TEdFormNode).Form.Selected := false;
 end;
 If Node.NodeType = ntVisual then begin
  (Node as TEdVisualNode).Visual.Selected := false;
 end;
end;

procedure ToeMain.OnSelect(NodesToSelect: TEdRawNodes);
begin
 oeInspector.OIItemList.Clear;
 oeInspector.OIContentList.Clear;
 If length(NodesToSelect) = 1 then begin
  // Select one node
  SnipWin.SelectNode(NodesToSelect[0]);
  oeInspector.OIItemList.LoadNode(NodesToSelect[0]);
  oeInspector.OIContentList.BuildFromTag(NodesToSelect[0]);
  oeInspector.BuildEventList(NodesToSelect[0]);
 end
  else
 begin
  // Select multiple nodes
  If SnipWin.Memo1.Enabled then begin
   SnipWin.Memo1.Enabled := false;
   SnipWin.Memo1.Text := 'Snippet window is not available' + #13#10 + 'with current object selection';
   SnipWin.Modified := false;
   SnipWin.ToolButton1.Enabled := false;
  end;
  If oeInspector.contentLV.Enabled then begin
   oeInspector.contentLV.Enabled := false;
  end;
  oeInspector.OIItemList.LoadNodes(NodesToSelect);
  oeInspector.BuildEventList(nil);
 end;
// oeInspector.PageControl1.ActivePageIndex := 0;
 If debug then showmessage('BUILDFromOIIL');
 oeInspector.BuildFromOIIL;
 If debug then showmessage('BuildFromOIContent');
 oeInspector.BuildFromOIContent;
// objbrowser.LoadFromNode(Tree.GetDisplayNode);
end;

procedure ToeMain.findFound(Sender: TObject; Folder: String;
  FileInfo: TSearchRec);
begin
 TutorialList.Add(PathToOk(Folder) + Fileinfo.Name);
end;

procedure ToeMain.findComplete(Sender: TObject);
begin
 TutorialList.BuildMenu;
 StartUpTimer.Enabled := true;
end;

procedure ToeMain.ObjectTracer1Click(Sender: TObject);
begin
 ObjectTracer1.Checked := not ObjectTracer1.Checked;
 TutorialList.ObjectTrace := ObjectTracer1.Checked;
end;

procedure ToeMain.ApplicationEvents1ShowHint(var HintStr: String;
  var CanShow: Boolean; var HintInfo: THintInfo);
begin
// HintStr := 'This is a test';
 If TutorialList.ObjectTrace then begin
  HintStr := TutorialList.GetObjectPath(HintInfo.HintControl);
 end;
// CanShow := false;
// If hintStr <> '' Then begin
//  HintInfo.ReshowTimeout := 50;
//  Hintwin.ShowHint(HintInfo.HintControl, adAuto, HintStr, '', 0, TutorialList.CaptionFont, TutorialList.MainFont);
// End;
end;

procedure ToeMain.Extendedhints1Click(Sender: TObject);
begin
 ExtendedHints1.Checked := Not ExtendedHints1.Checked;
 TutorialList.SetHintType(ExtendedHints1.Checked, application);
end;

procedure ToeMain.OnClipboardClear(Sender: TObject);
begin
 actionPaste.Enabled := False;
end;

procedure ToeMain.OnClipboardNewAddition(Sender: TObject);
begin
 actionPaste.Enabled := true;
end;

procedure ToeMain.actionCopyExecute(Sender: TObject);
Var
 I: integer;
 NT: TNodetype;
 CanCopy: boolean;
begin
 If snipwin.Memo1.Focused then begin
  snipwin.CopyToClipboard;
  exit;
 end;
 If select.Count = 0 then exit;
 NT := select.Node[0].NodeType;
 CanCopy := true;
 For I := 1 to Select.Count - 1 do begin
  If nt <> Select[I].NodeType then CanCopy := false;
 end;
 If not CanCopy then begin
  MessageDlg('You cannot copy objects of different types', mtInformation, [mbOK], 0);
  Exit;
 end;
 Clipboard.Clear;
 For I := 0 to Select.Count - 1 do begin
  Clipboard.AddToClipboard(Select[I].WriteXML(''));
 end;
 Clipboard.NodeType := NT;
 If TutorialList.WaitingForCallback <> '' then begin
  TutorialList.Callback(sender);
 end;
end;

procedure ToeMain.actionPasteExecute(Sender: TObject);
begin
 If snipwin.Memo1.Focused then begin
  snipwin.PasteFromClipboard;
  exit;
 end;
 If select.Count > 1 then begin
  MessageDlg('You cannot paste onto multiple objects.'+#13+#10+'Refine your selection', mtInformation, [mbOK], 0);
  exit;
 end;
 CML.XML.Text := Clipboard.ProvideCML;
 CML.Active := true;
 Case Clipboard.NodeType of
  ntForm: Begin
           Tree.GetDisplayNode.LoadChildren(CML.ChildNodes[0], Tree.GetDisplayNode);
          end;
  ntVisual: Begin
             If Select.CurrentSelectedNode.NodeType <> ntForm then begin
              MessageDlg('You currently have visual object(s) in the clipboard.'+#13+#10+'You must select a form to paste those onto.'+#13+#10+'Select a form and paste again.', mtInformation, [mbOK], 0);
              CML.Active := false;
              exit;
             end;
             (Select.CurrentSelectedNode as TEdFormNode).GetContentNode.LoadChildren(CML.ChildNodes[0], Select.CurrentSelectedNode);
            end;
  ntSensor: begin
            end;
 end;
 CML.Active := false;
 If TutorialList.WaitingForCallback <> '' then begin
  TutorialList.Callback(sender);
 end;
 ObjBrowser.LoadFromNode();
end;

procedure ToeMain.actionCutExecute(Sender: TObject);
Var
 I: integer;
 NT: TNodetype;
 CanCopy: boolean;
 Nodes: TEdRawnodes;
begin
 If snipwin.Memo1.Focused then begin
  snipwin.Memo1.CutToClipboard;
  exit;
 end;
 If select.Count = 0 then exit;
 NT := select.Node[0].NodeType;
 If not((NT = ntForm) or (NT = ntVisual)) then begin
  MessageDlg('You must select either a form or a visual object to cut.', mtWarning, [mbOK], 0);
  exit;
 end;
 CanCopy := true;
 For I := 1 to Select.Count - 1 do begin
  If nt <> Select[I].NodeType then CanCopy := false;
 end;
 If not CanCopy then begin
  MessageDlg('You cannot copy objects of different types', mtInformation, [mbOK], 0);
  Exit;
 end;
 Clipboard.Clear;
 For I := 0 to Select.Count - 1 do begin
  Clipboard.AddToClipboard(Select[I].WriteXML(''));
 end;
 Clipboard.NodeType := NT;
 If not Select.GetSelected(Nodes) then exit;
 Select.Clear;
 For I := length(Nodes) - 1 downto 0 do begin
  Nodes[I].DeleteSelf;
 end;
 If TutorialList.WaitingForCallback <> '' then begin
  TutorialList.Callback(sender);
 end;
 ObjBrowser.LoadFromNode();
end;

procedure ToeMain.ShowEventPaths1Click(Sender: TObject);
begin
 ShowEventPaths1.Checked := not ShoweventPaths1.Checked;
 If ShoweventPaths1.Checked then begin
  TutorialList.WaitingForCallback := 'showevents';
 end
  else
 begin
  TutorialList.WaitingForCallback := '';
 end;
end;

procedure ToeMain.OnPopup_ReplaceVisClick(Sender: TObject);
Var
 I: Integer;
 S, L, W, H, T: String;
 ChildCML: String;
 CNode: TEdContentNode;
 PNode: TEdParameterBlockNode;
 FormNode: TEdFormNode;
 Node: TEdVisualNode;
 GUID: TGUID;
begin
 S := (Sender as TMenuItem).Caption;
 S := GetFilt(S, 1, '&') + GetFilt(S, 2, '&');
 If not VPL.GetGUID(S, GUID) then exit;
 Node := (Select.CurrentSelectedNode as TEdVisualNode);
 CNode := (Node as TEdVisualNode).GetContentNode;
 PNode := (Node as TEdVisualNode).GetParameterBlockNode;
 For I := 0 to PNode.Count - 1 do begin
  If uppercase(PNode.Node[I].Name) = 'LEFT' then begin
   L := (PNode.Node[I] as TEdParameterNode).Value;
  end;
  If uppercase(PNode.Node[I].Name) = 'TOP' then begin
   T := (PNode.Node[I] as TEdParameterNode).Value;
  end;
  If uppercase(PNode.Node[I].Name) = 'HEIGHT' then begin
   H := (PNode.Node[I] as TEdParameterNode).Value;
  end;
  If uppercase(PNode.Node[I].Name) = 'WIDTH' then begin
   W := (PNode.Node[I] as TEdParameterNode).Value;
  end;
 end;
 ChildCML := '';
 For I := 0 to CNode.Count - 1 do begin
  ChildCML := ChildCML + CNode.Node[I].WriteXML('');
 end;
 ChildCML := '<cml>' + ChildCML + '</cml>';
 Select.Clear;
 FormNode := (Node.Parent.Parent as TEdFormNode); // first is content, second is parent form
 Node.DeleteSelf;
 Node := (FormNode as TEdFormNode).AddVisualNode(GUID, StrToInt(L), StrToInt(T));
 PNode := Node.GetParameterBlockNode;
 For I := 0 to PNode.Count -1 do begin
  If uppercase(PNode.Node[I].Name) = 'HEIGHT' then begin
   (PNode.Node[I] as TEdParameterNode).Value := H;
  end;
  If uppercase(PNode.Node[I].Name) = 'WIDTH' then begin
   (PNode.Node[I] as TEdParameterNode).Value := H;
  end;
 end;
 CNode := Node.GetContentNode;
 CML.XML.Text := ChildCML;
 CML.Active := true;
 CNode.LoadChildren(CML.ChildNodes[0], CNode);
 CML.Active := falsE;
 ObjBrowser.LoadFromNode();
 SelectNode(Node, true);
end;

procedure ToeMain.DesktopImage1Click(Sender: TObject);
begin
 Select.CurrentSelectedNode := tree.GetDisplayNode.Parent;
end;

procedure ToeMain.Popup_ScrollBoxPopup(Sender: TObject);
begin
 Show1.Checked := options.Visual.ShowGrid;
 SnapTo1.Checked := options.Visual.SnapToGrid;
 Dots1.Checked := options.Visual.ShowDot;
 Lines1.Checked := not options.Visual.ShowDot;
 If Clipboard.NodeType = ntForm then begin
  Paste3.Enabled := true;
 end
  else
 begin
  Paste3.Enabled := false;
 end;
end;

procedure ToeMain.Show1Click(Sender: TObject);
begin
 options.Visual.ShowGrid := not options.Visual.ShowGrid;
 Desktopimage1.ShowGrid := options.visual.showgrid;
 SaveOptions;
end;

procedure ToeMain.SnapTo1Click(Sender: TObject);
begin
 Options.Visual.SnapToGrid := not options.Visual.SnapToGrid;
 Snapto1.Checked := options.Visual.SnapToGrid;
 saveoptions;
end;

procedure ToeMain.Dots1Click(Sender: TObject);
begin
 options.Visual.ShowDot := true;
 desktopimage1.ShowDot := true;
 saveoptions;
end;

procedure ToeMain.Lines1Click(Sender: TObject);
begin
 options.Visual.ShowDot := false;
 desktopimage1.ShowDot := false;
 saveoptions;
end;

procedure ToeMain.Popup_FormPanelsPopup(Sender: TObject);
begin
 Show2.Checked := options.Visual.FormPanelOptions.ShowGrid;
 SnapTo2.Checked := options.Visual.FormPanelOptions.SnapToGrid;
 Dots2.Checked := options.Visual.FormPanelOptions.ShowDot;
 Lines2.Checked := not options.Visual.FormPanelOptions.ShowDot;
 If Clipboard.NodeType = ntVisual then begin
  Paste2.Enabled := true;
 end
  else
 begin
  Paste2.Enabled := false;
 end;
end;

procedure ToeMain.Show2Click(Sender: TObject);
Var
 I: Integer;
begin
 options.Visual.FormPanelOptions.ShowGrid := not options.Visual.FormPanelOptions.ShowGrid;
 For I := 0 to formmgr.count - 1 do begin
  Formmgr[I].Paint;
 end;
 SaveOptions;
end;


procedure ToeMain.SnapTo2Click(Sender: TObject);
begin
 Options.Visual.FormPanelOptions.SnapToGrid := not options.Visual.FormPanelOptions.SnapToGrid;
 SaveOptions;
end;

procedure ToeMain.Dots2Click(Sender: TObject);
Var
 I: Integer;
begin
 options.Visual.FormPanelOptions.ShowDot := true;
 Saveoptions;
 For I := 0 to formmgr.count -1 do begin
  FormMgr[I].Paint;
 end;
end;

procedure ToeMain.Lines2Click(Sender: TObject);
Var
 I: Integer;
begin
 options.Visual.FormPanelOptions.ShowDot := false;
 Saveoptions;
 For I := 0 to formmgr.count -1 do begin
  FormMgr[I].Paint;
 end;
end;

procedure ToeMain.FormMouseWheel(Sender: TObject; Shift: TShiftState;
  WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
begin
 If (ssShift in Shift) then begin
  // horz scroll
  ScrollBox1.HorzScrollBar.Position := Scrollbox1.HorzScrollBar.Position + (WheelDelta * -1);
 end
  else
 begin
  // vertical scroll
  ScrollBox1.VertScrollBar.Position := Scrollbox1.VertScrollBar.Position + (WheelDelta * -1);
 end;
end;

procedure ToeMain.PlugInManager1Click(Sender: TObject);
begin
 If Tree.Modified then begin
  case MessageDlg('Configuration has been changed, Save ?', mtConfirmation, [mbYes, mbNo, mbCancel], 0) of
   mrCancel: exit;
   mrYes: Begin
           PerformSave(false);
          end;
  end;
 end;
 TutorialList.SetTerminate := true;
 GlobalFilename := ''; // This done to let the recent list save the loaded file
 RecentList.SaveToReg;
 SaveFormStatus;
 ExecApp(PMLocation, '/LaunchEditor');
 Application.Terminate;
end;

procedure ToeMain.ImportCML1Click(Sender: TObject);
begin
 performload('', true);
end;

procedure ToeMain.FormActivate(Sender: TObject);
begin
 oeMain.SetHotKeyStates(self);
end;

procedure ToeMain.actionLeftExecute(Sender: TObject);
Var
 I: Integer;
 FS, VS: Boolean;
begin
 If select.Count = 0 then exit;
 FS := Options.Visual.SnapToGrid;
 VS := Options.Visual.FormPanelOptions.SnapToGrid;
 Options.Visual.SnapToGrid := false;
 Options.Visual.FormPanelOptions.SnapToGrid := false;
 For I := 0 to select.count - 1 do begin
  If Select.Node[I].NodeType = ntForm then begin
   (Select.Node[I] as TEdFormNode).Form.Left := (Select.Node[I] as TEdFormNode).Form.Left - 1;
   (Select.Node[I] as TedFormNode).UpdateParameter('left', IntToStr((Select.Node[I] as TEdFormNode).Form.Left));
   Select.UpdateSelected;
  end;
  If Select.Node[I].NodeType = ntVisual then begin
   (Select.Node[I] as TEdVisualNode).Visual.Left := (Select.Node[I] as TEdVisualNode).Visual.Left - 1;
   (Select.Node[I] as TEdVisualNode).UpdateParameter('left', IntToStr((Select.Node[I] as TEdVisualNode).Visual.Left));
   Select.UpdateSelected;
  end;
 end;
 Options.Visual.SnapToGrid := FS;
 Options.Visual.FormPanelOptions.SnapToGrid := VS;
end;

procedure ToeMain.actionRightExecute(Sender: TObject);
Var
 I: Integer;
 FS, VS: boolean;
begin
 If select.Count = 0 then exit;
 FS := Options.Visual.SnapToGrid;
 VS := Options.Visual.FormPanelOptions.SnapToGrid;
 Options.Visual.SnapToGrid := false;
 Options.Visual.FormPanelOptions.SnapToGrid := false;
 For I := 0 to select.count - 1 do begin
  If Select.Node[I].NodeType = ntForm then begin
   (Select.Node[I] as TEdFormNode).Form.Left := (Select.Node[I] as TEdFormNode).Form.Left + 1;
   (Select.Node[I] as TedFormNode).UpdateParameter('left', IntToStr((Select.Node[I] as TEdFormNode).Form.Left));
   Select.UpdateSelected;
  end;
  If Select.Node[I].NodeType = ntVisual then begin
   (Select.Node[I] as TEdVisualNode).Visual.Left := (Select.Node[I] as TEdVisualNode).Visual.Left + 1;
   (Select.Node[I] as TEdVisualNode).UpdateParameter('left', IntToStr((Select.Node[I] as TEdVisualNode).Visual.Left));
   Select.UpdateSelected;
  end;
 end;
 Options.Visual.SnapToGrid := FS;
 Options.Visual.FormPanelOptions.SnapToGrid := VS;
end;

procedure ToeMain.actionUpExecute(Sender: TObject);
Var
 I: Integer;
 FS, VS: boolean;
begin
 If select.Count = 0 then exit;
 FS := Options.Visual.SnapToGrid;
 VS := Options.Visual.FormPanelOptions.SnapToGrid;
 Options.Visual.SnapToGrid := false;
 Options.Visual.FormPanelOptions.SnapToGrid := false;
 For I := 0 to select.count - 1 do begin
  If Select.Node[I].NodeType = ntForm then begin
   (Select.Node[I] as TEdFormNode).Form.top := (Select.Node[I] as TEdFormNode).Form.top - 1;
   (Select.Node[I] as TedFormNode).UpdateParameter('top', IntToStr((Select.Node[I] as TEdFormNode).Form.Top));
   Select.UpdateSelected;
  end;
  If Select.Node[I].NodeType = ntVisual then begin
   (Select.Node[I] as TEdVisualNode).Visual.top := (Select.Node[I] as TEdVisualNode).Visual.top - 1;
   (Select.Node[I] as TEdVisualNode).UpdateParameter('top', IntToStr((Select.Node[I] as TEdVisualNode).Visual.top));
   Select.UpdateSelected;
  end;
 end;
 Options.Visual.SnapToGrid := FS;
 Options.Visual.FormPanelOptions.SnapToGrid := VS;
end;

procedure ToeMain.actionDownExecute(Sender: TObject);
Var
 I: Integer;
 FS, VS: boolean;
begin
 If select.Count = 0 then exit;
 FS := Options.Visual.SnapToGrid;
 VS := Options.Visual.FormPanelOptions.SnapToGrid;
 Options.Visual.SnapToGrid := false;
 Options.Visual.FormPanelOptions.SnapToGrid := false;
 For I := 0 to select.count - 1 do begin
  If Select.Node[I].NodeType = ntForm then begin
   (Select.Node[I] as TEdFormNode).Form.top := (Select.Node[I] as TEdFormNode).Form.top + 1;
   (Select.Node[I] as TedFormNode).UpdateParameter('top', IntToStr((Select.Node[I] as TEdFormNode).Form.Top));
   Select.UpdateSelected;
  end;
  If Select.Node[I].NodeType = ntVisual then begin
   (Select.Node[I] as TEdVisualNode).Visual.top := (Select.Node[I] as TEdVisualNode).Visual.top + 1;
   (Select.Node[I] as TEdVisualNode).UpdateParameter('top', IntToStr((Select.Node[I] as TEdVisualNode).Visual.top));
   Select.UpdateSelected;
  end;
 end;
 Options.Visual.SnapToGrid := FS;
 Options.Visual.FormPanelOptions.SnapToGrid := VS;
end;

procedure ToeMain.SetHotKeyStates(SelectedForm: TForm);
begin
 If uppercase(SelectedForm.Name) = 'OEMAIN' then begin
  oeMain.actionCopy.Enabled := true;
  oeMain.actionCut.Enabled := true;
  oeMain.actionPaste.Enabled := true;
  oeMain.actionDelete.Enabled := true;
  oeMain.actionUp.enabled := true;
  oeMain.actionDown.enabled := true;
  oeMain.actionLeft.Enabled := true;
  oeMain.actionRight.Enabled := true;
 end;
 If uppercase(SelectedForm.Name) = 'OEINSPECTOR' then begin
  oeMain.actionCopy.Enabled := false;
  oeMain.actionCut.Enabled := false;
  oeMain.actionPaste.Enabled := false;
  oeMain.actionDelete.Enabled := false;
  oeMain.actionUp.enabled := false;
  oeMain.actionDown.enabled := false;
  oeMain.actionLeft.Enabled := false;
  oeMain.actionRight.Enabled := false;
 end;
 If uppercase(SelectedForm.Name) = 'VARIABLEWIN' then begin
  oeMain.actionCopy.Enabled := false;
  oeMain.actionCut.Enabled := false;
  oeMain.actionPaste.Enabled := false;
  oeMain.actionDelete.Enabled := false;
  oeMain.actionUp.enabled := false;
  oeMain.actionDown.enabled := false;
  oeMain.actionLeft.Enabled := false;
  oeMain.actionRight.Enabled := false;
 end;
 If uppercase(SelectedForm.Name) = 'SNIPWIN' then begin
  oeMain.actionCopy.Enabled := true;
  oeMain.actionCut.Enabled := true;
  oeMain.actionPaste.Enabled := true;
  oeMain.actionDelete.Enabled := false;
  oeMain.actionUp.enabled := false;
  oeMain.actionDown.enabled := false;
  oeMain.actionLeft.Enabled := false;
  oeMain.actionRight.Enabled := false;
 end;
 If uppercase(SelectedForm.Name) = 'OEPLUGIN' then begin
  oeMain.actionCopy.Enabled := false;
  oeMain.actionCut.Enabled := false;
  oeMain.actionPaste.Enabled := false;
  oeMain.actionDelete.Enabled := false;
  oeMain.actionUp.enabled := false;
  oeMain.actionDown.enabled := false;
  oeMain.actionLeft.Enabled := false;
  oeMain.actionRight.Enabled := false;
 end;
end;

procedure ToeMain.DumpObjectlist1Click(Sender: TObject);
Var
 I: Integer;
 List: Tstringlist;

 Procedure Scan(Component: TComponent; AddToList: TStringlist);
 var
  I: Integer;
  Path: String;
 begin
  If (component is TControl) then begin
   Path := TutorialList.GetObjectPath(Component);
   If Path <> '' then begin
    AddToList.Add(TutorialList.GetObjectPath(Component) + '=' + (component as Tcontrol).Hint);
   end;
  end;
  For I := 0 to Component.ComponentCount - 1 do begin
   Scan(Component.Components[I], AddToList);
  end;
 end;

begin
 List := TStringlist.Create;
 For I := 0 to application.ComponentCount - 1 do begin
  Scan(Application.Components[I], List);
 end;
 List.SaveToFile('dumplist.txt');
 freeandnil(list);
end;

procedure ToeMain.temp1Click(Sender: TObject);
begin
 oeInspector.Events.TabVisible := false;
end;

procedure ToeMain.SetSnapping;
begin
 If Options.ToolWindows.Snapping.Main then oeMain.Tag := 999
  else oeMain.Tag := 0;
 If Options.ToolWindows.Snapping.SnipWin then SnipWin.Tag := 999
  else SnipWin.Tag := 0;
 If Options.ToolWindows.Snapping.OI then oeInspector.Tag := 999
  else oeInspector.Tag := 0;
 If Options.ToolWindows.Snapping.Palette then oePlugin.Tag := 999
  else oePlugin.Tag := 0;
 If Options.ToolWindows.Snapping.VarWin then VariableWin.Tag := 999
  else VariableWin.Tag := 0;
 If Options.ToolWindows.Snapping.ObjBrowser then ObjBrowser.Tag := 999
  else ObjBrowser.Tag := 0;
end;

procedure ToeMain.BringToFront2Click(Sender: TObject);
Var
 Cnt: Integer;
begin
 (CurrentSelectNode as TEdFormNode).Form.BringToFront;
 Cnt := CurrentSelectNode.Parent.Count;
 CurrentSelectNode.Parent.MoveChild(CurrentSelectNode.Index, Cnt-1);
 ObjBrowser.LoadFromNode();
end;

procedure ToeMain.SendToBack2Click(Sender: TObject);
begin
 (CurrentSelectNode as TEdFormNode).Form.SendToBack;
 CurrentSelectNode.Parent.MoveChild(CurrentSelectNode.Index, 0);
 ObjBrowser.LoadFromNode();
end;

procedure ToeMain.OptimizeFormSize1Click(Sender: TObject);
Var
 I, H, W: Integer;
 FormP: TFormPanel;
begin
 H := 0;
 W := 0;
 FormP := (CurrentSelectNode as TEdFormNode).Form;
 If FormP.VisualPanelList.Count = 0 then exit;
 For I := 0 to FormP.VisualPanelList.Count - 1 do begin
  If (FormP.VisualPanelList[I].Left + FormP.VisualPanelList[I].Width) > W then begin
   W := FormP.VisualPanelList[I].Left + FormP.VisualPanelList[I].Width;
  end;
  If (FormP.VisualPanelList[I].Top + FormP.VisualPanelList[I].Height) > H then begin
   H := FormP.VisualPanelList[I].Top + FormP.VisualPanelList[I].Height;
  end;
 end;
 FormP.Width := W;
 FormP.Height := H;
 FormP.Node.SetParameter('Width', IntToStr(W));
 FormP.Node.SetParameter('Height', IntToStr(H));
end;

procedure ToeMain.Popup_VisualsPopup(Sender: TObject);
Var
 Res, PlugIndex, InsertAt, I: Integer;
 MI: TMenuItem;
 ESV20: ICM2EditorSupportVis20;
 MC: Byte;
 MN, MH: PChar;
begin
 I := 0;
 InsertAt := 0;
 Repeat
  If Popup_Visuals.Items[I].Name = 'Delete1' then begin
   InsertAt := I;
  end;
  If Popup_Visuals.Items[I].Tag > 999 then begin
   Popup_Visuals.Items.Delete(I);
  end
   else
  begin
   Inc(I);
  end;
 Until I >= Popup_Visuals.Items.Count;
// popup_visuals.Items.in
 PlugIndex := -1;
 For I := 0 to vpl.Count - 1 do begin
  If GUIDTOstring((CurrentSelectNode As TEdVisualNode).VisualGUID) = GUIDToString(VPl[I].GUID) then begin
   PlugIndex := I;
  end;
 end;
 If plugindex = -1 then exit;
 Try
  ESV20 := CreateComObject (VPL[PlugIndex].GUID) as ICM2EditorSupportVis20;
 except
  exit;
 end;
 Res := ESV20.GetMenuCount(MC);
 If Res = S_OK then begin
  For I := 0 to MC - 1 do begin
   Res := ESV20.GetMenuItem(I, MN, MH);
   If Res = S_OK then begin
    MI := TMenuItem.Create(popup_visuals);
    MI.Tag := 1000 + I;
    MI.Caption := MN;
    MI.Hint := MH;
    MI.OnClick := OnVisMenu;
    Popup_visuals.Items.Insert(InsertAt, MI);
    Inc(InsertAt);
   end;
  end;
  MI := TMenuItem.Create(popup_visuals);
  MI.Tag := 99999;
  MI.Caption := '-';
  Popup_visuals.Items.Insert(InsertAt, MI);
 end;
end;

procedure ToeMain.OnVisMenu(Sender: TObject);
Var
 Res, PlugIndex, I: Integer;
 ESV20: ICM2EditorSupportVis20;
 ResultStr: Pchar;
begin
 PlugIndex := -1;
 For I := 0 to vpl.Count - 1 do begin
  If GUIDTOstring((CurrentSelectNode As TEdVisualNode).VisualGUID) = GUIDToString(VPl[I].GUID) then begin
   PlugIndex := I;
  end;
 end;
 If plugindex = -1 then exit;
 Try
  ESV20 := CreateComObject (VPL[PlugIndex].GUID) as ICM2EditorSupportVis20;
 except
  exit;
 end;
 Res := ESV20.OnMenu((Sender as TMenuItem).Tag - 1000, ResultStr);
 If Res = S_OK then begin
  If ResultStr <> '' then begin
   If uppercase(Copy(ResultStr, 1, length('<cml>'))) <> '<CML>' then begin
    ResultStr := PAnsiChar('<cml>' + ResultStr + '</cml>');
   end;
   CML.XML.Text := ResultStr;
   Try
    CML.Active := true;
   Except
    MessageDlg('The plugin returned invalid CML. Please inform the plugin coder.' + #13#10#13#10 + 'Returned CML:' + #13#10#13#10 + ResultStr, mtWarning, [mbOK], 0);
    exit;
   end;
   For I := 0 to CML.ChildNodes.Count - 1 do begin
    If uppercase(CML.ChildNodes[I].NodeName) = 'CML' then begin
     (CurrentSelectNode as TedVisualNode).GetContentNode.LoadChildren(CML.ChildNodes[I], (CurrentSelectNode as TedVisualNode).GetContentNode);
    end;
   end;
  end;
 end;
end;

procedure ToeMain.FormResize(Sender: TObject);
begin
 Statusbar1.Panels[0].Width := statusbar1.Width - 480;
end;

procedure ToeMain.DesktopImage1MouseMove(Sender: TObject;
  Shift: TShiftState; X, Y: Integer);
begin
 Statusbar1.Panels[1].Text := 'Cursor Coordinates [Desktop: X = ' + IntToStr(X) + ', Y = ' + IntToStr(Y) + ']';
end;

procedure ToeMain.CreateNewCML(Sender: TObject);
Var
 Node: TEdRawNode;
begin
  If assigned(tree) then begin
   If Tree.Modified then begin
    case MessageDlg('Configuration has been changed, Save ?', mtConfirmation, [mbYes, mbNo, mbCancel], 0) of
     mrCancel: exit;
     mrYes: Begin
             PerformSave(false);
           end;
    end;
   end;
  end;
  Select.Clear;
  GlobalFilename := '';
  UpdateCaption;
  If Assigned(Tree) then begin
   FreeAndNil(Tree);
  end;
  Tree := TEdCM2Tree.Create(Self, FormMgr, Addr(GPL), Addr(VPL), Addr(XPL));
  Tree.Root := TEdRootNode.Create(Tree, nil);
  Tree.Root.Name := '_ROOTNODE_';
  Node := Tree.Root.Add(ntCML);
  (Node as TEdCMLNode).SetupSelf(CMLVersion);
  Node := Node.Add(ntDisplay);
  (Node as TedDisplayNode).SetupSelf;
  Tree.Modified := false;
  SelectNode(Tree.Root, true);
  If TutorialList.WaitingForCallback <> '' then begin
   TutorialList.Callback(sender);
  end;
end;

procedure ToeMain.actionNewExecute(Sender: TObject);
Var
 Sel, It, t: Integer;
begin
 T := -1; It := -1;
 If not tempdlg.Execute(T, It) then exit;
 // MessageDlg('Tab: '+ IntToStR(T) + #13+#10+'Item: ' + IntToStr(I), mtWarning, [mbOK], 0);
 If (T = 0) and (It = 0) then begin
  CreateNewCML(self);
  Exit;
 end;
 Sel := -1;
 Case T of
  1: Begin
      // Forms
      Sel := StrToInt(tempdlg.ListView2.Items[It].SubItems[0]);
     end;
  2: begin
      // Visual objects
      Sel := StrToInt(tempdlg.ListView3.Items[It].SubItems[0]);
     end;
  3: begin
      // Sensor Objects
      Sel := StrToInt(tempdlg.ListView4.Items[It].SubItems[0]);
     end;
 end;
 If Sel = -1 then begin
  MessageDlg('Unable to find template', mtError, [mbOK], 0);
  exit;
 end;
 InsertTEmplate(CurrentSelectNode, Sel);
end;

procedure ToeMain.AddToTemplate1Click(Sender: TObject);
begin
 AddTempDlg.Execute(Select.CurrentSelectedNode);
end;

procedure ToeMain.AddToTemplate2Click(Sender: TObject);
begin
 AddTempDlg.Execute(Select.CurrentSelectedNode);
end;

procedure ToeMain.Bottom1Click(Sender: TObject);
Var
 FN: TEdFormNode;
 NewTop: Integer;
begin
 FN := ((CurrentSelectNode as TEdVisualNode).Parent.Parent as TEdFormNode);
 NewTop := FN.Form.Height - (CurrentSelectNode as TEdvisualNode).Visual.Height;
 (CurrentSelectNode as TEdvisualNode).Visual.Top := NewTop;
 (CurrentSelectNode as TEdVisualNode).GetParameterBlockNode.ChangeParameterValue('Top', IntToStr(NewTop));
end;

procedure ToeMain.Left1Click(Sender: TObject);
begin
 (CurrentSelectNode as TEdvisualNode).Visual.Left := 0;
 (CurrentSelectNode as TEdVisualNode).GetParameterBlockNode.ChangeParameterValue('Left', '0');
end;

procedure ToeMain.Right1Click(Sender: TObject);
Var
 FN: TEdFormNode;
 NewLeft: Integer;
begin
 FN := ((CurrentSelectNode as TEdVisualNode).Parent.Parent as TEdFormNode);
 NewLeft := FN.Form.Width - (CurrentSelectNode as TEdvisualNode).Visual.Width;
 (CurrentSelectNode as TEdvisualNode).Visual.Left := NewLeft;
 (CurrentSelectNode as TEdVisualNode).GetParameterBlockNode.ChangeParameterValue('Left', IntToStr(NewLeft));
end;

procedure ToeMain.op1Click(Sender: TObject);
begin
 (CurrentSelectNode as TEdvisualNode).Visual.Top := 0;
 (CurrentSelectNode as TEdVisualNode).GetParameterBlockNode.ChangeParameterValue('Top', '0');
end;

procedure ToeMain.StrechHorizontally1Click(Sender: TObject);
Var
 FN: TEdFormNode;
begin
 FN := ((CurrentSelectNode as TEdVisualNode).Parent.Parent as TEdFormNode);
 (CurrentSelectNode as TEdvisualNode).Visual.Width := FN.Form.Width;
 (CurrentSelectNode as TEdVisualNode).GetParameterBlockNode.ChangeParameterValue('Width', IntToStr(FN.Form.Width));
 (CurrentSelectNode as TEdvisualNode).Visual.Left := 0;
 (CurrentSelectNode as TEdVisualNode).GetParameterBlockNode.ChangeParameterValue('Left', '0');
end;

procedure ToeMain.StrechVertically1Click(Sender: TObject);
Var
 FN: TEdFormNode;
begin
 FN := ((CurrentSelectNode as TEdVisualNode).Parent.Parent as TEdFormNode);
 (CurrentSelectNode as TEdvisualNode).Visual.Height := FN.Form.Height;
 (CurrentSelectNode as TEdVisualNode).GetParameterBlockNode.ChangeParameterValue('Height', IntToStr(FN.Form.Height));
 (CurrentSelectNode as TEdvisualNode).Visual.Top := 0;
 (CurrentSelectNode as TEdVisualNode).GetParameterBlockNode.ChangeParameterValue('Top', '0');
end;

procedure ToeMain.actionObjectBrowserExecute(Sender: TObject);
begin
 ObjBrowser.Visible := not ObjBrowser.Visible;
 If TutorialList.WaitingForCallback <> '' then begin
  TutorialList.Callback(sender);
 end;
end;

procedure ToeMain.InsertTemplate(ToNode: TEdRawNode;
  TemplateIndex: Integer);
Var
 I, II: Integer;
 Found: Boolean;
 Node: TEdRawNode;
begin
 For I := 1 to countfilt(TemplateList[TemplateIndex].Required.Visuals, '|') do begin
  Found := false;
  For II := 0 to vpl.Count - 1 do begin
   if GUIDToString(vpl[II].GUID) = GetFilt(TemplateList[TemplateIndex].Required.Visuals, I, '|') Then begin
    Found := true;
    break;
   end;
  end;
  If not found then begin
   MessageDlg('This template uses a visual plugin you do not have installed', mtInformation, [mbOK], 0);
   exit;
  end;
 end;
 For I := 1 to countfilt(TemplateList[TemplateIndex].Required.Generals, '|') do begin
  Found := false;
  For II := 0 to gpl.Count - 1 do begin
   if GUIDToString(gpl[II].GUID) = GetFilt(TemplateList[TemplateIndex].Required.Generals, I, '|') Then begin
    Found := true;
    break;
   end;
  end;
  If not found then begin
   MessageDlg('This template uses a general plugin you do not have installed', mtInformation, [mbOK], 0);
   exit;
  end;
 end;

 CML.XML.Text := '<cml>' + TemplateList[TemplateIndex].ActualCML + '</cml>';
 Try
  CML.Active := true;
 except
  MessageDlg('This template doesn''t contain valid XML.', mtError, [mbOK], 0);
  exit;
 end;
 If uppercase(templateList[TemplateIndex].Information.CMLType) = 'FORM' then begin
  // Form
  Tree.GetDisplayNode.LoadChildren(CML.ChildNodes[0], Tree.GetDisplayNode);
 end;
 If uppercase(templateList[TemplateIndex].Information.CMLType) = 'VISUAL' then begin
  // Visual Objects
  Node := ToNode;;
  while (Node.NodeType <> ntForm) or (Node = nil) do begin
   Node := Node.Parent;
  end;
  If Node <> nil then begin
   If Node.NodeType = ntForm then begin
    (Node as TEdFormNode).GetContentNode.LoadChildren(CML.ChildNodes[0], Node);
   end;
  end;
 end;
 If uppercase(TemplateList[TemplateIndex].Information.CMLType) = 'SENSOR' then begin
  // Sensor objects
  Node := ToNode;
  while (Node.NodeType <> ntVisual) or (Node = nil) do begin
   Node := Node.Parent;
  end;
  If Node <> nil then begin
   If Node.NodeType = ntVisual then begin
    (Node as TEdVisualNode).GetContentNode.LoadChildren(CML.ChildNodes[0], Node);
   end;
  end;
 end;
 ObjBrowser.LoadFromNode();
end;

procedure ToeMain.AddEvent1Click(Sender: TObject);
Var
 E, M, C: String;
// EventsNode: TEdEventsNode;
begin
 E := '';
 M := '(none)';
 C := '';
 If not AddEventDlg.Execute(E, M, C) then exit;
// EventsNode := (CurrentSelectNode as TEdFormNode).GetEventsNode(true);
// (EventsNode.Add(ntEventHandler) as TEventHandlerNode).
end;

end.
