/* An instance of ActorApp is stored in TheApp, and is sent an
init message at startup.  Any application should have an
object in TheApp that can respond to init, abort and shouldClose,
containing application-wide data. */!!

inherit(Application, #ActorApp,
#(workspace /* The Actor workspace window */
imageName /* Name for the next snapshot file */
dynamic   /* dynamic for next snapshot */
static    /* static for next snapshot */), 2, nil)!!

now(class(ActorApp))!!

/* Dummy install to prevent an attempt to seal-off Actor. */
Def install(self, ima, dynamic, static)
{ errorBox("SEAL-OFF", "Cannot seal-off Actor Development environment.");
}!!

now(ActorApp)!!

/* Clear the mainWindow and redraw the current window
  if necessary.  This method returns true (self) to
  indicate that the sender may continue the abort
  process. */
Def abort(self)
{ fill(buffer(mainWindow), ' ');
  if ThePort ~= mainWindow
  then invalidate(ThePort);
  endif;
}!!

/* Close the workspace and get rid of it. */
Def destroyWorkspace(self)
{ if workspace
  then destroy(workspace);
    workspace := nil;
  endif;
}!!

/* This method is defined for compatibility with earlier
  versions of Actor. */
Def display(self)
{ ^mainWindow;
}!!

/* Return the dynamic instance variable. */
Def dynamic(self, value)
{ ^dynamic;
}!!

/* Return a string with current information about image,
  with current date and time. */
Def imageInfo(self)
{ ^imageName + ", " + timeStr() + ", "+ dateStr();
}!!

/* Return the imageName instance variable. */
Def imageName(self)
{ ^imageName;
}!!

/* Return true if there is no image file by the name
  of name or the user says it is OK to overwrite an
  existing image file. */
Def imageOK(self, name)
{ ^(name = imageName) cor
    not(exists(File, name, 0)) cor
    (yesNoBox("The image file "+name+" already exists",
      "Do you want to over write it?") == IDYES);
}!!

/* Start Actor with the tiled display window, which must
  be created first. Next, start a workspace window, if
  possible, then recreate any other windows that can
  respond to a recreate message. This method is executed at
  system startup as a way to initialize the entire Actor
  environment. */
Def init(self, str)
{ if not(init(self:ancestor, str))
    ^nil;
  endif;
  DeadWindows := new(Set, 4);
  if mainWindow
  then recreate(mainWindow);
    forceOnScreen(mainWindow);
  else startMainWindow(self);
  endif;
  add(OutPorts:late, mainWindow);
  addAbout(mainWindow);
  removeUsing(OpenWindows, mainWindow, {});
  if workspace
  then recreate(workspace);
  else
    if Classes[#WorkSpace]
    then startWorkSpace(self);
    endif;
  endif;
  removeUsing(OpenWindows, workspace, {});
  do(OpenWindows:late, {using(window) recreate(window);});
  if size(DeadWindows:late) > 0
  then do(DeadWindows:late,
    {using(window)
      remove(OpenWindows:late, window);
    });
    beep();
    printLine(loadString(382));
    beep();
  endif;
  ToolWindow cand loadDirty(ToolWindow);
  if workspace
  then forceOnScreen(workspace);
    changeLog(workspace,
      "/* Started image: " + imageInfo(self) + " */");
    setFocus(workspace);
    /* Call PostMessage(handle(workspace), messageID(#WM_SYSCOMMAND), IDSABOUT, 0); */
  endif;
  initMemory();
  ^messageLoop(self);
}!!

/* Reset the entire Actor Application.  Clear the
  mainWindow and the workspace. */
Def reset(self)
{ mainWindow cand cls(initWorkText(resetLocRect(mainWindow)));
  workspace cand cls(initWorkText(resetLocRect(workspace)));
}!!

/* Set the dynamic instance variable. */
Def setDynamic(self, value)
{ ^dynamic := value;
}!!

/* Set the imageName instance variable.  Ask about
 overwriting an existing image. */
Def setImageName(self, name)
{ if imageOK(self, name)
  then ^imageName := name;
  endif;
  ^nil;
}!!

/* Set the static instance variable. */
Def setStatic(self, value)
{ ^static := value;
}!!

/* Take care of business before terminating the application. */
Def shouldClose(self)
{ do(OpenWindows:late,
  {using(win)
    bringToTop(win);
    if not(shouldClose(win))
    then ^nil;
    endif;
  });
  if ToolWindow
  then ^shouldClose(ToolWindow);
  endif;
}!!

/* Save a snapshot, move and backup class source files.
  Re-init the set of 'dirty' class names. Present an Input
  Dialog to verify the name of the image file. */
Def snapshot(self | snapFile)
{ ToolWindow cand snapshot(ToolWindow);
  showWaitCurs();
  fill(buffer(mainWindow), nil);
  if workspace
  then changeLog(workspace,
    printNewLine("/* Snapshot: " + imageInfo(self) + " */"));
  endif;
  snap(snapFile := create(setName(new(File), imageName)), static, dynamic);
  close(snapFile);
  showOldCurs();
}!!

/* Edit the image name and the static and dynamic settings
  by presenting an Input Dialog.  Then take a snapshot.
  (See ActorApp:snapshot.) */
Def snapshotAs(self | snapFile)
{ if runModal(new(SnapDialog, imageName, static, dynamic),
    SNAP_BOX, ThePort) == IDOK
  then snapshot(self);
  endif;
}!!

/* Start a display window the first time.  Once created,
  this method may be removed from system. */
Def startMainWindow(self)
{ mainWindow := newMain(WorkWindow, nil, loadString(160), nil);
  setBuffer(mainWindow, new(String, 120));
  fill(buffer(mainWindow), ' ');
  home(mainWindow);
  show(mainWindow, CmdShow);
}!!

/* Start a workspace for the first time.  Once a workspace object
  belongs to OpenWindows, this method may be eliminated from the
  system. */
Def startWorkSpace(self)
{ workspace := new(Classes[#WorkSpace], mainWindow,
    loadString(320), loadString(321), nil);
  show(workspace, 1);
}!!

/* Return the static instance variable. */
Def static(self, value)
{ ^static;
}!!

/* Return the workspace instance variable. */
Def workspace(self)
{ ^workspace;
}!!
