{$I DacDemo.inc} unit DemoForm; interface uses {$IFNDEF WIN32} Types, {$ENDIF} SysUtils, Classes, DB, {$IFDEF LINUX} QControls, QStdCtrls, QComCtrls, QGraphics, QMenus, QTypes, QImgList, QForms, QButtons, QExtCtrls, Qt, QDialogs, {$ELSE} Windows, Forms, Messages, Controls, StdCtrls, Graphics, ImgList, ToolWin, ComCtrls, Dialogs, ExtCtrls, Tabs, Menus, DBCtrls, Buttons, ShellAPI, {$IFNDEF VER130} Variants, {$ENDIF} {$ENDIF} {$IFDEF CLR} System.ComponentModel, {$ENDIF} DBAccess, DAScript, DemoBase, DemoFrame, CategoryFrame {$IFDEF XPMAN}, UxTheme{$ENDIF} {$IFDEF USE_SYNEDIT}, SynMemo, SynEdit, SynEditHighlighter, SynHighlighterPas{$ENDIF} ; const MAX_HISTORY_SIZE = 6; type TDemoForm = class(TForm) StatusBar: TStatusBar; ImageList1: TImageList; PanelUnderTree: TPanel; TreeView: TTreeView; MainPanel: TPanel; Shape1: TShape; TVSplitter: TSplitter; pnTopLabel: TPanel; lbTitle: TLabel; lbAbout: TLabel; Panel2: TPanel; Panel1: TPanel; sbConnect: TSpeedButton; sbDisconnect: TSpeedButton; btCreate: TSpeedButton; btDrop: TSpeedButton; cbDebug: TCheckBox; pnSource: TPanel; pnDemo: TPanel; sbDemo: TSpeedButton; pnShowSource: TPanel; ToolBar: TToolBar; tbBrowseBack: TToolButton; tbBrowseForward: TToolButton; BackHistoryPopup: TPopupMenu; ForwardHistoryPopup: TPopupMenu; ilButtons: TImageList; ilDisabledButtons: TImageList; sbSource: TSpeedButton; sbFormText: TSpeedButton; pnOpenDemoDir: TPanel; sbOpenDemoDir: TSpeedButton; procedure FormCreate(Sender: TObject); virtual; procedure TreeViewChange(Sender: TObject; Node: TTreeNode); procedure TreeViewKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); procedure TreeViewClick(Sender: TObject); procedure TreeViewMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); procedure TVSplitterMoved(Sender: TObject); procedure TVSplitterCanResize(Sender: TObject; var NewSize: Integer; var Accept: Boolean); procedure lbAboutClick(Sender: TObject); virtual; procedure lbAboutMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); procedure lbTitleMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); procedure cbDebugClick(Sender: TObject); procedure sbOpenDemoDirClick(Sender: TObject); procedure sbConnectClick(Sender: TObject); procedure sbDisconnectClick(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure HistoryItemClick(Sender: TObject); procedure sbDemoClick(Sender: TObject); procedure FormResize(Sender: TObject); procedure BackHistoryPopupPopup(Sender: TObject); procedure ForwardHistoryPopupPopup(Sender: TObject); procedure tbBrowseBackClick(Sender: TObject); procedure tbBrowseForwardClick(Sender: TObject); procedure btScriptClick(Sender: TObject); procedure OnScriptError(Sender: TObject; E: Exception; SQL: String; var Action: TErrorAction); procedure sbSourceClick(Sender: TObject); procedure sbFormTextClick(Sender: TObject); protected Demos: TDemos; ActiveNode: TTreeNode; //History History: Array of integer; //Absolute indexes in TreeView HistoryIndex: integer; //Current History index HistoryEnd: integer; IgnoreScriptErrors: boolean; DropScriptActive: boolean; DemoSourceLoaded, FormSourceLoaded: boolean; //Product customization function GetConnection: TCustomDAConnection; virtual; abstract; //This function should return DAC product specific connection (i.e. OraSession, MyConnection) function ApplicationTitle: string; virtual; abstract; //This function should return DAC product specific title function ProductName: string; virtual; abstract; ////This function should return product name procedure RegisterDemos; virtual; abstract; //This procedure should regiter DAC product specific demos //XP manifest {$IFDEF XPMAN} procedure ReplaceFlatStyle(Control: TWinControl; Flat: boolean); {$ENDIF} //Demo selection procedure InitializeDemoFrame(Frame: TDemoFrame; DemoType: TDemoType); virtual; procedure UpdateDemo; procedure ShowDemo; procedure ShowDemoSource; procedure ShowFormSource; {$IFNDEF WIN32} procedure OnNavigate(DemoDescription: string); {$ELSE} procedure OnNavigate(Index: integer); {$ENDIF} //History procedure SelectDemo; procedure NavigateHistory(Offset: integer); procedure GetBackHistory(BackList: TStrings); procedure GetForwardHistory(ForwardList: TStrings); procedure DisableBrowse(Back, Forward: boolean); procedure FillHistoryPopup(BackHistory: boolean); //Connection procedure AfterConnect(Sender: TObject); procedure AfterDisconnect(Sender: TObject); public {$IFDEF USE_SYNEDIT} SourceBrowser: TSynMemo; {$ELSE} SourceBrowser: TMemo; {$ENDIF} function GetIsXPMan: boolean; function ProductColor: TColor; virtual; abstract; //This function should return DAC product specific color procedure ExecCreateScript; virtual; abstract; procedure ExecDropScript; virtual; abstract; end; implementation {$IFDEF CLR} {$R *.nfm} {$ENDIF} {$IFDEF WIN32} {$R *.dfm} {$ENDIF} {$IFDEF LINUX} {$R *.xfm} {$ENDIF} {$IFDEF XPMAN} {$R WindowsXP.res} {$ENDIF} procedure TDemoForm.FormCreate(Sender: TObject); begin SetLength(History, MAX_HISTORY_SIZE); HistoryIndex := -1; Demos := TDemos.Create(TreeView.Items); RegisterDemos; {$IFDEF XPMAN} if GetIsXPMan then begin ReplaceFlatStyle(Self, False); pnTopLabel.Color := ProductColor; end; {$ENDIF} {$IFDEF USE_SYNEDIT} SourceBrowser := TSynMemo.Create(pnSource); SourceBrowser.Highlighter := TSynPasSyn.Create(SourceBrowser); SourceBrowser.Options := [eoAltSetsColumnMode, eoAutoIndent, eoAutoSizeMaxScrollWidth, eoDisableScrollArrows, eoDragDropEditing, eoDropFiles, eoEnhanceEndKey, eoGroupUndo, eoHideShowScrollbars, eoKeepCaretX, eoShowScrollHint, eoSmartTabDelete, eoSmartTabs, eoTabIndent, eoTabsToSpaces]; with SourceBrowser.Gutter do begin Visible := True; AutoSize := True; DigitCount := 3; LeftOffset := 0; RightOffset := 0; ShowLineNumbers := True; Width := 1; end; {$ELSE} SourceBrowser := TMemo.Create(pnSource); SourceBrowser.ScrollBars := ssVertical; SourceBrowser.Font.Name := 'Courier New'; SourceBrowser.Font.Size := 10; {$ENDIF} with SourceBrowser do begin Parent := pnSource; Align := alClient; ReadOnly := True; end; Resize; TreeView.Items[0].Expand(True); TreeView.Items[0].Selected := True; with GetConnection do begin AfterConnect := Self.AfterConnect; AfterDisconnect := Self.AfterDisconnect; end; SelectDemo; end; procedure TDemoForm.FormDestroy(Sender: TObject); begin with GetConnection do begin AfterConnect := nil; AfterDisconnect := nil; end; SetLength(History, 0); Demos.Free; end; //TreeView routines procedure TDemoForm.TreeViewChange(Sender: TObject; Node: TTreeNode); begin if (TreeView.Selected.Data <> nil) then StatusBar.Panels[0].Text := TDemo(TreeView.Selected.Data).Hint else StatusBar.Panels[0].Text := TreeView.Selected.Text; StatusBar.Repaint; end; procedure TDemoForm.TreeViewKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); begin if Key = {$IFDEF LINUX}4100{$ELSE}13{$ENDIF} then SelectDemo; end; procedure TDemoForm.TreeViewClick(Sender: TObject); begin SelectDemo; end; //TreeView Hints procedure TDemoForm.TreeViewMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); var Node: TTreeNode; begin Node := TreeView.GetNodeAt(X, Y); if (Node <> nil) and (Node.Data <> nil) then TreeView.Hint := TDemo(Node.Data).Hint else TreeView.Hint := ''; end; //Sizing constraints procedure TDemoForm.TVSplitterMoved(Sender: TObject); begin if PanelUnderTree.ClientWidth = 0 then PanelUnderTree.ClientWidth := 150; end; procedure TDemoForm.TVSplitterCanResize(Sender: TObject; var NewSize: Integer; var Accept: Boolean); begin Accept := (NewSize >= PanelUnderTree.Constraints.MinWidth) and ((ClientWidth - MainPanel.Constraints.MinWidth - NewSize) > 0); end; function TDemoForm.GetIsXPMan: boolean; begin Result := {$IFDEF XPMAN}UseThemes; {$ELSE} False;{$ENDIF} end; {$IFDEF XPMAN} procedure TDemoForm.ReplaceFlatStyle(Control: TWinControl; Flat: boolean); var i: integer; begin for i := 0 to Control.ControlCount - 1 do if Control.Controls[i] is TSpeedButton then TSpeedButton(Control.Controls[i]).Flat := Flat else if Control.Controls[i] is TDBNavigator then TDBNavigator(Control.Controls[i]).Flat := Flat else if Control.Controls[i] is TWinControl then begin if Control.Controls[i] is TPanel then begin TPanel(Control.Controls[i]).ParentBackground := False; TPanel(Control.Controls[i]).Color := clBtnFace; end; ReplaceFlatStyle(TWinControl(Control.Controls[i]), Flat); end; end; {$ENDIF} //Demo Change procedure TDemoForm.InitializeDemoFrame(Frame: TDemoFrame; DemoType: TDemoType); begin Frame.Connection := GetConnection; Frame.SetDebug(cbDebug.Checked); Frame.Parent := pnDemo; if DemoType = dtCategory then //Attach browser event handlers TCategoryFrame(Frame).OnNavigate := OnNavigate; {$IFDEF XPMAN} if GetIsXPMan then ReplaceFlatStyle(Frame, False); {$ENDIF} Frame.Initialize; end; procedure TDemoForm.UpdateDemo; var i: integer; begin for i := 1 to StatusBar.Panels.Count - 1 do StatusBar.Panels[i].Text := ''; ActiveNode := TreeView.Selected; if (ActiveNode <> nil) then with Demos.SelectDemo(ActiveNode.AbsoluteIndex) do begin InitializeDemoFrame(Frame, DemoType); DemoSourceLoaded := False; FormSourceLoaded := False; if DemoType = dtCategory then begin pnShowSource.Visible := False; pnOpenDemoDir.Visible := False; ShowDemo; end else begin pnShowSource.Visible := True; {$IFNDEF LINUX} pnOpenDemoDir.Visible := True; {$ELSE} pnOpenDemoDir.Visible := False; {$ENDIF} if sbDemo.Down then ShowDemo else if sbSource.Down then ShowDemoSource else ShowFormSource; end; Self.Caption := ApplicationTitle + ' - ' + Name; Application.Title := ApplicationTitle; end; StatusBar.Repaint; end; procedure TDemoForm.ShowDemo; begin pnSource.Visible := False; pnDemo.Visible := True; end; procedure TDemoForm.ShowDemoSource; begin if not DemoSourceLoaded then begin Demos.SelectedDemo.LoadDemoCode(SourceBrowser.Lines); DemoSourceLoaded := True; FormSourceLoaded := False; end; pnSource.Visible := True; pnDemo.Visible := False; end; procedure TDemoForm.ShowFormSource; begin if not FormSourceLoaded then begin Demos.SelectedDemo.LoadFormCode(SourceBrowser.Lines); FormSourceLoaded := True; DemoSourceLoaded := False; end; pnSource.Visible := True; pnDemo.Visible := False; end; //User control procedure TDemoForm.sbOpenDemoDirClick(Sender: TObject); begin Demos.SelectedDemo.OpenDemoFolder; end; procedure TDemoForm.cbDebugClick(Sender: TObject); begin Demos.SelectedDemo.Frame.SetDebug(cbDebug.Checked); end; {$IFNDEF WIN32} procedure TDemoForm.OnNavigate(DemoDescription: string); var Node: TTreeNode; DemoName, CategoryName, FolderName: string; ListBox: TListBox; i: integer; begin Node := TreeView.Items.GetFirstNode; DemoName := Trim(Copy(DemoDescription, 1, pos('-', DemoDescription) - 1)); while Node <> nil do begin if TDemo(Node.Data).Name = DemoName then begin TreeView.Selected := Node; SelectDemo; break; end; Node := Node.GetNext; end; // Demo was not found in the tree. This is supplementary demo. if (Demos.SelectedDemo.DemoType = dtCategory) and (DemoName <> '') then begin ListBox := TCategoryFrame(Demos.SelectedDemo.Frame).DemosDescription; for i := ListBox.ItemIndex downto 0 do if (ListBox.Items[i] <> '') and (ListBox.Items[i][1] = ' ') then begin CategoryName := Trim(ListBox.Items[i]); Break; end; end; {$IFNDEF LINUX} FolderName := ExtractFilePath(ExtractFileDir(Application.ExeName)) + CategoryName + '\' + DemoName; ShellExecute(0, 'open', FolderName, '', '.', SW_SHOW); {$ENDIF} end; {$ELSE} procedure TDemoForm.OnNavigate(Index: integer); begin TreeView.Items[Index].Selected := True; SelectDemo; end; {$ENDIF} procedure TDemoForm.lbAboutClick(Sender: TObject); begin lbAbout.Font.Color := $FFFFFF; lbAbout.Cursor := crDefault; end; //About highlite procedure TDemoForm.lbAboutMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); begin lbAbout.Font.Color := TColor($FF00001A); //clHotLight lbAbout.Cursor := crHandPoint; end; procedure TDemoForm.lbTitleMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); begin lbAbout.Font.Color := $FFFFFF; lbAbout.Cursor := crDefault; end; procedure TDemoForm.sbConnectClick(Sender: TObject); begin GetConnection.Connect; end; procedure TDemoForm.sbDisconnectClick(Sender: TObject); begin GetConnection.Disconnect; end; procedure TDemoForm.AfterConnect(Sender: TObject); begin sbDisconnect.Enabled := True; sbConnect.Enabled := False; end; procedure TDemoForm.AfterDisconnect(Sender: TObject); begin sbDisconnect.Enabled := False; sbConnect.Enabled := True; end; //History procedure TDemoForm.SelectDemo; var i: integer; begin if TreeView.Selected = ActiveNode then //Same demo selected Exit; UpdateDemo; if HistoryIndex = (MAX_HISTORY_SIZE - 1) then for i := 0 to MAX_HISTORY_SIZE - 2 do History[i] := History[i + 1] else Inc(HistoryIndex); History[HistoryIndex] := ActiveNode.AbsoluteIndex; HistoryEnd := HistoryIndex; DisableBrowse(HistoryIndex = 0, True); end; procedure TDemoForm.NavigateHistory(Offset: integer); begin if ((HistoryIndex + Offset) < 0) or ((HistoryIndex + Offset) >= MAX_HISTORY_SIZE) then raise Exception.Create('Wrong history index'); HistoryIndex := HistoryIndex + Offset; TreeView.Items[Demos.GetDemoIndex(History[HistoryIndex])].Selected := True; DisableBrowse(HistoryIndex = 0, HistoryIndex = HistoryEnd); UpdateDemo; end; procedure TDemoForm.GetBackHistory(BackList: TStrings); var i: integer; begin BackList.Clear; for i := HistoryIndex - 1 downto 0 do BackList.Add(Demos[History[i]].Name); end; procedure TDemoForm.GetForwardHistory(ForwardList: TStrings); var i: integer; begin ForwardList.Clear; for i := HistoryIndex + 1 to HistoryEnd do ForwardList.Add(Demos[History[i]].Name); end; procedure TDemoForm.DisableBrowse(Back, Forward: boolean); begin tbBrowseBack.Enabled := not Back; tbBrowseForward.Enabled := not Forward; end; procedure TDemoForm.FillHistoryPopup(BackHistory: boolean); var NewItem: TMenuItem; List: TStrings; i: integer; HistoryPopup: TPopupMenu; begin if BackHistory then HistoryPopup := BackHistoryPopup else HistoryPopup := ForwardHistoryPopup; HistoryPopup.Items.Clear; List := TStringList.Create; if BackHistory then GetBackHistory(List) else GetForwardHistory(List); for i := 1 to List.Count do begin NewItem := TMenuItem.Create(HistoryPopup); HistoryPopup.Items.Add(NewItem); NewItem.Caption := List[i - 1]; if BackHistory then NewItem.Tag := -i else NewItem.Tag := i; NewItem.OnClick := HistoryItemClick; end; List.Free; end; procedure TDemoForm.HistoryItemClick(Sender: TObject); begin if Sender is TMenuItem then NavigateHistory(TMenuItem(Sender).Tag); end; procedure TDemoForm.BackHistoryPopupPopup(Sender: TObject); begin FillHistoryPopup(True); end; procedure TDemoForm.ForwardHistoryPopupPopup(Sender: TObject); begin FillHistoryPopup(False); end; procedure TDemoForm.tbBrowseBackClick(Sender: TObject); begin NavigateHistory(-1); end; procedure TDemoForm.tbBrowseForwardClick(Sender: TObject); begin NavigateHistory(1); end; procedure TDemoForm.sbDemoClick(Sender: TObject); begin ShowDemo; end; procedure TDemoForm.sbSourceClick(Sender: TObject); begin ShowDemoSource; end; procedure TDemoForm.sbFormTextClick(Sender: TObject); begin ShowFormSource; end; procedure TDemoForm.FormResize(Sender: TObject); begin lbAbout.Left := lbAbout.Parent.ClientWidth - 100; cbDebug.Left := cbDebug.Parent.ClientWidth - 100; pnOpenDemoDir.Left := cbDebug.Left - (pnOpenDemoDir.Width + 15); pnShowSource.Left := pnOpenDemoDir.Left - (pnShowSource.Width + 15); end; procedure TDemoForm.OnScriptError(Sender: TObject; E: Exception; SQL: String; var Action: TErrorAction); var OperationStr, ScriptFileStr, MessageStr: string; begin if DropScriptActive then begin OperationStr := 'drop'; ScriptFileStr := 'UninstallDemoObjects.sql'; end else begin OperationStr := 'create'; ScriptFileStr := 'InstallDemoObjects.sql'; end; MessageStr := Format('An error has been occured: %s' + #$d#$d'You can manually %s objects required for demo by using the ' + 'following file: %%%s%%\Demos\%s' + #$d'%%%s%% is the %s installation path on your computer.' + #13#10 + 'Ignore this exception?', [E.Message, OperationStr, ProductName, ScriptFileStr, ProductName, ProductName]); Action := eaContinue; if not IgnoreScriptErrors then case MessageDlg(MessageStr, mtError, [mbYes, mbNo{$IFNDEF LINUX}, mbYesToAll{$ENDIF}], 0) of mrNo: Action := eaAbort; {$IFNDEF LINUX} mrYesToAll: IgnoreScriptErrors := True; {$ENDIF} end; end; procedure TDemoForm.btScriptClick(Sender: TObject); var s: string; begin DropScriptActive := Sender = btDrop; if DropScriptActive then s := 'removed from database' else s := 'created in database'; if MessageDlg(Format('Objects required for the demo will be %s. Continue?', [s]), mtConfirmation, [mbYes, mbNo], 0) = mrYes then begin IgnoreScriptErrors := False; GetConnection.Connect; if Sender = btCreate then ExecCreateScript else ExecDropScript; end; end; end.