]> git.saurik.com Git - wxWidgets.git/blame - contrib/samples/ogl/studio/csprint.cpp
Elliptic arc fix for getting bounds
[wxWidgets.git] / contrib / samples / ogl / studio / csprint.cpp
CommitLineData
1fc25a89
JS
1/////////////////////////////////////////////////////////////////////////////
2// Name: csprint.cpp
3// Purpose: Printing and clipboard functionality
4// Author: Julian Smart
5// Modified by:
6// Created: 12/07/98
7// RCS-ID: $Id$
8// Copyright: (c) Julian Smart
2ba06d5a 9// Licence: wxWindows licence
1fc25a89
JS
10/////////////////////////////////////////////////////////////////////////////
11
12#ifdef __GNUG__
13// #pragma implementation
14#endif
15
16// For compilers that support precompilation, includes "wx.h".
92a19c2e 17#include "wx/wxprec.h"
1fc25a89
JS
18
19#ifdef __BORLANDC__
20#pragma hdrstop
21#endif
22
23#ifndef WX_PRECOMP
24#include <wx/wx.h>
25#endif
26
7c9955d1
JS
27#include <wx/deprecated/setup.h>
28#include <wx/deprecated/wxexpr.h>
29
1fc25a89
JS
30#include <wx/clipbrd.h>
31
32#ifdef __WXMSW__
33#include <wx/metafile.h>
34#endif
35
36#include "studio.h"
37#include "doc.h"
38#include "shapes.h"
39#include "view.h"
40
41IMPLEMENT_DYNAMIC_CLASS(wxDiagramClipboard, wxDiagram)
42
43// Copy selection
44bool wxDiagramClipboard::Copy(wxDiagram* diagram)
45{
46 DeleteAllShapes();
47
2ba06d5a 48 return DoCopy(diagram, this, false, NULL);
1fc25a89
JS
49}
50
51// Copy contents to the diagram, with new ids.
52
53bool wxDiagramClipboard::Paste(wxDiagram* diagram, wxDC* dc, int offsetX, int offsetY)
54{
2ba06d5a 55 return DoCopy(this, diagram, true, dc, offsetX, offsetY);
1fc25a89
JS
56}
57
58// Universal copy function (to or from clipboard).
59// TODO:
60// Note that this only works for non-composites so far (nested shapes
61// don't have their old-to-new object mappings stored).
62// Also, lines don't yet get their attachment points moved to the new offset position
63// if they have more than 2 points.
64bool wxDiagramClipboard::DoCopy(wxDiagram* diagramFrom, wxDiagram* diagramTo, bool newIds,
65 wxDC* dc, int offsetX, int offsetY)
66{
67 OnStartCopy(diagramTo);
68
69 wxHashTable mapping(wxKEY_INTEGER);
70
71 // First copy all node shapes.
72 wxList* shapeList = diagramFrom->GetShapeList();
5e0dbc8d 73 wxObjectList::compatibility_iterator node = shapeList->GetFirst();
1fc25a89
JS
74 while (node)
75 {
8552e6f0 76 wxShape* shape = (wxShape*) node->GetData();
1fc25a89
JS
77 if (((diagramFrom == this) || shape->Selected()) && !shape->IsKindOf(CLASSINFO(wxLineShape)))
78 {
79 wxShape* newShape = shape->CreateNewCopy();
80 newShape->GetLines().Clear();
81 if (newIds)
82 {
83 newShape->AssignNewIds();
84 }
85 mapping.Put((long) shape, (wxObject*) newShape);
86
87 newShape->SetX(newShape->GetX() + offsetX);
88 newShape->SetY(newShape->GetY() + offsetY);
89
90 OnAddShape(diagramTo, newShape, dc);
91
92 }
8552e6f0 93 node = node->GetNext();
1fc25a89
JS
94 }
95
8552e6f0 96 node = shapeList->GetFirst();
1fc25a89
JS
97 while (node)
98 {
8552e6f0 99 wxShape* shape = (wxShape*) node->GetData();
1fc25a89
JS
100 if (((diagramFrom == this) || shape->Selected()) && shape->IsKindOf(CLASSINFO(wxLineShape)))
101 {
102 wxLineShape* lineShape = (wxLineShape*) shape;
103 // Only copy a line if its ends are selected too.
104 if ((diagramFrom == this) || (lineShape->GetTo()->Selected() && lineShape->GetFrom()->Selected()))
105 {
106 wxLineShape* newShape = (wxLineShape*) shape->CreateNewCopy();
107 mapping.Put((long) shape, (wxObject*) newShape);
108
109 if (newIds)
110 newShape->AssignNewIds();
111
112 wxShape* fromShape = (wxShape*) mapping.Get((long) lineShape->GetFrom());
113 wxShape* toShape = (wxShape*) mapping.Get((long) lineShape->GetTo());
114
1484b5cc
VS
115 wxASSERT_MSG( (fromShape != NULL), _T("Could not find 'from' shape"));
116 wxASSERT_MSG( (toShape != NULL), _T("Could not find 'to' shape"));
1fc25a89
JS
117
118 fromShape->AddLine(newShape, toShape, newShape->GetAttachmentFrom(),
119 newShape->GetAttachmentTo());
120
121 OnAddShape(diagramTo, newShape, dc);
122
123 }
124 }
8552e6f0 125 node = node->GetNext();
1fc25a89
JS
126 }
127
128 // Now make sure line ordering is correct
8552e6f0 129 node = shapeList->GetFirst();
1fc25a89
JS
130 while (node)
131 {
8552e6f0 132 wxShape* shape = (wxShape*) node->GetData();
1fc25a89
JS
133 if (((diagramFrom == this) || shape->Selected()) && !shape->IsKindOf(CLASSINFO(wxLineShape)))
134 {
135 wxShape* newShape = (wxShape*) mapping.Get((long) shape);
136
137 // Make a list of all the new lines, in the same order as the old lines.
138 // Then apply the list of new lines to the shape.
139 wxList newLines;
5e0dbc8d 140 wxObjectList::compatibility_iterator lineNode = shape->GetLines().GetFirst();
1fc25a89
JS
141 while (lineNode)
142 {
8552e6f0 143 wxLineShape* lineShape = (wxLineShape*) lineNode->GetData();
1fc25a89
JS
144 if ((diagramFrom == this) || (lineShape->GetTo()->Selected() && lineShape->GetFrom()->Selected()))
145 {
146 wxLineShape* newLineShape = (wxLineShape*) mapping.Get((long) lineShape);
147
1484b5cc 148 wxASSERT_MSG( (newLineShape != NULL), _T("Could not find new line shape"));
1fc25a89
JS
149
150 newLines.Append(newLineShape);
151 }
152
8552e6f0 153 lineNode = lineNode->GetNext();
1fc25a89
JS
154 }
155
8552e6f0 156 if (newLines.GetCount() > 0)
1fc25a89
JS
157 newShape->ApplyAttachmentOrdering(newLines);
158 }
8552e6f0 159 node = node->GetNext();
1fc25a89
JS
160 }
161
162 OnEndCopy(diagramTo);
163
2ba06d5a 164 return true;
1fc25a89
JS
165}
166
167#ifdef __WXMSW__
168// Draw contents to a Windows metafile device context and a bitmap, and copy
169// these to the Windows clipboard
170bool wxDiagramClipboard::CopyToClipboard(double scale)
171{
93210c68 172#if wxUSE_METAFILE
1fc25a89
JS
173 // Make a metafile DC
174 wxMetaFileDC mfDC;
175 if (mfDC.Ok())
176 {
177 mfDC.SetUserScale(scale, scale);
178
179 // Draw on metafile DC
180 Redraw(mfDC);
181
b1c1e25b
JS
182 // int printWidth = mfDC.MaxX() - mfDC.MinX();
183 // int printHeight = mfDC.MaxY() - mfDC.MinY();
1fc25a89
JS
184 int maxX = (int)mfDC.MaxX();
185 int maxY = (int)mfDC.MaxY();
186 wxMetaFile *mf = mfDC.Close();
187
188 // Set to a bitmap memory DC
189 wxBitmap *newBitmap = new wxBitmap((int)(maxX + 10), (int)(maxY + 10));
190 if (!newBitmap->Ok())
191 {
192 delete newBitmap;
193
42c37dec
VS
194 wxChar buf[200];
195 wxSprintf(buf, _T("Sorry, could not allocate clipboard bitmap (%dx%d)"), (maxX+10), (maxY+10));
1484b5cc 196 wxMessageBox(buf, _T("Clipboard copy problem"));
2ba06d5a 197 return false;
1fc25a89
JS
198 }
199
200 wxMemoryDC memDC;
201 memDC.SelectObject(*newBitmap);
202 memDC.Clear();
203
204 // Now draw on memory bitmap DC
205 Redraw(memDC);
206
207 memDC.SelectObject(wxNullBitmap);
208
209 // Open clipboard and set the data
210 if (wxOpenClipboard())
211 {
212 wxEmptyClipboard();
213
214 // Copy the bitmap to the clipboard
215 wxSetClipboardData(wxDF_BITMAP, newBitmap, 0, 0);
216
217#if 0 // TODO: replace this code (wxEnhMetaFile doesn't have SetClipboard)
218 if (mf)
219 {
220 // Copy the metafile to the clipboard
221 // Allow a small margin
222 bool success = mf->SetClipboard((int)(mfDC.MaxX() + 15), (int)(mfDC.MaxY() + 15));
223 }
224#endif
225
226 // Close clipboard
227 wxCloseClipboard();
228 }
229
230 delete newBitmap;
231 delete mf;
232
233 }
93210c68
JS
234 return true;
235#else
236 wxMessageBox("wxUSE_METAFILE in build required to use Clipboard", _T("Clipboard copy problem"));
237 return false;
238#endif
1fc25a89
JS
239}
240#endif
241 // __WXMSW__
242
243// Override this to e.g. have the shape added through a Do/Undo command system.
244// By default, we'll just add it directly to the destination diagram.
245bool wxDiagramClipboard::OnAddShape(wxDiagram* diagramTo, wxShape* newShape, wxDC* dc)
246{
247 diagramTo->AddShape(newShape);
248
249 if (dc && (diagramTo != this))
250 {
2ba06d5a 251 newShape->Select(true, dc);
1fc25a89
JS
252 }
253
2ba06d5a 254 return true;
1fc25a89
JS
255}
256
257/*
258 * csDiagramClipboard
259 */
260
261IMPLEMENT_DYNAMIC_CLASS(csDiagramClipboard, wxDiagramClipboard)
262
263// Start/end copying
264bool csDiagramClipboard::OnStartCopy(wxDiagram* diagramTo)
265{
266 // Do nothing if copying to the clipboard
267 if (diagramTo == this)
2ba06d5a 268 return true;
1fc25a89
JS
269
270 // Deselect all objects initially.
271
272 csDiagram* diagram = (csDiagram*) diagramTo;
273 csDiagramDocument* doc = diagram->GetDocument();
2ba06d5a 274 ((csDiagramView*)doc->GetFirstView())->SelectAll(false);
1fc25a89 275
1484b5cc 276 m_currentCmd = new csDiagramCommand(_T("Paste"), doc);
1fc25a89 277
2ba06d5a 278 return true;
1fc25a89
JS
279}
280
281bool csDiagramClipboard::OnEndCopy(wxDiagram* diagramTo)
282{
283 // Do nothing if copying to the clipboard
284 if (diagramTo == this)
2ba06d5a 285 return true;
1fc25a89
JS
286
287 csDiagram* diagram = (csDiagram*) diagramTo;
288 csDiagramDocument* doc = diagram->GetDocument();
289
290 if (m_currentCmd)
291 {
8552e6f0 292 if (m_currentCmd->GetStates().GetCount() == 0)
1fc25a89
JS
293 {
294 delete m_currentCmd;
295 }
296 else
297 {
298 doc->GetCommandProcessor()->Submit(m_currentCmd);
299 m_currentCmd = NULL;
300 }
301 }
2ba06d5a 302 return true;
1fc25a89
JS
303}
304
305// Use the command framework to add the shapes, if we're copying to a diagram and
306// not the clipboard.
1484b5cc 307bool csDiagramClipboard::OnAddShape(wxDiagram* diagramTo, wxShape* newShape, wxDC* WXUNUSED(dc))
1fc25a89
JS
308{
309 if (diagramTo == this)
310 {
311 diagramTo->AddShape(newShape);
312 }
313 else
314 {
315 csDiagram* diagram = (csDiagram*) diagramTo;
1484b5cc 316 /* csDiagramDocument* doc = */ diagram->GetDocument();
1fc25a89
JS
317
318 if (newShape->IsKindOf(CLASSINFO(wxLineShape)))
319 m_currentCmd->AddState(new csCommandState(ID_CS_ADD_LINE_SELECT, newShape, NULL));
320 else
321 m_currentCmd->AddState(new csCommandState(ID_CS_ADD_SHAPE_SELECT, newShape, NULL));
322 }
323
2ba06d5a 324 return true;
1fc25a89
JS
325}
326
327