From bfcaf2d1dba1e685400f5abdb1b5cc573af38c35 Mon Sep 17 00:00:00 2001 From: michael Date: Sat, 31 Mar 2018 19:34:38 +0000 Subject: [PATCH] * Implement copy & paste (bug ID #0033351) git-svn-id: trunk@57584 - --- .../fpreport/design/fpreportdesignctrl.pp | 110 +++++- .../design/fpreportdesignobjectlist.pp | 70 +++- components/fpreport/design/frafpreportdata.pp | 1 - .../design/frmfpreportdesignermain.lfm | 189 +++++++-- .../design/frmfpreportdesignermain.pp | 365 +++++++++++++++++- 5 files changed, 691 insertions(+), 44 deletions(-) diff --git a/components/fpreport/design/fpreportdesignctrl.pp b/components/fpreport/design/fpreportdesignctrl.pp index cb9e80b934..8c91e1b7f3 100644 --- a/components/fpreport/design/fpreportdesignctrl.pp +++ b/components/fpreport/design/fpreportdesignctrl.pp @@ -21,7 +21,7 @@ interface uses Classes, SysUtils, controls, fpreport, graphics, lmessages, fpreportlclexport, lcltype, menus, - fpreportdesignobjectlist, fpreportdrawruler, graphutil, types; + fpreportdesignobjectlist, fpreportdrawruler, graphutil, ClipBrd, types; Const clGrid = TColor($E0E0E0); // Default color for guide grid @@ -52,6 +52,7 @@ Type FMinControlWidth: Integer; FObjects: TReportObjectList; FOnElementCreated: TOnElementCreatedEvent; + FOnPaste: TNotifyEvent; FOnReportChanged: TNotifyEvent; FOnSelectionChanged: TNotifyEvent; FOnStateChange: TNotifyEvent; @@ -132,6 +133,7 @@ Type procedure PaintSelection;virtual; Procedure PaintRulers; virtual; procedure Paint; override; + Procedure Paste; virtual; Property VRuler : TDrawRuler Read FVRuler; Property HRuler : TDrawRuler Read FHRuler; public @@ -140,6 +142,9 @@ Type procedure UpdatePageParams; virtual; procedure Reset; procedure CancelOperation; + Procedure CopySelectionToClipBoard; + Class Procedure CheckClipBoardFormat; + Function GetBandForPaste : TFPReportCustomBand; function ShowEditorForElement(aElement: TFPReportElement): Boolean; Function AddBand(ABandClass : TFPReportBandClass) : TFPReportCustomBand; Procedure AddElement(AElementClass : TFPReportElementClass; Multi : Boolean = False); @@ -164,20 +169,29 @@ Type Property OnSelectionChanged : TNotifyEvent Read FOnSelectionChanged Write FOnSelectionChanged; Property OnReportChanged : TNotifyEvent Read FOnReportChanged Write FOnReportChanged; Property OnStateChange : TNotifyEvent Read FOnStateChange Write FOnStateChange; + Property OnPaste : TNotifyEvent Read FOnPaste Write FOnPaste; end; Const DefaultDesignerOptions = [doGuideGrid,doShowRuler]; // Default for designer options +Var + ClipBoardFormat : TClipboardFormat; + implementation uses lclintf, forms; +Resourcestring + SErrFailedToCopyToClipboard = 'Failed to copy selection to clipboard.'; + const cMoveStepSmall = 1; cMoveStepLarge = 8; + ReportClipBoardFormatName = 'text/fpReport.Elements'; + { --------------------------------------------------------------------- TFPReportDesignerControl @@ -509,6 +523,52 @@ begin DoDrawCurrentFocusRect(FDrawFocusRect); end; +procedure TFPReportDesignerControl.Paste; +begin + If Assigned(FOnPaste) then + FOnPaste(Self); +end; + +Class procedure TFPReportDesignerControl.CheckClipBoardFormat; +begin + If ClipBoardFormat=0 then + ClipBoardFormat:=RegisterClipboardFormat(ReportClipBoardFormatName); +end; + +function TFPReportDesignerControl.GetBandForPaste: TFPReportCustomBand; + +Var + I : Integer; + A : TReportObjectArray; + O : TReportObject; + B : TFPReportCustomBand; + P : TPoint; + +begin + Result:=nil; + // First, check selection; + A:=Objects.GetSelection; + I:=0; + While (Result=Nil) and (I0 then + Result:=Page.Bands[0]; +end; + procedure TFPReportDesignerControl.WMEraseBkgnd(var Message: TLMEraseBkgnd); begin //do nothing to avoid flicker @@ -710,10 +770,28 @@ begin end; procedure TFPReportDesignerControl.KKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState); + +Const +{$IFDEF DARWIN} + CtrlKey = ssMeta; +{$ELSE} + CtrlKey = ssCtrl; +{$ENDIF} + + begin {$IFDEF DEBUGRD} Writeln('Key up: ',Key,', Shifted: ',Shift<>[]);{$ENDIF} if (Key=VK_DELETE) then - FObjects.DeleteSelection; + begin + Key:=0; + if FObjects.DeleteSelection = odrBand then + FObjects.OrderBands(Self.Canvas,CurrentDPI); + end + else if (Key=VK_C) and (Shift=[Ctrlkey]) then + begin + Key:=0; + CopySelectionToClipBoard; + end; end; procedure TFPReportDesignerControl.SetDesignerOptions(AValue: TDesignerOptions); @@ -1233,6 +1311,32 @@ begin end; end; +procedure TFPReportDesignerControl.CopySelectionToClipBoard; + +Var + S : TMemoryStream; + +begin + CheckClipBoardFormat; + S:=TStringStream.Create; + try + FObjects.SaveSelectionToStream(S); + With TFileStream.Create('/tmp/clipbrd.json',fmCreate) do + try + CopyFrom(S,0); + finally + Free; + end; + S.Position:=0; + if not ClipBrd.Clipboard.AddFormat(ClipBoardFormat,S) then + Raise EReportError.Create(SErrFailedToCopyToClipboard); + finally + S.Free; + end; +end; + + + function TFPReportDesignerControl.AddBand(ABandClass: TFPReportBandClass ): TFPReportCustomBand; @@ -1240,7 +1344,7 @@ Var O : TReportObject; begin - Result:=ABandClass.Create(Page); + Result:=ABandClass.Create(Page.Report); Result.Layout.Height:=PixelsToMM(FMinControlHeight,CurrentDPI); Result.Parent:=Page; O:=FObjects.AddBand(Result); diff --git a/components/fpreport/design/fpreportdesignobjectlist.pp b/components/fpreport/design/fpreportdesignobjectlist.pp index 3b071c12e4..e39bcff324 100644 --- a/components/fpreport/design/fpreportdesignobjectlist.pp +++ b/components/fpreport/design/fpreportdesignobjectlist.pp @@ -122,7 +122,7 @@ Type Procedure AdjustSelectedBandToContent(B : TFPReportCustomBand); Procedure AdjustSelectedBandsToContent; Procedure ResetModified; - Procedure SelectElement(E : TFPReportElement); + Procedure SelectElement(E : TFPReportElement; AddToSelection : Boolean = false); Function GetSelection : TReportObjectArray; // Will call selectionchanged, except when result=odrPage Function DeleteSelection : TObjectDeleteResult; @@ -141,6 +141,7 @@ Type Function HorizontalAlignOK(A: THAlignAction) : Boolean;virtual; Function VerticalAlignOK(A: TVAlignAction) : Boolean;virtual; function PointToResizeHandlePos(P: TPoint): TResizeHandlePosition; + procedure SaveSelectionToStream(aStream: TStream); // Properties Property CanvasExport : TFPReportExportCanvas Read FCanvasExport Write FCanvasExport; Property OnSelectionChange : TNotifyEvent Read FOnSelectionChange Write FOnSelectionChange; @@ -177,7 +178,8 @@ Function RectToStr(R : TRect) : String; implementation -uses math; +uses math, fpjson, fpreportstreamer; + Function PointToStr(P : TPoint) : String; @@ -690,7 +692,7 @@ begin FModified:=False; end; -procedure TReportObjectList.SelectElement(E: TFPReportElement); +procedure TReportObjectList.SelectElement(E: TFPReportElement; AddToSelection: Boolean = false); Var I : Integer; @@ -700,7 +702,10 @@ begin For I:=0 to Count-1 do begin O:=Objects[i]; - O.Selected:=(O.Element=E); + if AddToSelection then + O.Selected:=O.Selected or (O.Element=E) + else + O.Selected:=(O.Element=E); end; end; @@ -777,8 +782,10 @@ begin I:=Count-1; end; ReportChanged; + StructureChanged; if (Result<>odrPage) then SelectionChanged; + end; function TReportObjectList.HaveSelection: Boolean; @@ -1445,6 +1452,61 @@ begin end; end; +procedure TReportObjectList.SaveSelectionToStream(aStream: TStream); + + Procedure AddToList(L : TFPList; E : TFPReportElement); + + Var + I : integer; + EC : TFPReportElementWithChildren; + + begin + L.Add(E); + if E is TFPReportElementWithChildren then + begin + EC:=E as TFPReportElementWithChildren; + For I:=0 to EC.ChildCount-1 do + AddToList(L,EC.Child[I]); + end; + end; + + +Var + S : TFPReportJSONStreamer; + C : TJSONStringType; + i,aCount : Integer; + L : TFPList; + +begin + aCount:=0; + L:=Nil; + S:=TFPReportJSONStreamer.Create(Nil); + try + L:=TFPList.Create; + L.Capacity:=300; + S.JSON:=TJSONObject.Create; + S.OwnsJSON:=True; + For I:=0 to Self.Count-1 do + if Objects[i].Selected and (L.IndexOf(Elements[i])=-1) then + begin + S.PushElement(IntToStr(aCount)); + if Elements[i] is TFPReportCustomPage then + S.PushElement('Page'); + Elements[i].WriteElement(S,Nil); + if Elements[i] is TFPReportCustomPage then + S.PopElement; + AddToList(L,Elements[i]); + S.PopElement; + Inc(aCount); + end; + C:=S.JSON.FormatJSON(); + aStream.WriteBuffer(C[1],Length(C)); + finally + L.Free; + S.Free; + end; +end; + Function HCompare (P1,P2 : Pointer) : Integer; Var diff --git a/components/fpreport/design/frafpreportdata.pp b/components/fpreport/design/frafpreportdata.pp index e86eb389ae..111aadcf67 100644 --- a/components/fpreport/design/frafpreportdata.pp +++ b/components/fpreport/design/frafpreportdata.pp @@ -40,7 +40,6 @@ type procedure TVFunctionsStartDrag(Sender: TObject; var DragObject: TDragObject); procedure TVVariablesMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); private - FPageCount : TFPExprIdentifierDef; FIdentifiers: TFPExprIdentifierDefs; FUserVariables : TTreeNode; FBuiltinVariables : TTreeNode; diff --git a/components/fpreport/design/frmfpreportdesignermain.lfm b/components/fpreport/design/frmfpreportdesignermain.lfm index b927e65047..67b65d437b 100644 --- a/components/fpreport/design/frmfpreportdesignermain.lfm +++ b/components/fpreport/design/frmfpreportdesignermain.lfm @@ -393,6 +393,15 @@ object FPReportDesignerForm: TFPReportDesignerForm object MIDelete: TMenuItem Action = ADelete end + object MICopy: TMenuItem + Action = ACopy + end + object MICut: TMenuItem + Action = ACut + end + object MIPaste: TMenuItem + Action = APaste + end end object MReport: TMenuItem Caption = 'Report' @@ -915,6 +924,30 @@ object FPReportDesignerForm: TFPReportDesignerForm OnExecute = AResizeBandToFitExecute OnUpdate = AResizeBandToFitUpdate end + object ACopy: TAction + Category = 'Edit' + Caption = 'Copy' + ImageIndex = 37 + OnExecute = ACopyExecute + OnUpdate = ACopyUpdate + ShortCut = 16451 + end + object APaste: TAction + Category = 'Edit' + Caption = 'Paste' + ImageIndex = 39 + OnExecute = APasteExecute + OnUpdate = APasteUpdate + ShortCut = 16470 + end + object ACut: TAction + Category = 'Edit' + Caption = 'Cut' + ImageIndex = 38 + OnExecute = ACutExecute + OnUpdate = ACutUpdate + ShortCut = 16472 + end end object SDReport: TSaveDialog DefaultExt = '.json' @@ -927,7 +960,7 @@ object FPReportDesignerForm: TFPReportDesignerForm left = 264 top = 192 Bitmap = { - 4C69250000001000000010000000FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + 4C69280000001000000010000000FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF FF006D9CD4896A9AD2FB6697CFEEFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00709ED6DB6D9C @@ -1121,35 +1154,35 @@ object FPReportDesignerForm: TFPReportDesignerForm FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF001615FFFF0A0AFFFF0000FFFFFFFFFF008989 + 89FF898989FFFFFFFF00898989FF898989FFFFFFFF00898989FF898989FFFFFF + FF00898989FF898989FFFFFFFF001616FFFF0A0BFFFF0000FFFF0B0BFFFF1616 + FFFFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF006E6E + FFFF7979FFFF8384FFFF7878FFFFFFFFFF000B0AFFFF0101FFFF0B0BFFFF1617 + FFFF2222FFFF2C2DFFFFFFFFFF00FFFFFF00FFFFFF005858FFFF6363FFFF6E6E + FFFFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000C0CFFFF1717 + FFFF2222FFFF2C2DFFFF3737FFFF4343FFFF4E4DFFFF5859FFFFFFFFFF00FFFF + FF00FFFFFF00898989FFFFFFFF00FFFFFF00898989FFFFFFFF00FFFFFF00FFFF + FF002222FFFF2D2DFFFF3738FFFF4242FFFF4E4EFFFFFFFFFF00FFFFFF00FFFF + FF00FFFFFF00898989FFFFFFFF00FFFFFF00898989FFFFFFFF00FFFFFF00FFFF + FF002222FFFF2D2EFFFF3838FFFF4343FFFF4E4DFFFFFFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF001717 + FFFF2222FFFF2D2DFFFF3938FFFF4343FFFF4E4EFFFF5959FFFFFFFFFF00FFFF + FF00FFFFFF00898989FFFFFFFF00FFFFFF00898989FFFFFFFF000D0DFFFF1817 + FFFF2223FFFF2E2EFFFFFFFFFF00FFFFFF004E4FFFFF595AFFFF6464FFFFFFFF + FF00FFFFFF00898989FFFFFFFF00FFFFFF00898989FF0202FFFF0D0DFFFF1817 + FFFF2223FFFFFFFFFF00FFFFFF00FFFFFF00FFFFFF005A5AFFFF6464FFFF6F70 + FFFFFFFFFF00FFFFFF00FFFFFF00FFFFFF000909FFFF0202FFFF0D0DFFFF1818 + FFFFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF006465FFFF6F6F + FFFFFFFFFF00898989FFFFFFFF001414FFFF0909FFFF0202FFFF0E0DFFFFFFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF006464FFFF6F70 + FFFF7B7BFFFF898989FFFFFFFF001413FFFF0809FFFF0302FFFF0D0EFFFFFFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF006F70 + FFFF7A7AFFFFFFFFFF00FFFFFF001313FFFF0809FFFF0303FFFFFFFFFF00FFFF FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00806D5EFF7C614CFF8062 - 49FF816249FF816249FF826449FF816348FF836248FF836248FF84624AFF7E61 - 4CFF806D5EFFFFFFFF00FFFFFF00FFFFFF00FFFFFF007C614CFFEED4BCFFEDD2 - B8FFEFD2B7FFEDCFB4FFEFCFB2FFEECEB1FFF1CFB2FFF0CEB1FFEFCCB2FFEBCC - B3FF7E614CFFFFFFFF00FFFFFF00FFFFFF00FFFFFF007C614CFFE6CCB4FFD1B6 - 9CFFD2B59AFFD1B398FFD2B295FFCBAB8EFFCBA98CFFC8A689FFC6A389FFDCBD - A4FF7E614CFFFFFFFF00FFFFFF00FFFFFF00FFFFFF00806D5EFF7C614CFF8062 - 49FF816249FF816249FF816249FF816249FF836248FF816348FF816249FF7C61 - 4CFF806D5EFFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF007A7BFFFF898989FFFFFFFF00FFFFFF00898989FF898989FFFFFFFF008989 + 89FF898989FFFFFFFF00898989FF898989FFFFFFFF00898989FF898989FFFFFF + FF00898989FF898989FFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF @@ -2111,7 +2144,103 @@ object FPReportDesignerForm: TFPReportDesignerForm 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000 + 0000000000000000000000000000C77947AACC8655CECC8857DECB8856DBCC88 + 56DBCB8757DBCA8350D0C479426EB2673C08FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00CA8554D0FFFFFFDBFDF3E9DEFDF3EADEFCF2 + E8DEFAEFE3DEFAF2E7DEEABB88DECF85559CB4693D0AFFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00CB8656DAFEF5EDDEFCDEC5DEFBE0C7DEF9DC + C2DEF5D3B4DEFEF9F3DEFAE2C4DEECC193DEC37D4880FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00CB8655DBFEF6F0DEFCE2CDDEFCE3CDDEFADF + C8DEF7D9BCDEF5E9DDDEFAF3EBDEFBF8F3DECD9565DCFFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00CB8655DBFEF7F1DEFCE5D2DEFCE4D1DEFBE2 + CCDEF9DDC4DEEAC39DFFE6BF96FFE4BB92FFE4BB92FFD1A06CF5D09E6DF6CC96 + 5FDAC479427EB2673C09FFFFFF00CB8654DBFFF7F2DEFEE7D5DEFEE7D5DEFDE5 + D1DEFAE0CADEE5BE96FFFFFFFEFFFDF3E9FFFDF3EAFFFCF2E8FFFAEFE3FFFAF2 + E7FFEABB88FFCF8555B3B4693D0CCB8553DBFFF7F0DEFFE7D5DEFDE7D6DEFDE6 + D4DEFCE4D0DEE4BB93FFFEF5EDFFFCDEC5FFFBE0C7FFF9DCC2FFF5D3B4FFFEF9 + F3FFFAE2C4FFECC193FFC37D4893CA8452DBFFF7F1DEFFE9D9DEFFEADBDEFFE9 + D9DEFFE7D7DEE4BB92FFFEF6F0FFFCE2CDFFFCE3CDFFFADFC8FFF7D9BCFFF5E9 + DDFFFAF3EBFFFBF8F3FFCA8353FECC8352DBFBF5EEDEFFE9D9DEFFEADBDEFFE9 + D9DEFFE7D7DEE4BB92FFFEF7F1FFFCE5D2FFFCE4D1FFFBE2CCFFF9DDC4FFF6D7 + BBFFF3D1AFFFFAEFE4FFCC8758FECF8253DEEFF1E7DEFFE9D9DEFFEADBDEFFE9 + D9DEFFE7D7DEE4BB91FFFFF7F2FFFEE7D5FFFEE7D5FFFDE5D1FFFAE0CAFFF9DE + C4FFF7D9BCFFFDF2E7FFCC8757FEC87C4ED3FCF3ECDEFAF1E8DEFAF0E7DEFBF1 + E9DEFBF2EADEE4BA91FFFFF7F0FFFFE7D5FFFDE7D6FFFDE6D4FFFCE4D0FFFBE3 + CBFFFADCC2FFFEF3E8FFCC8656FEC7794AB9C8794BCEC87545DDC77545D4C875 + 45D4C77545D4CA8452FFFFF7F1FFFFE9D9FFFFEADBFFFFE9D9FFFFE7D7FFFFE5 + D2FFFFE2CBFFFFF7F1FFCB8555FEFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00CC8352FBFBF5EEFFFFE9D9FFFFEADBFFFFE9D9FFFFE7D7FFFFE5 + D2FFFFE2CBFFFBF6EFFFCC8355FEFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00CF8253FFEFF1E7FFFFE9D9FFFFEADBFFFFE9D9FFFFE7D7FFFFE5 + D2FFFFE2CBFFEFF2E8FFCE8156FFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00C77949EDFCF3ECFFFAF1E8FFFAF0E7FFFBF1E9FFFBF2EAFFFBF2 + EAFFFBF2EBFFFDF4EEFFCA8054F9FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00C57342C1C67545E6C87545FEC77545F3C87545F3C77545F3C775 + 45F3C87546F4C57444E8CA7F53F1FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF009A6B2731AA7E43A192601805FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00A87D4269CCB08BE0915D1409FFFFFF00FFFFFF00FFFF + FF0092601706FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00AA81476FD6BD9FF793611910FFFFFF00FFFFFF009666 + 202CA9804BCBFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00AC834B75DEC9AFFF95641D1FFFFFFF0092601726C3A4 + 7CEBB59063CBFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00AF87507CE7D5C1FF95651F2B8F5C121BC5A783E7D5BC + 9DE1B5936462FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00B1895384EEDFCEFF97662065C2A37CDAE9D8C5FDA982 + 4E7BFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00B38C5789F1E2D4FFCEB28EF4F5EBE0FFA67F4A9DFFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00000B8802FFFFFF00B48E5A90F6EADDFFE1CDB4FFB18D5DBFFFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00030D8C1F1B26 + A7992A34BACC111C9D89BB9869CCF0E0D0FFB7915FC58F5D140BFFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00030D8C1F2C35B9D73C46 + CFFF333ECAF23F4CD7FFD8BC9AFFF6EAE1FFBB925ABF9462183B91611A01FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF001D28A99C3B46CCFF0812 + 903A071190533B48D4FFDBBD9CFFEECCA6FF404CDEFF3A43D1FF0F199869FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00323CC3EC232EADAFFFFF + FF001A25A8994250D2FFCBA375FE414FD6FF1621A39D2F39C0D42E38BEDF020D + 8B0AFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF002F3ABDDE353FC9E52530 + B3C23F4ADDFF1F2AACC22430B2CB323CC6F2000A8603111B9D773741C8FF0812 + 8E20FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000F199763323DC7F83741 + CFFF1F29ABB0000A8618232DB4AF3540CCFD000985181C27A895343EC5F8040E + 8C14FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00050F8D1F0610 + 8E26010B8A03FFFFFF00121C9B70404BD9FF2C35BFDD3D47D1FF1D27A9A4FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00020D8C0A1C27A69F353FC9F7222DAFB9030D8C1CFFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF002063982A206398FF2063 + 98FF206398FF206398FF206398FF206398F0FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF0020639832206398B2206398FF3775A4FFB6EF + FEFF80DBF3FF80DBF3FFB6EFFEFF2E6EA1FF206398FF206398A520639853FFFF + FF00FFFFFF00FFFFFF00FFFFFF00206398E071B3DBFE7EBFE4FF4E9DDFFFB5EE + FDFF75D4F0FF75D4F0FFB5EEFDFF4B9BDEFF6EB4E0FF6DB3DFF9206398F3FFFF + FF00FFFFFF00FFFFFF00FFFFFF00206398FF7FBFE4FF69B2DEFF4A9BDAFF4497 + DCFF4396DCFF4296DCFF4295DCFF4195DBFF519ED6FF6CB2DEFF206398FFFFFF + FF00FFFFFF00FFFFFF00FFFFFF00206398FF7CBDE4FF65AEDDFF62ABDCFF5EA8 + DAFF5CA7D9FF5CA7D9FF5CA7D9FF5CA7D9FF529FD7FF62A3D8FF206398FFFFFF + FF00FFFFFF00FFFFFF00FFFFFF00206398FF7ABBE3FF61AADBFF5AA5D9FF53A0 + D7FF529FD7FF529FD7FF529FD7FF529FD7FF529FD7FF62A3D8FF206398FFFFFF + FF00FFFFFF00FFFFFF00FFFFFF00206398FF76B9E2FF5CA7D9FF58A4D8FF53A0 + D7FF539ED5FF618BA9FF6488A1FF6487A1FF6386A0FF69879FFF4A6881FF6A6A + 6A8A6868688A6565658A62626263206398FF73B7E1FF57A3D7FF53A0D7FF509D + D5FF5299CFFF7594ACFFF8F8F8FFF2F2F2FFF2F2F2FFF2F2F2FFF2F2F2FFF2F2 + F2FFF1F1F1FFF4F4F4FA5E5E5E84206398FF70B5E0FF529FD7FF509CD6FF4E98 + D4FF4F95CDFF7391AAFFF1F1F1FFB7B7B7FFB6B6B6FFB6B6B6FFB6B6B6FFB5B5 + B5FFB5B5B5FFEEEEEEFA5A5A5A84206398FF6DB3DFFF509CD5FF4E98D3FF4B94 + D1FF4C91CBFF708EA7FFF1F1F1FFE9E9E9FFE9E9E9FFE8E8E8FFE8E8E8FFE8E8 + E8FFE7E7E7FFEDEDEDFA56565684206398FF6BB1DEFF4D97D3FF4B93D2FF488F + D0FF4A8CC9FF6F8BA5FFF1F1F1FFB6B6B6FFB5B5B5FFB5B5B5FFB4B4B4FFB4B4 + B4FFB4B4B4FFEDEDEDFA53535384206398FF69AEDCFF4A93D1FF488FD0FF468B + CEFF4788C7FF6C88A3FFF0F0F0FFE8E8E8FFE8E8E8FFE7E7E7FFE7E7E7FFE7E7 + E7FFE7E7E7FFEDEDEDFA4F4F4F84206398FF68ABDCFF488ECFFF468BCEFF4387 + CDFF4484C6FF6885A1FFF0F0F0FFB4B4B4FFB4B4B4FFB4B4B4FFB4B4B4FFB4B4 + B4FFB3B3B3FFEDEDEDFA4C4C4C84206398C262A5D7FF65A8DAFF64A6D9FF62A4 + D8FF629FD1FF758EA4FFEFEFEFFFE7E7E7FFE7E7E7FFE7E7E7FFE7E7E7FFE6E6 + E6FFE6E6E6FFECECECFA494949842063984A206398CF206398FF206398FF2063 + 98FF246395FF587388FFF7F7F7FFF0F0F0FFF0F0F0FFF0F0F0FFF0F0F0FFF0F0 + F0FFF0F0F0FFF3F3F3FA46464684FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF005E5E5E025B5B5B775858588A5555558A5252528A4F4F4F8A4C4C4C8A4A4A + 4A8A4848488A4646468A44444466 } end object PMAdd: TPopupMenu diff --git a/components/fpreport/design/frmfpreportdesignermain.pp b/components/fpreport/design/frmfpreportdesignermain.pp index 06144f9d9a..f7f7e21acd 100644 --- a/components/fpreport/design/frmfpreportdesignermain.pp +++ b/components/fpreport/design/frmfpreportdesignermain.pp @@ -20,7 +20,7 @@ interface uses Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls, fpreportdata, - Menus, ActnList, ComCtrls, ExtCtrls, IniPropStorage, fpreport, fpreportdesignctrl, + Menus, ActnList, ComCtrls, ExtCtrls, IniPropStorage, fpreport, fpreportdesignctrl, contnrs, fraReportObjectInspector, fpreportdesignreportdata, frafpreportdata, mrumanager; type @@ -37,6 +37,14 @@ type ); TFPReportDesignOptions = set of TFPReportDesignOption; + // What to do when selection contains a report page + TPageCopyAction = (pcaNone,pcaAbort,pcaReplace,pcaAdd); + TPageCopyActions = set of TPageCopyAction; + + // What to do when selection contains a band that cannot be correctly added to the current page. + TBandCopyAction = (bcaNone,bcaAbort,bcaConvertToChild); + TBandCopyActions = Set of TBandCopyAction; + { TPageTabSheet } TPageTabSheet = class(TTabSheet) @@ -74,6 +82,9 @@ type AAlignVCenter: TAction; AAlignBottom: TAction; AAlign: TAction; + ACopy: TAction; + ACut: TAction; + APaste: TAction; AResizeBandToFit: TAction; AFileSaveAs: TAction; ARecent: TAction; @@ -102,6 +113,9 @@ type MenuItem1: TMenuItem; MenuItem2: TMenuItem; MenuItem3: TMenuItem; + MICopy: TMenuItem; + MICut: TMenuItem; + MIPaste: TMenuItem; MISaveAs: TMenuItem; MIPreview: TMenuItem; MIframeBottom: TMenuItem; @@ -234,6 +248,10 @@ type procedure AAddShapeExecute(Sender: TObject); procedure AAlignExecute(Sender: TObject); procedure AAlignUpdate(Sender: TObject); + procedure ACopyExecute(Sender: TObject); + procedure ACopyUpdate(Sender: TObject); + procedure ACutExecute(Sender: TObject); + procedure ACutUpdate(Sender: TObject); procedure ADeleteExecute(Sender: TObject); procedure ADeleteUpdate(Sender: TObject); procedure AFileSaveAsExecute(Sender: TObject); @@ -242,6 +260,8 @@ type procedure AFrameExecute(Sender: TObject); procedure AFrameUpdate(Sender: TObject); procedure ANewExecute(Sender: TObject); + procedure APasteExecute(Sender: TObject); + procedure APasteUpdate(Sender: TObject); procedure APreviewExecute(Sender: TObject); procedure APreviewUpdate(Sender: TObject); procedure AReportDataExecute(Sender: TObject); @@ -298,12 +318,22 @@ type procedure InitialiseData; {$ENDIF} function CreateNewPage: TFPReportCustomPage; + procedure DoPaste(Sender: TObject); procedure DoReportChangedByDesigner(Sender: TObject); procedure DoSelectionModifiedByOI(Sender: TObject); procedure DoStructureChange(Sender: TObject); + procedure ExecutePaste(aControl: TFPReportDesignerControl); + procedure GetCopyActions(aControl: TFPReportDesignerControl; L: TFPObjectList; out PCA: TPageCopyAction; out + BCA: TBandCopyAction); function GetModified: boolean; procedure ActivateDesignerForElement(AElement: TFPReportElement); + function GetPageCopyAction(aCount: Integer): TPageCopyAction; + function GetBandCopyAction(aCount: Integer): TBandCopyAction; procedure MaybeAddFirstPage; + procedure PasteBand(aControl: TFPReportDesignerControl; aAction: TBandCopyAction; var aBand: TFPReportCustomBand); + procedure PasteElement(aControl: TFPReportDesignerControl; aBand: TFPReportCustomBand; aElement: TFPReportElement); + procedure PasteList(aControl: TFPReportDesignerControl; L: TFPObjectList); + function PastePage(aAction: TPageCopyAction; aPage: TFPReportCustomPage): TFPReportDesignerControl; procedure ResetReport; procedure SetBandActionTags; procedure SetDesignOptions(AValue: TFPReportDesignOptions); @@ -315,7 +345,7 @@ type procedure MRUMenuManager1RecentFile(Sender: TObject; const AFileName: String); procedure Notification(AComponent: TComponent; Operation: TOperation); override; procedure ApplyDesignOptions; virtual; - function AddPageDesign(aPageNo: Integer; APage: TFPReportCustomPage): TTabSheet; + function AddPageDesign(APage: TFPReportCustomPage): TTabSheet; Function FindTabForReportPage(APage : TFPReportCustomPage) : TPageTabSheet; procedure DoSelectComponent(Sender: TObject; Selected: TComponent); virtual; procedure DoSelectionChanged(Sender: TObject); virtual; @@ -367,6 +397,7 @@ uses fpttf, fpreportstreamer, fpjson, + Clipbrd, jsonparser; {$R *.lfm} @@ -390,6 +421,26 @@ ResourceString SErrInvalidReport = 'Invalid report design'; SErrFixErrors = 'The report design contains %d errors:'+sLineBreak+'%s'+sLineBreak+ 'You will need to fix these errors before proceeding.'; + SErrCannotCopyClipboardFormat = 'Clipboard contents cannot be pasted into report.'; + SCopyingPage = 'Pasting report page'; + SCopyingPageWhat = 'The selection contains a complete report page.'+sLineBreak+ + 'What do you want to do with this page?'; + SCopyingPages = 'Pasting multiple report pages'; + SCopyingPagesWhat = 'The selection contains multiple complete report pages.'+sLineBreak+ + 'What do you want to do with these pages?'; + SCopyingBand = 'Pasting conflicting band'; + SCopyingBandWhat = 'The selection contains a band which cannot be logically placed on the current page.'+sLineBreak+ + 'What do you want to do with this band?'; + SCopyingBands = 'Pasting multiple conflicting bands'; + SCopyingBandsWhat = 'The selection contains multiple bands which cannot be logically placed on the current page.'+sLineBreak+ + 'What do you want to do with these bands?'; + SNoCopy = 'Do not copy'; + SPageAdd = 'Add as new page'; + SPageReplace = 'Replace current page'; + SAbortCopy = 'Abort copy'; + sBandConvert = 'Convert to child band'; + sBandConverts = 'Convert to child bands'; + SErrNoBandToPaste = 'No band to paste elements on'; Const StateNames : Array[TDesignerState] of string = ('','Resetting', @@ -516,7 +567,7 @@ begin MaybeAddFirstPage; Report.StartDesigning; For I:=0 to Report.PageCount-1 do - AddPageDesign(I+1,Report.Pages[I]); + AddPageDesign(Report.Pages[I]); ShowReportData; ResetObjectInspector; if FLoadModified then @@ -653,8 +704,7 @@ begin end; -function TFPReportDesignerForm.AddPageDesign(aPageNo: Integer; - APage: TFPReportCustomPage): TTabSheet; +function TFPReportDesignerForm.AddPageDesign(APage: TFPReportCustomPage): TTabSheet; Var TS : TPageTabSheet; @@ -682,6 +732,7 @@ begin D.OnStateChange:=@DoStateChange; D.OnReportChanged:=@DoReportChangedByDesigner; D.Objects.OnStructureChange:=@DoStructureChange; + D.OnPaste:=@DoPaste; D.Objects[0].Selected:=True; Result:=TS; end; @@ -811,6 +862,272 @@ begin Result.StartDesigning; end; +Function TFPReportDesignerForm.GetPageCopyAction(aCount : Integer) : TPageCopyAction; + +Var + MR : TModalResult; + +begin + if aCount=1 then + MR:=QuestionDlg(SCopyingPage,SCopyingPageWhat,mtWarning,[ + mrIgnore,SNoCopy, + mrYes,SPageAdd, + mrRetry,sPageReplace, + mrAbort,sAbortCopy],'') + else + MR:=QuestionDlg(SCopyingPages,SCopyingPagesWhat,mtWarning,[ + mrIgnore,SNoCopy, + mrYes,SPageAdd, + mrAbort,sAbortCopy],''); + case MR of + mrIgnore : Result:=pcaNone; + mrYes: Result:=pcaAdd; + mrRetry : Result:=pcaReplace; + mrAbort :Result:=pcaAbort; + else + Result := pcaAbort + end; +end; + +function TFPReportDesignerForm.GetBandCopyAction(aCount: Integer): TBandCopyAction; + +Var + MR : TModalResult; + BC,C,M : String; + +begin + if aCount=1 then + begin + C:=SCopyingBand; + M:=SCopyingBandWhat; + BC:=sBandConvert; + end + else + begin + C:=SCopyingBands; + M:=SCopyingBandsWhat; + BC:=sBandConverts; + end; + MR:=QuestionDlg(C,M,mtWarning,[ + mrIgnore,SNoCopy, + mrYes,BC, + mrAbort,sAbortCopy],''); + case MR of + mrIgnore : Result:=bcaNone; + mrYes: Result:=bcaConvertToChild; + mrAbort :Result:=bcaAbort; + else + Result := bcaAbort + end; +end; + + + +procedure TFPReportDesignerForm.ExecutePaste(aControl : TFPReportDesignerControl); + +Var + L : TFPObjectList; + S : TMemoryStream; + +begin + aControl.CheckClipBoardFormat; + if Not ClipBoard.HasFormat(ClipBoardFormat) then + Raise EReportError.Create(SErrCannotCopyClipboardFormat); + L:=Nil; + S:=Nil; + try + S:=TMemoryStream.Create; + ClipBoard.GetFormat(ClipBoardFormat,S); + S.Position:=0; + L:=FReport.StreamToReportElements(S); + PasteList(aControl,L); + finally + FreeAndNil(L); + FreeAndNil(S); + end; +end; + +procedure TFPReportDesignerForm.GetCopyActions(aControl : TFPReportDesignerControl; L : TFPObjectList; + Out PCA : TPageCopyAction; + out BCA : TBandCopyAction); + +Var + i,pCount : Integer; + +begin + PCA:=pcaNone; + bca:=bcaNone; + pCount:=0; + for I:=0 to L.Count-1 do + if L[i] is TFPReportCustomPage then + inc(pCount); + if pCount>0 then + PCA:=GetPageCopyAction(pCount); + if (PCA=pcaAbort) then + exit; + pCount:=0; + for I:=0 to L.Count-1 do + if L[i] is TFPReportCustomBand then + if Not aControl.Page.CheckBandMultiplicity(TFPReportCustomBand(L[i])) then + Inc(pCount); + if pCount>0 then + BCA:=GetBandCopyAction(pCount) +end; + +procedure TFPReportDesignerForm.PasteList(aControl : TFPReportDesignerControl; L : TFPObjectList); + +Var + L2 : TFPList; + i : Integer; + PCA : TPageCopyAction; + BCA : TBandCopyAction; + E : TFPReportElement; + B : TFPReportCustomBand; + cControl : TFPReportDesignerControl; + NeedReorder : Boolean; + +begin + GetCopyActions(aControl,l,PCA,BCA); + if (PCA=pcaAbort) or (BCA=bcaAbort) then + exit; + cControl:=aControl; + // First the pages (current page may be changed by this) + For I:=0 to L.Count-1 do + if L[I] is TFPReportCustomPage then + begin + E:=TFPReportCustomPage(L.Extract(L[i])); + cControl:=PastePage(PCA,(E as TFPReportCustomPage)); + end; + if L.Count=0 then + exit; + // .. and paste the rest. + NeedReorder:=False; + L2:=TFPList.Create; // List to contain pasted elements + try + B:=aControl.GetBandForPaste; + While (L.Count>0) do + begin + E:=TFPReportElement(L.Extract(L[0])); + if E is TFPReportCustomBand then + begin + PasteBand(cControl,BCA,TFPReportCustomBand(E)); + NeedReorder:=NeedReorder or Assigned(E); + // If there was not a band, use the just pasted one, if there is one. + if B=Nil then + B:=aControl.GetBandForPaste; + end + else if (E is TFPReportElement) then + PasteElement(cControl,B,E) + else + FreeAndNil(E); + if Assigned(E) then + L2.Add(E); + end; + // Set selection to pasted objects. Pages will not be selected by this + cControl.Objects.ClearSelection; + For I:=0 to L2.Count-1 do + cControl.Objects.SelectElement(TFPReportElement(L2[i])); + if NeedReorder then + cControl.Objects.OrderBands(cControl.Canvas,CurrentDesigner.CurrentDPI); + DoStructureChange(Self); + finally + FreeAndNil(L2); + end; +end; + + +Function TFPReportDesignerForm.PastePage(aAction : TPageCopyAction; aPage : TFPReportCustomPage) : TFPReportDesignerControl; + +Var + Idx : Integer; + oldPage : TFPReportCustomPage; + +begin + Idx:=CurrentDesigner.Page.PageIndex; + FReport.AddPage(aPage); + Case aAction of + pcaAdd: + begin + Result:=TPageTabSheet(AddPageDesign(aPage)).Designer; + end; + pcaReplace: + begin + oldPage:=CurrentDesigner.Page; + idx:=OldPage.PageIndex; + CurrentDesigner.Page:=aPage; + FReport.RemovePage(oldPage); + aPage.PageIndex:=idx; + end; + end; +end; + +Procedure TFPReportDesignerForm.PasteBand(aControl : TFPReportDesignerControl; aAction : TBandCopyAction; var aBand : TFPReportCustomBand); + +Var + C : TFPReportCustomChildBand; + I : Integer; + N : String; + +begin + if Not aControl.Page.CheckBandMultiplicity(aBand) then + Case aAction of + bcaNone : FreeAndNil(aBand); + bcaConvertToChild : + begin + C:=TFPReportCustomChildBand(gElementFactory.CreateInstance('ChildBand',aControl.Page.Report)); + N:=aBand.Name; + // Copy properties + aBand.ChildBand:=Nil; + C.Assign(aBand); + // Copy elements + For I:=aBand.ChildCount-1 downto 0 do + aBand.Child[i].Parent:=C; + // Replace + FreeAndNil(aBand); + aBand:=C; + aBand.Name:=N; + end; + end; + // Paste into page. + if Assigned(aBand) then + begin + aBand.Parent:=aControl.Page; + aControl.Objects.AddBand(aBand); + end; +end; + +Procedure TFPReportDesignerForm.PasteElement(aControl : TFPReportDesignerControl; aBand : TFPReportCustomBand; aElement : TFPReportElement); + +Const + xShift = 2.0; + yShift = 2.0; + +begin + if (ABand=Nil) then + Raise EReportError.Create(SErrNoBandToPaste); + aElement.Parent:=aBand; + aElement.Layout.Left:=aElement.Layout.Left+xShift; + if aElement.Layout.Left>aBand.Layout.Width then + begin + aElement.Layout.Left:=aBand.Layout.Width-aElement.Layout.Width; + if aElement.Layout.Left<0 then + aElement.Layout.Left:=0; + end; + aElement.Layout.Top:=aElement.Layout.Top+yShift; + if aElement.Layout.top>aBand.Layout.Height then + begin + aElement.Layout.top:=aBand.Layout.Height-aElement.Layout.Height; + if aElement.Layout.top<0 then + aElement.Layout.top:=0; + end; + aControl.Objects.AddElement(aElement); +end; + +procedure TFPReportDesignerForm.DoPaste(Sender: TObject); +begin + ExecutePaste(Sender as TFPReportDesignerControl); +end; + procedure TFPReportDesignerForm.AAddPageExecute(Sender: TObject); Var @@ -821,7 +1138,7 @@ begin FReport.AddPage(P); P.Name:='Page'+IntToStr(FReport.PageCount); FOI.RefreshReportTree; - PCReport.ActivePage:=AddPageDesign(FReport.PageCount,P); + PCReport.ActivePage:=AddPageDesign(P); Modified:=True; end; @@ -902,6 +1219,31 @@ begin and CurrentDesigner.Objects.HaveSelection end; +procedure TFPReportDesignerForm.ACopyExecute(Sender: TObject); +begin + if Assigned(CurrentDesigner) then + CurrentDesigner.CopySelectionToClipBoard; +end; + +procedure TFPReportDesignerForm.ACopyUpdate(Sender: TObject); +begin + (Sender As Taction).Enabled:=Assigned(CurrentDesigner) and CurrentDesigner.Objects.HaveSelection; +end; + +procedure TFPReportDesignerForm.ACutExecute(Sender: TObject); +begin + if Assigned(CurrentDesigner) then + begin + CurrentDesigner.CopySelectionToClipBoard; + CurrentDesigner.Objects.DeleteSelection; + end; +end; + +procedure TFPReportDesignerForm.ACutUpdate(Sender: TObject); +begin + (Sender As Taction).Enabled:=Assigned(CurrentDesigner) and CurrentDesigner.Objects.HaveSelection; +end; + procedure TFPReportDesignerForm.ADeleteExecute(Sender: TObject); Var @@ -1063,6 +1405,17 @@ begin DesignReport; end; +procedure TFPReportDesignerForm.APasteExecute(Sender: TObject); +begin + DoPaste(CurrentDesigner); +end; + +procedure TFPReportDesignerForm.APasteUpdate(Sender: TObject); +begin + TFPReportDesignerControl.CheckClipBoardFormat; + (Sender as TAction).Enabled:=ClipBoard.HasFormat(ClipBoardFormat); +end; + Procedure TFPReportDesignerForm.MaybeAddFirstPage; Var