1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: Printing and clipboard functionality
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
13 // #pragma implementation
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
27 #include <wx/ogl/ogl.h> // base header of OGL, includes and adjusts wx/deprecated/setup.h
29 #include <wx/clipbrd.h>
32 #include <wx/metafile.h>
40 IMPLEMENT_DYNAMIC_CLASS(wxDiagramClipboard
, wxDiagram
)
43 bool wxDiagramClipboard::Copy(wxDiagram
* diagram
)
47 return DoCopy(diagram
, this, false, NULL
);
50 // Copy contents to the diagram, with new ids.
52 bool wxDiagramClipboard::Paste(wxDiagram
* diagram
, wxDC
* dc
, int offsetX
, int offsetY
)
54 return DoCopy(this, diagram
, true, dc
, offsetX
, offsetY
);
57 // Universal copy function (to or from clipboard).
59 // Note that this only works for non-composites so far (nested shapes
60 // don't have their old-to-new object mappings stored).
61 // Also, lines don't yet get their attachment points moved to the new offset position
62 // if they have more than 2 points.
63 bool wxDiagramClipboard::DoCopy(wxDiagram
* diagramFrom
, wxDiagram
* diagramTo
, bool newIds
,
64 wxDC
* dc
, int offsetX
, int offsetY
)
66 OnStartCopy(diagramTo
);
68 wxHashTable
mapping(wxKEY_INTEGER
);
70 // First copy all node shapes.
71 wxList
* shapeList
= diagramFrom
->GetShapeList();
72 wxObjectList::compatibility_iterator node
= shapeList
->GetFirst();
75 wxShape
* shape
= (wxShape
*) node
->GetData();
76 if (((diagramFrom
== this) || shape
->Selected()) && !shape
->IsKindOf(CLASSINFO(wxLineShape
)))
78 wxShape
* newShape
= shape
->CreateNewCopy();
79 newShape
->GetLines().Clear();
82 newShape
->AssignNewIds();
84 mapping
.Put((long) shape
, (wxObject
*) newShape
);
86 newShape
->SetX(newShape
->GetX() + offsetX
);
87 newShape
->SetY(newShape
->GetY() + offsetY
);
89 OnAddShape(diagramTo
, newShape
, dc
);
92 node
= node
->GetNext();
95 node
= shapeList
->GetFirst();
98 wxShape
* shape
= (wxShape
*) node
->GetData();
99 if (((diagramFrom
== this) || shape
->Selected()) && shape
->IsKindOf(CLASSINFO(wxLineShape
)))
101 wxLineShape
* lineShape
= (wxLineShape
*) shape
;
102 // Only copy a line if its ends are selected too.
103 if ((diagramFrom
== this) || (lineShape
->GetTo()->Selected() && lineShape
->GetFrom()->Selected()))
105 wxLineShape
* newShape
= (wxLineShape
*) shape
->CreateNewCopy();
106 mapping
.Put((long) shape
, (wxObject
*) newShape
);
109 newShape
->AssignNewIds();
111 wxShape
* fromShape
= (wxShape
*) mapping
.Get((long) lineShape
->GetFrom());
112 wxShape
* toShape
= (wxShape
*) mapping
.Get((long) lineShape
->GetTo());
114 wxASSERT_MSG( (fromShape
!= NULL
), _T("Could not find 'from' shape"));
115 wxASSERT_MSG( (toShape
!= NULL
), _T("Could not find 'to' shape"));
117 fromShape
->AddLine(newShape
, toShape
, newShape
->GetAttachmentFrom(),
118 newShape
->GetAttachmentTo());
120 OnAddShape(diagramTo
, newShape
, dc
);
124 node
= node
->GetNext();
127 // Now make sure line ordering is correct
128 node
= shapeList
->GetFirst();
131 wxShape
* shape
= (wxShape
*) node
->GetData();
132 if (((diagramFrom
== this) || shape
->Selected()) && !shape
->IsKindOf(CLASSINFO(wxLineShape
)))
134 wxShape
* newShape
= (wxShape
*) mapping
.Get((long) shape
);
136 // Make a list of all the new lines, in the same order as the old lines.
137 // Then apply the list of new lines to the shape.
139 wxObjectList::compatibility_iterator lineNode
= shape
->GetLines().GetFirst();
142 wxLineShape
* lineShape
= (wxLineShape
*) lineNode
->GetData();
143 if ((diagramFrom
== this) || (lineShape
->GetTo()->Selected() && lineShape
->GetFrom()->Selected()))
145 wxLineShape
* newLineShape
= (wxLineShape
*) mapping
.Get((long) lineShape
);
147 wxASSERT_MSG( (newLineShape
!= NULL
), _T("Could not find new line shape"));
149 newLines
.Append(newLineShape
);
152 lineNode
= lineNode
->GetNext();
155 if (newLines
.GetCount() > 0)
156 newShape
->ApplyAttachmentOrdering(newLines
);
158 node
= node
->GetNext();
161 OnEndCopy(diagramTo
);
167 // Draw contents to a Windows metafile device context and a bitmap, and copy
168 // these to the Windows clipboard
169 bool wxDiagramClipboard::CopyToClipboard(double scale
)
172 // Make a metafile DC
176 mfDC
.SetUserScale(scale
, scale
);
178 // Draw on metafile DC
181 // int printWidth = mfDC.MaxX() - mfDC.MinX();
182 // int printHeight = mfDC.MaxY() - mfDC.MinY();
183 int maxX
= (int)mfDC
.MaxX();
184 int maxY
= (int)mfDC
.MaxY();
185 wxMetaFile
*mf
= mfDC
.Close();
187 // Set to a bitmap memory DC
188 wxBitmap
*newBitmap
= new wxBitmap((int)(maxX
+ 10), (int)(maxY
+ 10));
189 if (!newBitmap
->Ok())
194 wxSprintf(buf
, _T("Sorry, could not allocate clipboard bitmap (%dx%d)"), (maxX
+10), (maxY
+10));
195 wxMessageBox(buf
, _T("Clipboard copy problem"));
200 memDC
.SelectObject(*newBitmap
);
203 // Now draw on memory bitmap DC
206 memDC
.SelectObject(wxNullBitmap
);
208 // Open clipboard and set the data
209 if (wxOpenClipboard())
213 // Copy the bitmap to the clipboard
214 wxSetClipboardData(wxDF_BITMAP
, newBitmap
, 0, 0);
216 #if 0 // TODO: replace this code (wxEnhMetaFile doesn't have SetClipboard)
219 // Copy the metafile to the clipboard
220 // Allow a small margin
221 bool success
= mf
->SetClipboard((int)(mfDC
.MaxX() + 15), (int)(mfDC
.MaxY() + 15));
235 wxMessageBox("wxUSE_METAFILE in build required to use Clipboard", _T("Clipboard copy problem"));
242 // Override this to e.g. have the shape added through a Do/Undo command system.
243 // By default, we'll just add it directly to the destination diagram.
244 bool wxDiagramClipboard::OnAddShape(wxDiagram
* diagramTo
, wxShape
* newShape
, wxDC
* dc
)
246 diagramTo
->AddShape(newShape
);
248 if (dc
&& (diagramTo
!= this))
250 newShape
->Select(true, dc
);
260 IMPLEMENT_DYNAMIC_CLASS(csDiagramClipboard
, wxDiagramClipboard
)
263 bool csDiagramClipboard::OnStartCopy(wxDiagram
* diagramTo
)
265 // Do nothing if copying to the clipboard
266 if (diagramTo
== this)
269 // Deselect all objects initially.
271 csDiagram
* diagram
= (csDiagram
*) diagramTo
;
272 csDiagramDocument
* doc
= diagram
->GetDocument();
273 ((csDiagramView
*)doc
->GetFirstView())->SelectAll(false);
275 m_currentCmd
= new csDiagramCommand(_T("Paste"), doc
);
280 bool csDiagramClipboard::OnEndCopy(wxDiagram
* diagramTo
)
282 // Do nothing if copying to the clipboard
283 if (diagramTo
== this)
286 csDiagram
* diagram
= (csDiagram
*) diagramTo
;
287 csDiagramDocument
* doc
= diagram
->GetDocument();
291 if (m_currentCmd
->GetStates().GetCount() == 0)
297 doc
->GetCommandProcessor()->Submit(m_currentCmd
);
304 // Use the command framework to add the shapes, if we're copying to a diagram and
305 // not the clipboard.
306 bool csDiagramClipboard::OnAddShape(wxDiagram
* diagramTo
, wxShape
* newShape
, wxDC
* WXUNUSED(dc
))
308 if (diagramTo
== this)
310 diagramTo
->AddShape(newShape
);
314 csDiagram
* diagram
= (csDiagram
*) diagramTo
;
315 /* csDiagramDocument* doc = */ diagram
->GetDocument();
317 if (newShape
->IsKindOf(CLASSINFO(wxLineShape
)))
318 m_currentCmd
->AddState(new csCommandState(ID_CS_ADD_LINE_SELECT
, newShape
, NULL
));
320 m_currentCmd
->AddState(new csCommandState(ID_CS_ADD_SHAPE_SELECT
, newShape
, NULL
));