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