123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197 |
- unit FormDocument;
- interface
- uses
- jsonhelper, JsonDocument,
- WinSizeUtil, LineNumbersMemoFMX,
- System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
- System.Math, System.StrUtils, FMX.DialogService,
- FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.StdCtrls,
- FMX.Controls.Presentation, FMX.Layouts, FMX.TreeView, FMX.Objects, System.JSON,
- FMX.Memo.Types, FMX.ScrollBox, FMX.Memo, System.ImageList, FMX.ImgList, FMX.Text,
- FMX.ListBox, FMX.Edit, FMX.TabControl, FMX.Menus, FMX.Ani, FMX.Effects,
- FMX.Filter.Effects, System.Generics.Collections, System.Actions, FMX.ActnList,
- System.Math.Vectors, FMX.Controls3D, FMX.Layers3D, FMX.EditBox, FMX.NumberBox;
- type
- TfmDocument = class(TForm)
- pmTreeViewItem: TPopupMenu;
- miMoveDown: TMenuItem;
- imglstJSONKind: TImageList;
- miMoveUp: TMenuItem;
- pnlSizeBorder: TPanel;
- lytMiddle: TLayout;
- rctFooter: TRectangle;
- lytLeftAndRight: TLayout;
- rctLeft: TRectangle;
- rctLeftToolBar: TRectangle;
- rctBtnCollapseAll: TRectangle;
- ColorAnimation6: TColorAnimation;
- pathBtnCollapseAll: TPath;
- rctBtnExpandAll: TRectangle;
- ColorAnimation7: TColorAnimation;
- pathBtnExpandAll: TPath;
- lytLeftToolBar_right: TLayout;
- rctBtnDelete: TRectangle;
- ColorAnimation8: TColorAnimation;
- Path2: TPath;
- rctBtnAddSubItem: TRectangle;
- ColorAnimation9: TColorAnimation;
- pathBtnAddSub: TPath;
- rctBtnAddItem: TRectangle;
- ColorAnimation10: TColorAnimation;
- pathBtnAddBrother: TPath;
- rctBtnMoveDown: TRectangle;
- ColorAnimation11: TColorAnimation;
- pathBtnMoveDown: TPath;
- rctBtnMoveUp: TRectangle;
- ColorAnimation12: TColorAnimation;
- pathBtnMoveUp: TPath;
- tvJson: TTreeView;
- rctDrap: TRectangle;
- rctRight: TRectangle;
- rctRightTopBar: TRectangle;
- edtName: TEdit;
- cbValueType: TComboBox;
- rctRightMiddle: TRectangle;
- mmoEdit: TMemo;
- rctForBoolValue: TRectangle;
- rbTrue: TRadioButton;
- rbFalse: TRadioButton;
- slL_R: TSplitter;
- rctTitleBar: TRectangle;
- rctTitleBarForMove: TRectangle;
- rctBtnClose: TRectangle;
- aniForCloseBtn: TColorAnimation;
- pathCloseBtn: TPath;
- rctBtnMin: TRectangle;
- aniForMinBtn: TColorAnimation;
- pathMinBtn: TPath;
- rctBtnMax: TRectangle;
- aniForMaxBtn: TColorAnimation;
- pathMaxBtn: TPath;
- lblCaption: TLabel;
- imgLogo: TImage;
- lblFilename: TLabel;
- rctToolBar: TRectangle;
- MenuBar1: TMenuBar;
- miFile: TMenuItem;
- miFileNew: TMenuItem;
- miFileOpen: TMenuItem;
- miFileOpenRecent: TMenuItem;
- miFileSave: TMenuItem;
- miFileSaveAs: TMenuItem;
- miFileClose: TMenuItem;
- miEdit: TMenuItem;
- miEditMoveUp: TMenuItem;
- miEditMoveDown: TMenuItem;
- miView: TMenuItem;
- miViewShowLog: TMenuItem;
- miViewDarkStyle: TMenuItem;
- BitmapAnimation1: TBitmapAnimation;
- miViewFont: TMenuItem;
- miHelp: TMenuItem;
- miHelpHelp: TMenuItem;
- miHelpAbout: TMenuItem;
- txtMsg: TText;
- aniMsg: TFloatAnimation;
- miWindow: TMenuItem;
- mi1: TMenuItem;
- miWindowShowAll: TMenuItem;
- miWindowItems: TMenuItem;
- lblPath: TLabel;
- rctLinePos: TRectangle;
- lblLineAndPos: TLabel;
- ErrorLight: TCircle;
- rctIndent: TRectangle;
- lblIndent: TLabel;
- rctWordWarp: TRectangle;
- ColorAnimation13: TColorAnimation;
- miViewLang: TMenuItem;
- pathWordWrap: TPath;
- procedure tvJsonChange(Sender: TObject);
- procedure mmoEditChangeTracking(Sender: TObject);
- procedure FormCreate(Sender: TObject);
- procedure cbValueTypeChange(Sender: TObject);
- procedure FormResize(Sender: TObject);
- procedure slL_RMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Single);
- procedure rctBtnCloseClick(Sender: TObject);
- procedure rctBtnMaxClick(Sender: TObject);
- procedure rctBtnMinClick(Sender: TObject);
- procedure mmoEditViewportPositionChange(Sender: TObject; const OldViewportPosition, NewViewportPosition: TPointF; const ContentSizeChanged: Boolean);
- procedure edtNameChangeTracking(Sender: TObject);
- procedure rctBtnCollapseAllMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Single);
- procedure rctBtnExpandAllMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Single);
- procedure rctIndentClick(Sender: TObject);
- procedure rctWordWarpClick(Sender: TObject);
- procedure rctBtnMoveUpMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Single);
- procedure rctBtnMoveDownMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Single);
- procedure tvJsonDragChange(SourceItem, DestItem: TTreeViewItem; var Allow: Boolean);
- procedure tvJsonDragOver(Sender: TObject; const Data: TDragObject; const Point: TPointF; var Operation: TDragOperation);
- procedure tvJsonMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Single);
- procedure rctBtnDeleteClick(Sender: TObject);
- procedure pmTreeViewItemPopup(Sender: TObject);
- procedure tvJsonMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Single);
- procedure JsonFileDragOver(Sender: TObject; const Data: TDragObject; const Point: TPointF; var Operation: TDragOperation);
- procedure JsonFileDragDrop(Sender: TObject; const Data: TDragObject; const Point: TPointF);
- procedure rbTrueFalseChange(Sender: TObject);
- procedure FormClose(Sender: TObject; var Action: TCloseAction);
- procedure FormDestroy(Sender: TObject);
- procedure rctBtnAddItemMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Single);
- procedure rctBtnAddSubItemMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Single);
- procedure miFileOpenRecentApplyStyleLookup(Sender: TObject);
- procedure FormActivate(Sender: TObject);
- procedure miWindowShowAllApplyStyleLookup(Sender: TObject);
- procedure ErrorLightClick(Sender: TObject);
- private
- FDoc: TJsonDocument;
- FIsUpdating: Boolean;
- FLinesMemoUtil: TLinesMemoUtil;
- FIndent: Integer;
- FCurrentJSONKind: TJSONKind;
- FRightPanelWidthPercent: Single; // 右侧宽度占整个窗口的比例
- procedure SetIndent(AValue: Integer);
- function GetWordWarp: Boolean;
- procedure SetWordWarp(AValue: Boolean);
- property Indent: Integer read FIndent write SetIndent;
- property WordWarp: Boolean read GetWordWarp write SetWordWarp;
- public
- property Doc: TJsonDocument read FDoc;
- private
- procedure InitUI;
- procedure miFileOepnedClick(Sender: TObject);
- procedure miRecentFilesClick(Sender: TObject);
- procedure FilenameChanged(ASender: TObject);
- procedure SetErrInfo(const AMsg: string);
- public
- procedure SetLang;
- procedure NewFile;
- procedure OpenFile(const AFilename: string);
- procedure SetStyleBook;
- procedure InitOpenedFileMenu;
- procedure InitRecentFile;
- procedure ShowInfo(AText: string; ALevel: Integer = 0; ADelay: Single = 3.0);
- end;
- var
- fmDocument: TfmDocument;
- implementation
- {$R *.fmx}
- uses JSONTreeView, memo_json_auto, data_const, pub, Logger, fmFontDialog,
- rjson, FormMain;
- procedure TfmDocument.FilenameChanged(ASender: TObject);
- var
- strTmp: string;
- begin
- if FDoc.FileName = '' then
- begin
- strTmp := c_untitled_filename;
- for var i := 1 to 9999 do
- begin
- if g_pub.DocumentWindowList.GetWindowByFilename(strTmp) = nil then
- Break;
- strTmp := c_untitled_filename + ' (' + i.ToString + ')';
- end;
- lblFilename.Text := strTmp
- end
- else
- begin
- lblFilename.Text := FDoc.FileName;
- {$IFDEF MACOS}
- fmMain.InitMacOsRecentFile;
- {$ENDIF}
- end;
- {$IFDEF MACOS}
- Caption := app_name + ' ' + app_version + ' [' + lblFilename.Text + ']';
- {$ENDIF}
- end;
- procedure TfmDocument.SetErrInfo(const AMsg: string);
- begin
- ErrorLight.TagString := AMsg;
- ErrorLight.Fill.Color := IfThen(AMsg.IsEmpty, $FF00FF00, $FFFF0000);
- end;
- procedure TfmDocument.FormCreate(Sender: TObject);
- var
- LDisplay: TDisplay;
- begin
- FDoc := TJsonDocument.Create;
- FDoc.OnFilenameChanged := FilenameChanged;
- if g_pub.DocumentWindowList.LastActive <> nil then
- begin
- Position := TFormPosition.Designed;
- Left := g_pub.DocumentWindowList.LastActive.Left + 28;
- Top := g_pub.DocumentWindowList.LastActive.Top + 28;
- Width := g_pub.DocumentWindowList.LastActive.Width;
- Height := g_pub.DocumentWindowList.LastActive.Height;
- LDisplay := Screen.DisplayFromForm(g_pub.DocumentWindowList.LastActive);
- if (Left > LDisplay.BoundsRect.Right - 320) or (Top > LDisplay.BoundsRect.Bottom - 240) then
- begin
- Left := 0;
- Top := 0;
- end;
- end;
- g_pub.DocumentWindowList.Add(self);
- FIsUpdating := False;
- TMemoJsonAuto.Create(self, mmoEdit);
- FLinesMemoUtil := TLinesMemoUtil.Create(self, mmoEdit);
- InitUI;
- end;
- procedure TfmDocument.FormDestroy(Sender: TObject);
- begin
- FDoc.Free;
- end;
- procedure TfmDocument.FormResize(Sender: TObject);
- begin
- rctRight.Width := IfThen((Width - 10) * FRightPanelWidthPercent > slL_R.MinSize,
- IfThen((Width - 10) * (1.0 - FRightPanelWidthPercent) >= slL_R.MinSize, (Width - 10) * FRightPanelWidthPercent, (Width - 10) - slL_R.MinSize),
- slL_R.MinSize);
- {$IFDEF MSWINDOWS}
- pathMaxBtn.Data.Data := IfThen(WindowState = TWindowState.wsMaximized, c_ResPathData, c_MaxPathData);
- {$ENDIF}
- end;
- procedure TfmDocument.InitUI;
- begin
- {$IFDEF MACOS}
- rctTitleBar.Visible := False;
- pnlSizeBorder.StyleLookup := 'panelstyle_macos_frame';
- mmoEdit.TextSettings.Font.Family := 'SimSong'; // [BIZ UDGothic] [BIZ UDMincho] [PCMyungjo] [SimSong]
- rctToolBar.Visible := False;
- rctToolBar.Free;
- lytMiddle.Margins.Left := 2;
- lytMiddle.Margins.Right := 2;
- lytMiddle.Margins.Top := 2;
- {$ELSE}
- Transparency := True;
- with TWinSizeHelper.Create(self) do
- begin
- SetControlled(pnlSizeBorder);
- SetTitleBar(rctTitleBarForMove);
- CanMaximized := True;
- end;
- for var item in g_pub.Languages do
- begin
- var
- mi := TMenuItem.Create(miViewLang);
- mi.Text := item['caption'].ToStr('None');
- mi.RadioItem := True;
- mi.GroupIndex := 10;
- mi.OnClick := fmMain.actViewLangExecute;
- miViewLang.AddObject(mi);
- end;
- {$ENDIF}
- SetLang;
- Caption := app_name + ' ' + app_version;
- lblCaption.Text := Caption;
- rctDrap.Visible := False;
- OnResize := nil;
- Indent := g_pub.Config['editor.indent'].ToInt(4);
- WordWarp := g_pub.Config['editor.wordWarp'];
- SetStyleBook;
- FRightPanelWidthPercent := 0.5;
- rctRight.Width := (Width - 10) * FRightPanelWidthPercent;
- OnResize := FormResize;
- end;
- procedure TfmDocument.SetStyleBook;
- const
- c_PathColors: array [Boolean] of TAlphaColor = ({false:}$FF000000, {true:}$FFFFFFFF);
- begin
- tvJson.ScrollBy(tvJson.ViewportPosition.X, tvJson.ViewportPosition.Y); // 否则切换时会偶发异常
- StyleBook := g_pub.StyleBook;
- fmMain.actViewDarkStyle.Checked := g_pub.IsDarkStyle;
- tvJson.ShowScrollBars := True;
- for var item in [pathMaxBtn.Fill, pathMinBtn.Fill, pathCloseBtn.Fill] do
- item.Color := c_PathColors[fmMain.actViewDarkStyle.Checked];
- mmoEdit.TextSettings.FontColor := c_PathColors[fmMain.actViewDarkStyle.Checked];
- end;
- procedure TfmDocument.SetLang;
- begin
- {$IFDEF MSWINDOWS}
- miViewLang.Items[g_pub.LangIndex].IsChecked := True;
- {$ENDIF}
- rctIndent.Hint := g_pub.LangStr('strIndent');
- rctWordWarp.Hint := g_pub.LangStr('strWordWarp');
- end;
- procedure TfmDocument.NewFile;
- begin
- FDoc.New;
- FIsUpdating := True;
- try
- tvJson.Clear;
- SetTreeItem(tvJson, FDoc.JsonRoot);
- tvJson.ExpandAll;
- tvJson.Items[0].Select;
- mmoEdit.SetFocus;
- mmoEdit.Text := '{' + sLineBreak + StringOfChar(' ', Indent) + sLineBreak + '}';
- mmoEdit.CaretPosition := TCaretPosition.Create(1, Indent);
- cbValueType.ItemIndex := 0;
- finally
- FIsUpdating := False;
- end;
- end;
- procedure TfmDocument.OpenFile(const AFilename: string);
- begin
- if FDoc.Open(AFilename, True, False) then
- begin
- FIsUpdating := True;
- try
- tvJson.Clear;
- tvJson.BeginUpdate;
- SetTreeItem(tvJson, FDoc.JsonRoot);
- tvJson.EndUpdate;
- tvJson.ExpandAll;
- mmoEdit.Text := '';
- ShowInfo('Open: ' + AFilename);
- finally
- FIsUpdating := False;
- end;
- if tvJson.Count > 0 then
- begin
- tvJson.Items[0].Select;
- end;
- end
- else
- begin
- ShowMessage('An error occurred while opening the file.!');
- end;
- end;
- procedure TfmDocument.tvJsonChange(Sender: TObject);
- var
- selItem: TJSONTreeViewItem;
- LJsonKind: TJSONKind;
- begin
- if FIsUpdating then
- Exit;
- FIsUpdating := True;
- try
- SetErrInfo('');
- selItem := TJSONTreeViewItem(tvJson.Selected);
- if selItem = nil then
- begin
- mmoEdit.Text := '';
- Exit;
- end;
- edtName.Text := selItem.LastPath;
- mmoEdit.Text := selItem.Value;
- lblPath.Text := selItem.Path;
- edtName.Enabled := not selItem.Key.IsEmpty;
- LJsonKind := selItem.JsonValue.JsonKind;
- cbValueType.ItemIndex := ord(LJsonKind) - 1;
- if LJsonKind in [jkObject, jkArray] then
- begin
- mmoEdit.Text := selItem.JsonValue.Format(Indent);
- end
- else
- begin
- mmoEdit.Text := selItem.Value;
- if LJsonKind = jkBoolean then
- begin
- rbTrue.IsChecked := selItem.JsonValue.AsType<Boolean>;
- rbFalse.IsChecked := not rbTrue.IsChecked;
- end;
- end;
- finally
- FIsUpdating := False;
- end;
- end;
- procedure TfmDocument.tvJsonDragChange(SourceItem, DestItem: TTreeViewItem; var Allow: Boolean);
- var
- Pos: TPointF;
- Source, Dest: TJSONTreeViewItem;
- begin
- Allow := False;
- rctDrap.Visible := False;
- if DestItem = nil then
- Exit;
- Dest := TJSONTreeViewItem(DestItem);
- Source := TJSONTreeViewItem(SourceItem);
- if Source.IsChild(Dest) then
- begin
- {$IFDEF DEBUG}
- g_Logger.Debug('父条目不能插入子条目!');
- {$ENDIF}
- Exit;
- end;
- Pos := Dest.ScreenToLocal(Screen.MousePos);
- if Pos.Y < Dest.LocalRect.Height / 4 then
- begin
- if ((Dest.ParentItem = Source.ParentItem) and (Dest.Index - Source.Index = 1)) or (Dest.ParentItem = nil) then
- begin
- {$IFDEF DEBUG}
- g_Logger.Debug('Do nothing');
- {$ENDIF}
- end
- else
- begin
- {$IFDEF DEBUG}
- g_Logger.Debug('前边插入');
- {$ENDIF}
- TJSONTreeViewItem(Source).ExtractFromParent(True);
- TJSONTreeViewItem(Dest.ParentItem).InsertItem(Dest.Index, Source, True);
- Source.Select;
- end;
- end
- else if Pos.Y > Dest.LocalRect.Height / 4 * 3 then
- begin
- if ((Dest.ParentItem = Source.ParentItem) and (Source.Index - Dest.Index = 1)) or (Dest.ParentItem = nil) then
- begin
- {$IFDEF DEBUG}
- g_Logger.Debug('Do nothing');
- {$ENDIF}
- end
- else
- begin
- {$IFDEF DEBUG}
- g_Logger.Debug('后边插入');
- {$ENDIF}
- TJSONTreeViewItem(Source).ExtractFromParent(True);
- TJSONTreeViewItem(Dest.ParentItem).InsertItem(Dest.Index + 1, Source, True);
- Source.Select;
- end;
- end
- else
- begin
- if not Dest.JsonValue.IsObjectOrArray then
- begin
- {$IFDEF DEBUG}
- g_Logger.Debug('Do nothing');
- {$ENDIF}
- end
- else
- begin
- {$IFDEF DEBUG}
- g_Logger.Debug('插入子项');
- {$ENDIF}
- TJSONTreeViewItem(Source).ExtractFromParent(True);
- Dest.AddItem(Source, True);
- Source.Select;
- end;
- end;
- end;
- procedure TfmDocument.tvJsonDragOver(Sender: TObject; const Data: TDragObject; const Point: TPointF; var Operation: TDragOperation);
- var
- Pos: TPointF;
- Source, Dest: TJSONTreeViewItem;
- LRect: TRectF;
- LPoint: TPointF;
- begin
- Operation := TDragOperation.None;
- Dest := TJSONTreeViewItem(tvJson.ItemByPoint(Point.X, Point.Y));
- if Dest = nil then
- Exit;
- Source := TJSONTreeViewItem(Data.Source);
- if Source.IsChild(Dest) then
- Exit;
- LRect := Dest.BoundsRect;
- Pos := Dest.ScreenToLocal(Screen.MousePos);
- LPoint := tvJson.ScreenToLocal(Dest.LocalToScreen(PointF(0, 0)));
- if Pos.Y < Dest.LocalRect.Height / 4 then
- begin
- if ((Dest.ParentItem = Source.ParentItem) and (Dest.Index - Source.Index = 1)) or (Dest.ParentItem = nil) then
- begin
- rctDrap.Visible := False;
- end
- else
- begin
- rctDrap.Height := Dest.Height / 2;
- rctDrap.Position.Y := LPoint.Y - rctDrap.Height / 2 + tvJson.ViewportPosition.Y;
- rctDrap.Position.X := LPoint.X + tvJson.ViewportPosition.X;
- rctDrap.Width := tvJson.ClipRect.Width - 10 - rctDrap.Position.X + tvJson.ViewportPosition.X;
- rctDrap.Visible := True;
- end;
- end
- else if Pos.Y > Dest.LocalRect.Height / 4 * 3 then
- begin
- if ((Dest.ParentItem = Source.ParentItem) and (Source.Index - Dest.Index = 1)) or (Dest.ParentItem = nil) then
- begin
- rctDrap.Visible := False;
- end
- else
- begin
- rctDrap.Height := Dest.Height / 2;
- rctDrap.Position.Y := LPoint.Y - rctDrap.Height / 2 + Dest.Height + tvJson.ViewportPosition.Y;
- rctDrap.Position.X := LPoint.X + tvJson.ViewportPosition.X;
- rctDrap.Width := tvJson.ClipRect.Width - 10 - rctDrap.Position.X + tvJson.ViewportPosition.X;
- rctDrap.Visible := True;
- end;
- end
- else
- begin
- if not Dest.JsonValue.IsObjectOrArray then
- begin
- rctDrap.Visible := False;
- end
- else
- begin
- rctDrap.Height := Dest.Height / 4 * 3;
- rctDrap.Position.Y := LPoint.Y + (Dest.Height - rctDrap.Height) / 2 + tvJson.ViewportPosition.Y;
- rctDrap.Position.X := LPoint.X + tvJson.ViewportPosition.X;
- rctDrap.Width := tvJson.ClipRect.Width - 10 - rctDrap.Position.X + tvJson.ViewportPosition.X;
- rctDrap.Visible := True;
- end;
- end;
- end;
- procedure TfmDocument.tvJsonMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Single);
- var
- LItem: TTreeViewItem;
- begin
- if ssRight in Shift then
- begin
- LItem := tvJson.ItemByPoint(X, Y);
- if LItem <> nil then
- begin
- LItem.Select;
- pmTreeViewItem.Popup(Screen.MousePos.X, Screen.MousePos.Y);
- end;
- end;
- end;
- procedure TfmDocument.tvJsonMouseMove(Sender: TObject; Shift: TShiftState; X,
- Y: Single);
- begin
- if not(ssLeft in Shift) then
- rctDrap.Visible := False;
- end;
- {-------------------------------------------------------------------------------
- 名称: TfmDocument.actHelpAboutExecute
- 说明: 关于
- 参数: Sender
- -------------------------------------------------------------------------------}
- procedure TfmDocument.cbValueTypeChange(Sender: TObject);
- var
- LJValue:
- TJsonValue;
- treeItem:
- TJSONTreeViewItem;
- bValue:
- Boolean;
- begin
- FCurrentJSONKind := TJSONKind(cbValueType.ItemIndex + 1);
- rctForBoolValue.Visible := FCurrentJSONKind = jkBoolean;
- mmoEdit.Visible := FCurrentJSONKind <> jkBoolean;
- mmoEdit.Enabled := FCurrentJSONKind in [jkObject, jkArray, jkString, jkNumber];
- treeItem := TJSONTreeViewItem(tvJson.Selected);
- if FIsUpdating or (treeItem = nil) then
- Exit;
- LJValue := nil;
- FIsUpdating := True;
- try
- try
- case FCurrentJSONKind of
- jkObject:
- begin
- LJValue := TJsonValue.ParseJSONValue(mmoEdit.Text, True, False);
- if not(LJValue is TJSONObject) then
- begin
- FreeAndNil(LJValue);
- mmoEdit.Text := '{' + sLineBreak + StringOfChar(' ', Indent) + sLineBreak + '}';
- mmoEdit.CaretPosition := TCaretPosition.Create(1, Indent);
- mmoEdit.SetFocus;
- LJValue := TJSONObject.Create;
- end;
- end;
- jkArray:
- begin
- LJValue := TJsonValue.ParseJSONValue(mmoEdit.Text, True, False);
- if not(LJValue is TJSONArray) then
- begin
- FreeAndNil(LJValue);
- LJValue := TJSONArray.Create;
- mmoEdit.Text := '[' + sLineBreak + StringOfChar(' ', Indent) + sLineBreak + ']';
- mmoEdit.CaretPosition := TCaretPosition.Create(1, Indent);
- mmoEdit.SetFocus;
- end;
- end;
- jkString:
- begin
- LJValue := TJSONString.Create(mmoEdit.Text);
- mmoEdit.GoToTextEnd;
- mmoEdit.SetFocus;
- end;
- jkNumber:
- begin
- LJValue := TJsonValue.ParseJSONValue(mmoEdit.Text.Trim, True, False);
- if not(LJValue is TJSONNumber) then
- begin
- FreeAndNil(LJValue);
- LJValue := TJSONNumber.Create(0);
- end;
- mmoEdit.Text := LJValue.Value;
- mmoEdit.GoToTextEnd;
- mmoEdit.SetFocus;
- end;
- jkBoolean:
- begin
- bValue := StrToBoolDef(mmoEdit.Text.Trim, False);
- LJValue := TJSONBool.Create(bValue);
- mmoEdit.Text := LJValue.Value;
- if bValue then
- begin
- rbTrue.IsChecked := True;
- end
- else
- begin
- rbFalse.IsChecked := True;
- end;
- end;
- jkNull:
- begin
- LJValue := TJSONNull.Create;
- mmoEdit.Text := LJValue.Value;
- end;
- end;
- except
- on E: Exception do
- SetErrInfo(E.Message);
- end;
- treeItem.ClearItem;
- treeItem.JsonValue := LJValue;
- treeItem.ReText;
- SetTreeItems(treeItem, LJValue);
- if treeItem.ParentItem = nil then
- begin
- FDoc.JsonRoot := LJValue;
- end;
- finally
- FIsUpdating := False;
- end;
- end;
- procedure TfmDocument.edtNameChangeTracking(Sender: TObject);
- var
- treeItem: TJSONTreeViewItem;
- begin
- if FIsUpdating or Trim(edtName.Text).IsEmpty then
- Exit;
- FIsUpdating := True;
- try
- treeItem := TJSONTreeViewItem(tvJson.Selected);
- if treeItem <> nil then
- begin
- TJSONPair(treeItem.JsonData).Rename(Trim(edtName.Text));
- treeItem.Text := Trim(edtName.Text) + ': ' + treeItem.Value;
- end;
- finally
- FIsUpdating := False;
- end;
- end;
- procedure TfmDocument.ErrorLightClick(Sender: TObject);
- begin
- if not ErrorLight.TagString.IsEmpty then
- ShowInfo(ErrorLight.TagString, 1, 5);
- end;
- procedure TfmDocument.FormActivate(Sender: TObject);
- var
- LIndex: Integer;
- begin
- LIndex := g_pub.DocumentWindowList.IndexOf(self);
- if LIndex > 0 then
- begin
- g_pub.DocumentWindowList.Move(LIndex, 0);
- {$IFDEF DEBUG}
- g_Logger.Debug('窗口激活,移动到列表首位!');
- {$ENDIF}
- end;
- end;
- procedure TfmDocument.FormClose(Sender: TObject; var Action: TCloseAction);
- begin
- g_pub.Config['editor.indent'] := Indent;
- g_pub.Config['editor.wordWarp'] := mmoEdit.TextSettings.WordWrap;
- g_pub.DocumentWindowList.Remove(self);
- Action := TCloseAction.caFree;
- end;
- procedure TfmDocument.mmoEditChangeTracking(Sender: TObject);
- var
- LJValue: TJsonValue;
- treeItem: TJSONTreeViewItem;
- begin
- treeItem := TJSONTreeViewItem(tvJson.Selected);
- if FIsUpdating or (treeItem = nil) then
- Exit;
- LJValue := nil;
- SetErrInfo('');
- FIsUpdating := True;
- try
- try
- if FCurrentJSONKind = jkString then
- begin
- LJValue := TJSONString.Create(mmoEdit.Text);
- end
- else
- begin
- LJValue := TJsonValue.ParseJSONValue(mmoEdit.Text, True, True);
- if LJValue.JsonKind <> FCurrentJSONKind then
- begin
- FreeAndNil(LJValue);
- end;
- end;
- except
- on E: Exception do
- SetErrInfo(E.Message);
- end;
- if LJValue <> nil then
- begin
- if treeItem.JsonValue.ToString = LJValue.ToString then
- begin
- FreeAndNil(LJValue);
- end
- else
- begin
- treeItem.BeginUpdate;
- treeItem.ClearItem;
- treeItem.JsonValue := LJValue;
- if treeItem.ParentItem = nil then
- begin
- FDoc.JsonRoot := LJValue;
- end;
- treeItem.ReText;
- SetTreeItems(treeItem, LJValue);
- treeItem.EndUpdate;
- end;
- end;
- finally
- FIsUpdating := False;
- end;
- end;
- procedure TfmDocument.mmoEditViewportPositionChange(Sender: TObject; const OldViewportPosition, NewViewportPosition: TPointF; const ContentSizeChanged: Boolean);
- begin
- lblLineAndPos.Text := (mmoEdit.CaretPosition.Line + 1).ToString + ': ' + (mmoEdit.CaretPosition.Pos + 1).ToString;
- end;
- procedure TfmDocument.pmTreeViewItemPopup(Sender: TObject);
- var
- selItem: TJSONTreeViewItem;
- begin
- selItem := TJSONTreeViewItem(tvJson.Selected);
- if selItem = nil then
- begin
- for var i := 0 to pmTreeViewItem.ItemsCount - 1 do
- pmTreeViewItem.Items[i].Enabled := False;
- Exit;
- end;
- fmMain.actEditMoveUp.Enabled := selItem.Index <> 0;
- fmMain.actEditMoveDown.Enabled := (selItem.ParentItem <> nil) and (selItem.Index < selItem.ParentItem.Count - 1);
- end;
- procedure TfmDocument.rbTrueFalseChange(Sender: TObject);
- var
- treeItem: TJSONTreeViewItem;
- begin
- treeItem := TJSONTreeViewItem(tvJson.Selected);
- if FIsUpdating or (treeItem = nil) then
- Exit;
- mmoEdit.Text := rbTrue.IsChecked.ToString(TUseBoolStrs.True).ToLower;
- end;
- procedure TfmDocument.rctBtnAddItemMouseDown(Sender: TObject;
- Button: TMouseButton; Shift: TShiftState; X, Y: Single);
- var
- newItem, selItem, parItem: TJSONTreeViewItem;
- LIndex: Integer;
- begin
- if tvJson.Selected = nil then
- Exit;
- if tvJson.Selected.ParentItem = nil then
- Exit;
- selItem := TJSONTreeViewItem(tvJson.Selected);
- parItem := selItem.MyParentItem;
- LIndex := selItem.Index;
- newItem := TJSONTreeViewItem.Create(nil);
- if parItem.JsonValue is TJSONObject then
- begin
- newItem.JsonData := TJSONPair.Create('newItem', 'new value');
- end
- else
- begin
- newItem.JsonData := TJSONString.Create('newItem');
- end;
- parItem.InsertItem(LIndex + 1, newItem, True);
- newItem.Select;
- end;
- procedure TfmDocument.rctBtnAddSubItemMouseDown(Sender: TObject;
- Button: TMouseButton; Shift: TShiftState; X, Y: Single);
- var
- newItem, selItem: TJSONTreeViewItem;
- begin
- if tvJson.Selected = nil then
- Exit;
- selItem := TJSONTreeViewItem(tvJson.Selected);
- if not selItem.JsonValue.IsObjectOrArray then
- Exit;
- newItem := TJSONTreeViewItem.Create(nil);
- if selItem.JsonValue is TJSONObject then
- begin
- newItem.JsonData := TJSONPair.Create('newItem', 'new value');
- end
- else
- begin
- newItem.JsonData := TJSONString.Create('newItem');
- end;
- selItem.AddItem(newItem, True);
- newItem.Select;
- end;
- procedure TfmDocument.rctBtnCloseClick(Sender: TObject);
- begin
- Close;
- end;
- procedure TfmDocument.rctBtnCollapseAllMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Single);
- begin
- if tvJson.Selected <> nil then
- tvJson.Selected.CollapseAll
- else
- tvJson.CollapseAll;
- end;
- procedure TfmDocument.rctBtnDeleteClick(Sender: TObject);
- var
- selItem: TJSONTreeViewItem;
- parItem: TJSONTreeViewItem;
- LIndex: Integer;
- begin
- if tvJson.Selected = nil then
- Exit;
- if tvJson.Selected.ParentItem = nil then
- Exit;
- TDialogService.MessageDialog('Confirm deletion of this item?', TMsgDlgType.mtConfirmation, [TMsgDlgBtn.mbYes, TMsgDlgBtn.mbNo], TMsgDlgBtn.mbNo, 0,
- procedure(const AResult: TModalResult)
- begin
- if AResult = mrYes then
- begin
- selItem := TJSONTreeViewItem(tvJson.Selected);
- LIndex := selItem.Index;
- parItem := selItem.ExtractFromParent(True);
- selItem.JsonData.Free;
- selItem.Free;
- if LIndex < parItem.Count then
- parItem.Items[LIndex].Select
- else if parItem.Count > 0 then
- parItem.Items[parItem.Count - 1].Select
- else
- parItem.Select;
- end;
- end);
- end;
- procedure TfmDocument.rctBtnExpandAllMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Single);
- begin
- if tvJson.Selected <> nil then
- begin
- if tvJson.Selected.ParentItem <> nil then
- begin
- tvJson.Selected.ExpandAll;
- end
- else
- begin
- tvJson.ExpandAll;
- end;
- end
- else
- begin
- tvJson.ExpandAll;
- end;
- end;
- procedure TfmDocument.rctBtnMaxClick(Sender: TObject);
- begin
- {$IFDEF MSWINDOWS}
- if WindowState = TWindowState.wsMaximized then
- begin
- WindowState := TWindowState.wsNormal;
- end
- else
- begin
- WindowState := TWindowState.wsMaximized;
- end;
- {$ENDIF}
- end;
- procedure TfmDocument.rctBtnMinClick(Sender: TObject);
- begin
- fmMain.OnActivate := nil;
- try
- Hide;
- if g_pub.DocumentWindowList.NumOfVisible <= 0 then
- begin
- fmMain.WindowState := TWindowState.wsMinimized;
- fmMain.Deactivate;
- end;
- finally
- fmMain.OnActivate := fmMain.FormActivate;
- end;
- end;
- procedure TfmDocument.rctBtnMoveDownMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Single);
- begin
- fmMain.actEditMoveDownExecute(Sender);
- end;
- procedure TfmDocument.rctBtnMoveUpMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Single);
- begin
- fmMain.actEditMoveUpExecute(Sender);
- end;
- procedure TfmDocument.miFileOpenRecentApplyStyleLookup(Sender: TObject);
- begin
- {$IFDEF MSWINDOWS}
- if TThread.GetTickCount - miFileOpenRecent.Tag > 2000 then // 防止多次触发
- begin
- InitRecentFile;
- miFileOpenRecent.Tag := TThread.GetTickCount;
- end;
- {$ENDIF}
- end;
- procedure TfmDocument.miFileOepnedClick(Sender: TObject);
- begin
- if TMenuItem(Sender).TagObject <> nil then
- begin
- TfmDocument(TMenuItem(Sender).TagObject).Show;
- //TfmDocument(TMenuItem(Sender).TagObject).Activate;
- //TfmDocument(TMenuItem(Sender).TagObject).BringToFront;
- end;
- end;
- procedure TfmDocument.miRecentFilesClick(Sender: TObject);
- var
- LFilename: string;
- LDocWin: TDocumentWindow;
- begin
- if TMenuItem(Sender).Tag = -100 then
- begin
- g_pub.Config['recent'] := nil;
- end
- else
- begin
- LFilename := TMenuItem(Sender).Text;
- LDocWin := g_pub.DocumentWindowList.GetWindowByFilename(LFilename);
- if LDocWin <> nil then
- LDocWin.Show
- else
- OpenFile(LFilename);
- end;
- end;
- procedure TfmDocument.miWindowShowAllApplyStyleLookup(Sender: TObject);
- begin
- {$IFDEF MSWINDOWS}
- if TThread.GetTickCount - miWindowItems.Tag > 2000 then // 防止多次触发
- begin
- InitOpenedFileMenu;
- miWindowItems.Tag := TThread.GetTickCount;
- end;
- {$ENDIF}
- end;
- procedure TfmDocument.rctIndentClick(Sender: TObject);
- begin
- FIsUpdating := True;
- try
- case Indent of
- 0:
- Indent := 2;
- 2:
- Indent := 4;
- 4:
- Indent := 0;
- end;
- //Indent := IfThen(Indent = 2, 4, 2);
- finally
- FIsUpdating := False;
- end;
- end;
- procedure TfmDocument.JsonFileDragDrop(Sender: TObject;
- const
- Data:
- TDragObject;
- const
- Point:
- TPointF);
- begin
- if Length(Data.Files) = 1 then
- begin
- OpenFile(Data.Files[0]);
- end;
- end;
- procedure TfmDocument.JsonFileDragOver(Sender: TObject;
- const
- Data:
- TDragObject;
- const
- Point:
- TPointF;
- var
- Operation: TDragOperation);
- begin
- if Length(Data.Files) = 1 then
- Operation := TDragOperation.Link;
- end;
- procedure TfmDocument.rctWordWarpClick(Sender: TObject);
- begin
- WordWarp := not WordWarp;
- end;
- procedure TfmDocument.slL_RMouseUp(Sender: TObject;
- Button: TMouseButton;
- Shift: TShiftState;
- X, Y: Single);
- begin
- FRightPanelWidthPercent := rctRight.Width / (pnlSizeBorder.Width - 10);
- end;
- procedure TfmDocument.SetIndent(AValue: Integer);
- begin
- if FIndent = AValue then
- Exit;
- FIndent := AValue;
- lblIndent.Text := AValue.ToString;
- if tvJson.Selected <> nil then
- begin
- if TJSONTreeViewItem(tvJson.Selected).JsonValue.IsObjectOrArray then
- begin
- if FIndent > 0 then
- begin
- mmoEdit.Text := TJSONTreeViewItem(tvJson.Selected).JsonValue.Format(FIndent);
- end
- else
- begin
- mmoEdit.Text := TJSONTreeViewItem(tvJson.Selected).JsonValue.ToString;
- end;
- end;
- end;
- end;
- function TfmDocument.GetWordWarp: Boolean;
- begin
- Result := mmoEdit.TextSettings.WordWrap;
- end;
- procedure TfmDocument.SetWordWarp(AValue: Boolean);
- begin
- if mmoEdit.TextSettings.WordWrap = AValue then
- Exit;
- FIsUpdating := True;
- try
- mmoEdit.TextSettings.WordWrap := AValue;
- pathWordWrap.Fill.Color := IfThen(mmoEdit.TextSettings.WordWrap, $FF00FF00, $FF808080);
- finally
- FIsUpdating := False;
- end;
- end;
- procedure TfmDocument.InitOpenedFileMenu;
- var
- miTmp: TMenuItem;
- begin
- miWindowItems.Clear;
- for var item in g_pub.DocumentWindowList do
- begin
- miTmp := TMenuItem.Create(miWindowItems);
- miTmp.TagObject := item;
- miTmp.Text := item.lblFilename.Text;
- miTmp.OnClick := miFileOepnedClick;
- miWindowItems.AddObject(miTmp);
- miTmp.Enabled := self <> item;
- end;
- end;
- procedure TfmDocument.InitRecentFile;
- var
- miTmp: TMenuItem;
- begin
- miFileOpenRecent.Clear;
- for var item in g_pub.Config['recent'] do
- begin
- miTmp := TMenuItem.Create(miFileOpenRecent);
- miTmp.Text := item;
- miTmp.OnClick := miRecentFilesClick;
- miFileOpenRecent.AddObject(miTmp);
- miTmp.Enabled := (miTmp.Text <> FDoc.FileName) and FileExists(miTmp.Text);
- end;
- if miFileOpenRecent.ItemsCount > 0 then
- begin
- miTmp := TMenuItem.Create(miFileOpenRecent);
- miTmp.Text := '-';
- miFileOpenRecent.AddObject(miTmp);
- miTmp := TMenuItem.Create(miFileOpenRecent);
- //miTmp.Text := 'Clear';
- //miTmp.Tag := -100;
- miTmp.Action := fmMain.actFileClearRecent;
- //miTmp.OnClick := miRecentFilesClick;
- miFileOpenRecent.AddObject(miTmp);
- end
- else
- begin
- miTmp := TMenuItem.Create(miFileOpenRecent);
- miTmp.Text := 'No file!';
- miTmp.Enabled := False;
- miFileOpenRecent.AddObject(miTmp);
- end;
- end;
- procedure TfmDocument.ShowInfo(AText: string; ALevel: Integer = 0; ADelay: Single = 3.0);
- begin
- aniMsg.Stop;
- txtMsg.Text := AText;
- case ALevel of
- 0:
- txtMsg.TextSettings.FontColor := IfThen(fmMain.actViewDarkStyle.Checked, $FFFFFFFF, $FF000000);
- 1:
- txtMsg.TextSettings.FontColor := $FFFF0000;
- end;
- txtMsg.Opacity := 1.0;
- aniMsg.Delay := ADelay;
- aniMsg.Start;
- end;
- initialization
- end.
|