home *** CD-ROM | disk | FTP | other *** search
- unit Plotmenu;
-
- {$I Plot.inc}
-
- {-----------------------------------------------------------------------------
- The contents of this file are subject to the Q Public License
- ("QPL"); you may not use this file except in compliance
- with the QPL. You may obtain a copy of the QPL from
- the file QPL.html in this distribution, derived from:
-
- http://www.trolltech.com/products/download/freelicense/license.html
-
- The QPL prohibits development of proprietary software.
- There is a Professional Version of this software available for this.
- Contact sales@chemware.hypermart.net for more information.
-
- Software distributed under the QPL is distributed on an "AS IS" basis,
- WITHOUT WARRANTY OF ANY KIND, either expressed or implied. See the QPL for
- the specific language governing rights and limitations under the QPL.
-
- The Original Code is: Axis.pas, released 12 September 2000.
-
- The Initial Developer of the Original Code is Mat Ballard.
- Portions created by Mat Ballard are Copyright (C) 1999 Mat Ballard.
- Portions created by Microsoft are Copyright (C) 1998, 1999 Microsoft Corp.
- All Rights Reserved.
-
- Contributor(s): Mat Ballard e-mail: mat.ballard@chemware.hypermart.net.
-
- Last Modified: 02/25/2000
- Current Version: 2.00
-
- You may retrieve the latest version of this file from:
-
- http://Chemware.hypermart.net/
-
- This work was created with the Project JEDI VCL guidelines:
-
- http://www.delphi-jedi.org/Jedi:VCLVCL
-
- in mind.
-
- Purpose:
- The purpose of this module is to provide the developer using TPlot a quick
- method of rapidly implementing menu access to the TPlot functions.
-
- It will be augmented by a TPlotAction module at a later stage.
-
- Known Issues:
- - Since TPlotMenu is useless without TPlot, there is only the one
- registration unit: TPlot_Reg.pas.
- - Is INVISIBLE in D1 Runtime - works perfectly in the designer, but
- no menu is present in running applications. If anyone wants to help fix
- this, please do so and let me know the answer.
- -----------------------------------------------------------------------------}
-
- interface
-
- uses
- Classes, SysUtils,
- {$IFDEF WINDOWS}
- Menus,
- {$ENDIF}
- {$IFDEF WIN32}
- Menus,
- {$ENDIF}
- {$IFDEF LINUX}
- QMenus,
- {$ENDIF}
-
- Misc, Plot, Plotdefs;
-
- const
- TPLOTMENU_VERSION = 200;
-
- FILE_TAG = 1000;
- HELP_TAG = 1095;
- ABOUT_TAG = 1096;
- REOPEN_TAG = 1097;
- EXIT_DIV_TAG = 1098;
- EXIT_TAG = 1099;
-
- mnuReopen = 2;
-
- type
- TPlotMenu = class(TMainMenu)
- private
- {The plot to which this menu is linked:}
- FPlot: TPlot;
- {and the limit of the number of those files:}
- FHistoryLimit: Byte;
- {Creates the menus after the Plot property is set:}
- procedure CreateMenus;
- {Creates the Reopen menu item and Submenu and adds it to the File menu:}
- procedure CreateReopenSubMenu;
- {Gets the History List as a string:}
- function GetHistory: String;
- protected
- {function GetPlot(Target: TObject): TPlot; virtual;}
- procedure HandleClick(Sender: TObject);
- {The default event handler for all menu items. It forwards the event to TPlot
- by calling the latter's HandleClick method, which then passes it onto the
- appropriate handler method.}
-
- {$IFNDEF DELPHI1}
- procedure HandleClunk(Sender: TObject);
- {Called when the menu is clicked on, it sets the Enabled property of all menuitems.}
- {$ENDIF}
-
- procedure HandleFileClick(Sender: TObject);
- {Called when the a Reopen File menuitem is clicked on.}
- procedure Notification(AComponent: TComponent; Operation: TOperation); override;
- {Implementation of the standard Notification method for linked components.}
- procedure SetPlot(Value: TPlot);
- {Sets the pointer to the parental TPlot, creates the menus and their OnClicks}
- public
- property History: String read GetHistory stored FALSE;
- {A History List, CRLF delimited, of previously closed files.
- Just use it as:
- MyStringList.Create;
- MyStringList.Text := PlotMenu1.History;}
-
- constructor Create(AOwner: TComponent); override;
- {The standard constructor.}
- destructor Destroy; override;
- {The standard destructor.}
-
- procedure ApplyOptions(Value: TPopupOptions);
-
- procedure AddHistory(Value: String);
- {Adds one more file to the History List.}
- function MenuExists(ATag: Integer; ACaption: String): Boolean;
- {Does AMenu already exist in Self ?}
- {}
- {The basis for comparison is both the Tag and Caption}
- procedure SetUpOnClicks;
- {This assigns the HandleClick and HandleClunk methods to all menu items with
- relevant Tags and that are already unassigned.}
- published
- property HistoryLimit: Byte read FHistoryLimit write FHistoryLimit;
- {The limit of the number of files in the History List.}
- property Plot: TPlot read FPlot write SetPlot;
- {The plot to which TPlotMenu is linked.}
- end;
-
- implementation
-
- {Constructor and Destructor ---------------------------------------------------}
- {------------------------------------------------------------------------------
- Constructor: TPlotMenu.Create
- Description: standard Constructor
- Author: Mat Ballard
- Date created: 04/25/2000
- Date modified: 04/25/2000 by Mat Ballard
- Purpose: sets the Plot Property
- Known Issues:
- ------------------------------------------------------------------------------}
- constructor TPlotMenu.Create(AOwner: TComponent);
- begin
- inherited Create(AOwner);
- FPlot := nil;
- FHistoryLimit := 10;
- end;
-
- {------------------------------------------------------------------------------
- Destructor: TPlotMenu.Destroy
- Description: standard Destructor
- Author: Mat Ballard
- Date created: 04/25/2000
- Date modified: 04/25/2000 by Mat Ballard
- Purpose: frees the Plot Property
- Known Issues:
- ------------------------------------------------------------------------------}
- destructor TPlotMenu.Destroy;
- begin
- if FPlot <> nil then
- {$IFDEF DELPHI1}
- FPlot.Notification(Self, opRemove);
- {$ELSE}
- FPlot.FreeNotification(Self);
- {$ENDIF}
- FPlot := nil;
- inherited Destroy;
- end;
-
- {Get functions and Set procedures ---------------------------------------------}
- {------------------------------------------------------------------------------
- Procedure: TPlotMenu.AddHistory
- Description: Adds one more file to the History List
- Author: Mat Ballard
- Date created: 09/01/2000
- Date modified: 09/01/2000 by Mat Ballard
- Purpose: History List management
- Known Issues:
- ------------------------------------------------------------------------------}
- procedure TPlotMenu.AddHistory(Value: String);
- var
- i: Integer;
- pReopen: TMenuItem;
- TempMenuItem: TMenuItem;
- begin
- if (csDestroying in ComponentState) then exit;
- if (Length(Value) = 0) then exit;
-
- pReopen := Self.Items[0].Items[mnuReopen];
- if (pReopen = nil) then
- exit;
-
- {$IFNDEF DELPHI1}
- for i := 0 to pReopen.Count-1 do
- begin
- if (pReopen.Items[i].Hint = Value) then
- begin
- {Change the order of existing entries:}
- pReopen.Items[i].MenuIndex := 0;
- exit;
- end;
- end;
- {$ENDIF}
-
- TempMenuItem := TMenuItem.Create(Self);
- {Note: we store the full pathname in the Hint because D5 mangles the Caption:
- the AutoHotKeys property does not work ! Also looks neater !}
- TempMenuItem.Caption := ExtractFileName(Value);
- TempMenuItem.Hint := Value;
- TempMenuItem.OnClick := HandleFileClick;
- pReopen.Insert(0, TempMenuItem);
-
- while (pReopen.Count > FHistoryLimit) do
- pReopen.Delete(pReopen.Count-1);
-
- pReopen.Enabled := TRUE;
- end;
-
- {------------------------------------------------------------------------------
- Procedure: TPlotMenu.GetHistory
- Description: Gets the History List as a string.
- Author: Mat Ballard
- Date created: 08/13/2000
- Date modified: 08/13/2000 by Mat Ballard
- Purpose: History List management
- Known Issues:
- ------------------------------------------------------------------------------}
- function TPlotMenu.GetHistory: String;
- var
- i: Integer;
- TheString: String;
- pReopen: TMenuItem;
- begin
- TheString := '';
- pReopen := Self.Items[0].Items[mnuReopen];
-
- for i := 0 to pReopen.Count-1 do
- TheString := TheString + pReopen.Items[i].Caption;
-
- GetHistory := TheString;
- end;
-
- {------------------------------------------------------------------------------
- Procedure: TPlotMenu.SetPlot
- Description: standard property Set procedure
- Author: Mat Ballard
- Date created: 04/25/2000
- Date modified: 04/25/2000 by Mat Ballard
- Purpose: sets the Plot Property
- Known Issues:
- ------------------------------------------------------------------------------}
- procedure TPlotMenu.SetPlot(Value: TPlot);
- begin
- if Value <> FPlot then
- begin
- if (Value = nil) then
- begin
- FPlot := Value;
- FPlot.SetPlotMenu(TMainMenu(nil));
- end
- else
- begin
- FPlot := Value;
- {$IFDEF DELPHI1}
- Value.Notification(Self, opInsert); {???}
- {$ELSE}
- Value.FreeNotification(Self);
- {$ENDIF}
- CreateMenus;
- SetUpOnClicks;
- CreateReopenSubMenu;
- FPlot.SetPlotMenu(TMainMenu(Self));
- end;
- end;
- end;
-
- {General methods --------------------------------------------------------------}
- {------------------------------------------------------------------------------
- Procedure: TCustomPlot.CreateMenus
- Description: creates popup menus that are accessible by right-click
- Author: Mat Ballard
- Date created: 12/1/1999
- Date modified: 04/20/2000 by Mat Ballard
- Purpose: modularize user-interface code
- Known Issues: this was a bitch to get right !
- ------------------------------------------------------------------------------}
- procedure TPlotMenu.CreateMenus;
- var
- i,
- j,
- HelpMenuIndex: Word;
- {This following is just a dummy matrix of menu items used to create sub-menus,
- then removed and the menuitems freed.}
- TempMenu: array [0..31] of array [0..0] of TMenuItem;
- TempMenuItem: TMenuItem;
- begin
- {don't create menus when the Plot property is streamed in:}
- if (csLoading in ComponentState) then exit;
-
- {who needs more than 32 menus ?!}
- if (FPlot.PlotPopupMenu.Items.Count > 32) then raise
- EComponentError.CreateFmt(sCreateMenus1, [FPlot.PlotPopupMenu.Items.Count]);
-
- {create the sub-menus:}
- for i := 0 to FPlot.PlotPopupMenu.Items.Count-1 do
- begin
- {we create a temporary menu array to add the submenu, and then later remove it:}
- TempMenu[i][0] := TMenuItem.Create(Self);
- {don't re-create a menu if it already exists:}
- if (not MenuExists(
- FPlot.PlotPopupMenu.Items[i].Tag,
- FPlot.PlotPopupMenu.Items[i].Caption)) then
- begin
- TempMenuItem := NewSubMenu(
- FPlot.PlotPopupMenu.Items[i].Caption,
- 0,
- FPlot.PlotPopupMenu.Items[i].Name,
- TempMenu[i]);
- TempMenuItem.Tag := FPlot.PlotPopupMenu.Items[i].Tag;
- Self.Items.Add(TempMenuItem);
- end;
- {create the menus in each sub-menu:}
- for j := 0 to FPlot.PlotPopupMenu.Items[i].Count-1 do
- begin
- if (not MenuExists(
- FPlot.PlotPopupMenu.Items[i].Items[j].Tag,
- FPlot.PlotPopupMenu.Items[i].Items[j].Caption)) then
- begin
- TempMenuItem := TMenuItem.Create(Self);
- TempMenuItem.Caption := FPlot.PlotPopupMenu.Items[i].Items[j].Caption;
- TempMenuItem.Name := FPlot.PlotPopupMenu.Items[i].Items[j].Name;
- TempMenuItem.Tag := FPlot.PlotPopupMenu.Items[i].Items[j].Tag;
- TempMenuItem.Hint := FPlot.PlotPopupMenu.Items[i].Items[j].Hint;
- {$IFDEF COMPILER4_UP}
- TempMenuItem.ImageIndex := FPlot.PlotPopupMenu.Items[i].Items[j].ImageIndex;
- {$ENDIF}
- {add the TempMenuItem to the popup:}
- Self.Items[i].Add(TempMenuItem);
- end;
- end; {j over menu items}
- {remove the temporary menu array used to create the submenu:}
- if (Self.Items[i].Items[0].Caption = '') then
- begin
- Self.Items[i].Remove(TempMenu[i][0]);
- {then free it:}
- TempMenu[i][0].Free;
- end;
- end; {i over submenus}
-
- {don't re-create a menu if it already exists:}
- if (Self.Items.Count = FPlot.PlotPopupMenu.Items.Count) then
- begin
- HelpMenuIndex := FPlot.PlotPopupMenu.Items.Count;
- {we now add a "Help" menu:}
- {first, we create a temporary menu array to add the submenu, and then later remove it:}
- TempMenu[HelpMenuIndex][0] := TMenuItem.Create(Self);
- TempMenuItem := NewSubMenu(
- sHelp,
- 0,
- 'HelpMenu',
- TempMenu[HelpMenuIndex]);
- TempMenuItem.Tag := HELP_TAG;
- Self.Items.Add(TempMenuItem);
- {create the "About" menu item:}
- TempMenuItem := TMenuItem.Create(Self);
- TempMenuItem.Caption := '&' + sAbout + '...';
- TempMenuItem.Name := 'AboutMenu';
- TempMenuItem.Tag := ABOUT_TAG;
- TempMenuItem.Hint := sAuthor;
- {add the TempMenuItem to the popup:}
- Self.Items[HelpMenuIndex].Add(TempMenuItem);
-
- {remove the temporary menu array used to create the submenu:}
- if (Self.Items[HelpMenuIndex].Items[0].Caption = '') then
- begin
- Self.Items[HelpMenuIndex].Remove(TempMenu[HelpMenuIndex][0]);
- {then free it:}
- TempMenu[HelpMenuIndex][0].Free;
- end;
- end;
-
- {Add a divider to the File menu:}
- if (not MenuExists(EXIT_DIV_TAG, '-')) then
- begin
- TempMenuItem := TMenuItem.Create(Self);
- TempMenuItem.Caption := '-';
- TempMenuItem.Tag := EXIT_DIV_TAG;
- Self.Items[0].Add(TempMenuItem);
- end;
-
- {Add an "Exit" to the File menu:}
- if (not MenuExists(EXIT_TAG, 'E&xit')) then
- begin
- TempMenuItem := TMenuItem.Create(Self);
- TempMenuItem.Caption := sExit;
- TempMenuItem.Tag := EXIT_TAG;
- TempMenuItem.Name := 'ExitMenuItem';
- Self.Items[0].Add(TempMenuItem);
- end;
- end;
-
- {------------------------------------------------------------------------------
- Procedure: TCustomPlot.CreateReopenSubMenu
- Description: creates popup menus that are accessible by right-click
- Author: Mat Ballard
- Date created: 12/1/1999
- Date modified: 04/20/2000 by Mat Ballard
- Purpose: modularize user-interface code
- Known Issues: this was a bitch to get right !
- ------------------------------------------------------------------------------}
- procedure TPlotMenu.CreateReopenSubMenu;
- var
- {This following is just a dummy matrix of menu items used to create sub-menus,
- then removed and the menuitems freed.}
- TempMenu: array [0..0] of TMenuItem;
- TempMenuItem: TMenuItem;
- begin
- {don't create menus when the Plot property is streamed in:}
- if (csLoading in ComponentState) then exit;
-
- {don't re-create a menu if it already exists:}
- if ((Self.Items[0].Items[mnuReopen].Tag = REOPEN_TAG) and
- (Self.Items[0].Items[mnuReopen].Caption = sReopen)) then
- exit;
-
- {we create a temporary menu array to add the submenu, and then later remove it:}
- TempMenu[0] := TMenuItem.Create(Self);
- TempMenu[0].Visible := FALSE;
- TempMenuItem := NewSubMenu(
- sReopen,
- 0,
- 'ReopenSubMenu',
- TempMenu);
-
- TempMenuItem.Tag := REOPEN_TAG;
- {disable the "Reopen" menu because it has no entries:}
- {$IFNDEF SHOWALLMENUS}
- TempMenuItem.Enabled := FALSE;
- {$ENDIF}
-
- Self.Items[0].Insert(mnuReopen, TempMenuItem);
- {remove the temporary menu array used to create the submenu:}
- Self.Items[0].Items[mnuReopen].Remove(TempMenu[0]);
- {then free it:}
- TempMenu[0].Free;
- end;
-
- {------------------------------------------------------------------------------
- Procedure: TPlotMenu.SetUpOnClicks
- Description: points all appropriate OnClick event handlers at the TPlot.HandleClick method
- Author: Mat Ballard
- Date created: 04/25/2000
- Date modified: 04/25/2000 by Mat Ballard
- Purpose: responding to user menu clicks
- Known Issues: have to call this manually (after setting Plot property)
- ------------------------------------------------------------------------------}
- procedure TPlotMenu.SetUpOnClicks;
- var
- i,
- j: Integer;
- begin
- for i := 0 to Self.Items.Count-1 do
- begin
- {don't change any existing assignments:}
- {$IFNDEF DELPHI1}
- if ((Self.Items[i].Tag >= FILE_TAG) and
- (Self.Items[i].Tag < EXIT_TAG)) then
- if (not Assigned(Self.Items[i].OnClick)) then
- Self.Items[i].OnClick := HandleClunk;
- {$ENDIF}
-
- for j := 0 to Self.Items[i].Count-1 do
- begin
- {gotta have a valid tag:}
- if ((Self.Items[i].Items[j].Tag >= FILE_TAG) and
- (Self.Items[i].Items[j].Tag < EXIT_TAG)) then
- begin
- {separators don't have OnClicks}
- if (Self.Items[i].Items[j].Caption <> '-') then
- {don't change any existing assignments:}
- {$IFDEF COMPILER2_UP}
- if (not Assigned(Self.Items[i].Items[j].OnClick)) then
- {$ENDIF}
- Self.Items[i].Items[j].OnClick := HandleClick;
- end;
- end;
- end;
- end;
-
- {------------------------------------------------------------------------------
- Procedure: TPlotMenu.HandleClick
- Description: Click Event handler for all menus
- Author: Mat Ballard
- Date created: 04/25/2000
- Date modified: 04/25/2000 by Mat Ballard
- Purpose: responds to user clicks of the menus by firing the TPlot method
- Known Issues:
- ------------------------------------------------------------------------------}
- procedure TPlotMenu.HandleClick(Sender: TObject);
- begin
- if (FPlot = nil) then exit;
- if (TMenuItem(Sender).Tag < HELP_TAG) then
- FPlot.HandleClick(Self, TMenuItem(Sender).Tag)
- else if (TMenuItem(Sender).Tag = ABOUT_TAG) then
- FPlot.ShowAbout;
- end;
-
- {$IFNDEF DELPHI1}
- {------------------------------------------------------------------------------
- Procedure: TPlotMenu.HandleClunk
- Description: Click Event handler for all menus
- Author: Mat Ballard
- Date created: 04/25/2000
- Date modified: 04/25/2000 by Mat Ballard
- Purpose: responds to user clicks of the menus by setting the menuitem state (Enabled property)
- Known Issues:
- ------------------------------------------------------------------------------}
- procedure TPlotMenu.HandleClunk(Sender: TObject);
- begin
- if (FPlot = nil) then exit;
- FPlot.DetermineMenuEnabledness(Self);
- end;
- {$ENDIF}
-
- {------------------------------------------------------------------------------
- Procedure: TPlotMenu.HandleFileClick
- Description: Click Event handler for all Reopen file menus
- Author: Mat Ballard
- Date created: 04/25/2000
- Date modified: 04/25/2000 by Mat Ballard
- Purpose: responds to user clicks of the FilaName menus by firing the
- TPlot.Open method
- Known Issues:
- ------------------------------------------------------------------------------}
- procedure TPlotMenu.HandleFileClick(Sender: TObject);
- begin
- if (FPlot = nil) then exit;
-
- FPlot.OpenFile(TMenuItem(Sender).Hint);
- end;
-
- {------------------------------------------------------------------------------
- Procedure: TPlotMenu.Notification
- Description: handles changes in Plot property
- Author: Mat Ballard
- Date created: 04/25/2000
- Date modified: 04/25/2000 by Mat Ballard
- Purpose: Notifies TPlot that it is no longer loved
- Known Issues:
- ------------------------------------------------------------------------------}
- procedure TPlotMenu.Notification(AComponent: TComponent;
- Operation: TOperation);
- begin
- inherited Notification(AComponent, Operation);
- if (Operation = opRemove) and (AComponent = Plot) then
- begin
- FPlot := nil;
- end;
- end;
-
- {------------------------------------------------------------------------------
- Function: TPlotMenu.MenuExists
- Description: Does this menu exist ? Based on Tag and Caption
- Author: Mat Ballard
- Date created: 04/25/2000
- Date modified: 04/25/2000 by Mat Ballard
- Purpose: do we need to add a menu item ?
- Return Value: Boolean;
- Known Issues:
- ------------------------------------------------------------------------------}
- function TPlotMenu.MenuExists(ATag: Integer; ACaption: String): Boolean;
- var
- i,
- j: Integer;
- begin
- for i := 0 to Self.Items.Count-1 do
- begin
- {the menus:}
- if ((Self.Items[i].Tag = ATag) and
- (Self.Items[i].Caption = ACaption)) then
- begin
- MenuExists := TRUE;
- exit;
- end;
- for j := 0 to Self.Items[i].Count-1 do
- begin
- {the submenus:}
- if ((Self.Items[i].Items[j].Tag = ATag) and
- (Self.Items[i].Items[j].Caption = ACaption)) then
- begin
- MenuExists := TRUE;
- exit;
- end;
- end;
- end;
- MenuExists := FALSE;
- end;
-
- {------------------------------------------------------------------------------
- Procedure: TPlotMenu.ApplyOptions
- Description: handles changes Plot.Options property that control menu visibility
- Author: Mat Ballard
- Date created: 04/25/2000
- Date modified: 04/25/2000 by Mat Ballard
- Purpose: UI management
- Known Issues:
- ------------------------------------------------------------------------------}
- procedure TPlotMenu.ApplyOptions(Value: TPopupOptions);
- var
- i: Integer;
- begin
- for i := 0 to Ord(High(TMainMenus)) do
- Self.Items[i].Visible :=
- (TMainMenus(i) in Value.Menu);
- for i := 0 to Ord(High(TFileMenus)) do
- Self.Items[Ord(mnuFile)].Items[i].Visible :=
- (TFileMenus(i) in Value.File_);
- for i := 0 to Ord(High(TEditMenus)) do
- Self.Items[Ord(mnuEdit)].Items[i].Visible :=
- (TEditMenus(i) in Value.Edit);
- for i := 0 to Ord(High(TViewMenus)) do
- Self.Items[Ord(mnuView)].Items[i].Visible :=
- (TViewMenus(i) in Value.View);
- for i := 0 to Ord(High(TCalcMenus)) do
- Self.Items[Ord(mnuCalc)].Items[i].Visible :=
- (TCalcMenus(i) in Value.Calc);
- end;
-
-
-
- end.
-