⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cpuobservers.pas

📁 一个不出名的GBA模拟器
💻 PAS
字号:
//////////////////////////////////////////////////////////////////////
//                                                                  //
// CpuObservers.pas: CPU Observer Framework                         //
//   Observer superclass and observer list management               //
//                                                                  //
// The contents of this file are subject to the Bottled Light       //
// Public License Version 1.0 (the "License"); you may not use this //
// file except in compliance with the License. You may obtain a     //
// copy of the License at http://www.bottledlight.com/BLPL/         //
//                                                                  //
// Software distributed under the License is distributed on an      //
// "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or   //
// implied. See the License for the specific language governing     //
// rights and limitations under the License.                        //
//                                                                  //
// The Original Code is the Mappy VM User Interface, released       //
// April 1st, 2003. The Initial Developer of the Original Code is   //
// Bottled Light, Inc. Portions created by Bottled Light, Inc. are  //
// Copyright (C) 2001-2003 Bottled Light, Inc. All Rights Reserved. //
//                                                                  //
// Author(s):                                                       //
//   Michael Noland (joat), michael@bottledlight.com                //
//                                                                  //
// Changelog:                                                       //
//   1.0: First public release (April 1st, 2003)                    //
//                                                                  //
// Notes:                                                           //
//   Mappy VM uses an observer model, where any number of data      //
//   viewers, or 'observers' can be registered, and they'll appear  //
//   in the viewers menu item for the user to activate or close     //
//   at will.  When an observer is active, its UpdateObserver       //
//   method is called after each simulation step (either one cycle  //
//   or an entire frame).  Observers also call UpdateObservers to   //
//   notify other observers when they've modified the MVM core      //
//   state in any way.                                              //
//                                                                  //
//   This model has a couple of advantages, most notably less       //
//   usage and extensibility.  Memory usage because observer forms  //
//   are created on the fly when needed, rather than kept around in //
//   memory on the oft chance someone will use it. Extensability    //
//   because making a new observer is a case of creating a new form //
//   and descending it from TCpuObserver, implementing two methods, //
//   and adding a RegisterViewer call to the bottom of the unit.    //
//                                                                  //
//   This idea of demand-creation of forms is also used for dialogs //
//   such as Audio Options.  They're also descended from the same   //
//   TCpuObserver, and behave in exactly the same way, except they  //
//   are invoked from a different menu item in the user interface.  //
//                                                                  //
//   A slightly more recent addition is the decentralization of     //
//   loading/saving config data.  Now all an observer has to do is  //
//   override two virutal methods and grab/store their config state //
//   into a TIniFile (registry be damned!)                          //
//                                                                  //
//////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////
unit CpuObservers; ///////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////
interface ////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////

uses
  SysUtils, Classes, Contnrs, Graphics, Controls, Forms, Math, Menus,
  IniFiles, console, nexus;

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

type
  TCpuObserver = class(TForm)
  private
    myItem: TMenuItem;
  protected
    procedure Shutdown;
    procedure observerClose(Sender: TObject; var Action: TCloseAction);
  public
    class function OCaption: string; virtual; abstract;
    procedure UpdateObserver; virtual; abstract;
    procedure LoadSettings(ini: TIniFile); virtual;
    procedure SaveSettings(ini: TIniFile); virtual;

    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  end;

  TCpuObserverClass = class of TCpuObserver;

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

procedure RegisterViewer(typ: TCpuObserverClass);
procedure RegisterDialog(typ: TCpuObserverClass);
function CreateObserver(name: string; menuItem: TMenuItem): TCpuObserver;
function FindObserver(name: string): TCpuObserver;
procedure UpdateObservers;
procedure CloseObservers;

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

var
  observerList: TObjectList;
  observers, guiObservers: TStringList;

//////////////////////////////////////////////////////////////////////
implementation ///////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////

procedure RegisterViewer(typ: TCpuObserverClass);
begin
  observers.AddObject(typ.OCaption, TObject(typ));
end;

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

procedure RegisterDialog(typ: TCpuObserverClass);
begin
  guiObservers.AddObject(typ.OCaption, TObject(typ));
end;

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

function CreateObserver(name: string; menuItem: TMenuItem): TCpuObserver;
var
  i: integer;
begin
  Result := nil;

  i := observers.IndexOf(name);
  if i > -1 then
    Application.CreateForm(TCpuObserverClass(observers.objects[i]), Result)
  else begin
    i := guiObservers.IndexOf(name);
    Application.CreateForm(TCpuObserverClass(guiObservers.objects[i]), Result);
  end;

  if i > - 1 then begin
    observerList.Add(Result);

    Result.myItem := menuItem;
    Result.myItem.Checked := true;
    Result.Show;
  end;
end;

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

function FindObserver(name: string): TCpuObserver;
var
  i: integer;
begin
  for i := 0 to observerList.Count - 1 do begin
    Result := observerList.Items[i] as TCpuObserver;
    if Result.OCaption = name then Exit;
  end;
  Result := nil;
end;

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

procedure UpdateObservers;
var
  i: integer;
begin
  // Update each open observer
  for i := 0 to observerList.count - 1 do
    (observerList.Items[i] as TCpuObserver).UpdateObserver;
end;

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

procedure CloseObservers;
begin
  while observerList.Count > 0 do (observerList.Items[0] as TCpuObserver).Close;
  observerList.Clear;
end;

//////////////////////////////////////////////////////////////////////
// TCpuObserver //////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////

constructor TCpuObserver.Create(AOwner: TComponent);
var
  ini: TIniFile;
begin
  inherited;
  OnClose := observerClose;

  // Set some things up
  Caption := ocaption;

  // Load the settings
  ini := TIniFile.Create(appIniFile);
  LoadSettings(ini);
  ini.Free;
end;

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

destructor TCpuObserver.Destroy;
begin
  Shutdown;
  inherited;
end;

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

procedure TCpuObserver.Shutdown;
var
  ini: TIniFile;
begin
  // Save the settings
  ini := TIniFile.Create(appIniFile);
  SaveSettings(ini);
  ini.Free;
end;

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

procedure TCpuObserver.observerClose(Sender: TObject; var Action: TCloseAction);
var
  ref: TCpuObserver;
  index: integer;
begin
  // Uncheck the observer entry in the view menu
  ref := Sender as TCpuObserver;
  ref.myItem.Checked := false;

  // Close the observer and remove it from the list
  Action := caFree;
  index := observerList.IndexOf(Sender);
  if index > -1 then observerList.Delete(index);
end;

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

procedure TCpuObserver.LoadSettings(ini: TIniFile);
var
  ws: TWindowState;
begin
  ws := TWindowState(Min(2, Max(0, ini.ReadInteger(OCaption, 'WindowState', Ord(wsNormal)))));
  if ws <> wsMaximized then begin
    Width := ini.ReadInteger(OCaption, 'Width', Width);
    Height := ini.ReadInteger(OCaption, 'Height', Height);
    Left := ini.ReadInteger(OCaption, 'Left', Left);
    Top := ini.ReadInteger(OCaption, 'Top', Top);
  end;
  WindowState := ws;
end;

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

procedure TCpuObserver.SaveSettings(ini: TIniFile);
begin
  ini.WriteInteger(OCaption, 'WindowState', Ord(WindowState));
  ini.WriteInteger(OCaption, 'Left', Left);
  ini.WriteInteger(OCaption, 'Top', Top);
  ini.WriteInteger(OCaption, 'Width', Width);
  ini.WriteInteger(OCaption, 'Height', Height);
end;

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

initialization
  observers := TStringList.Create;
  guiObservers := TStringList.Create;
  observerList := TObjectList.Create(false);
finalization
  observerList.Free;
  guiObservers.Free;
  observers.Free;
end.

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

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -