--- /dev/null
+/////////////////////////////////////////////////////////////////////////////
+// Name: csprint.cpp
+// Purpose: Printing and clipboard functionality
+// Author: Julian Smart
+// Modified by:
+// Created: 12/07/98
+// RCS-ID: $Id$
+// Copyright: (c) Julian Smart
+// Licence: wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#ifdef __GNUG__
+// #pragma implementation
+#endif
+
+// For compilers that support precompilation, includes "wx.h".
+#include <wx/wxprec.h>
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#ifndef WX_PRECOMP
+#include <wx/wx.h>
+#endif
+
+#include <wx/wxexpr.h>
+#include <wx/clipbrd.h>
+
+#ifdef __WXMSW__
+#include <wx/metafile.h>
+#endif
+
+#include "studio.h"
+#include "doc.h"
+#include "shapes.h"
+#include "view.h"
+
+IMPLEMENT_DYNAMIC_CLASS(wxDiagramClipboard, wxDiagram)
+
+// Copy selection
+bool wxDiagramClipboard::Copy(wxDiagram* diagram)
+{
+ DeleteAllShapes();
+
+ return DoCopy(diagram, this, FALSE, NULL);
+}
+
+// Copy contents to the diagram, with new ids.
+
+bool wxDiagramClipboard::Paste(wxDiagram* diagram, wxDC* dc, int offsetX, int offsetY)
+{
+ return DoCopy(this, diagram, TRUE, dc, offsetX, offsetY);
+}
+
+// Universal copy function (to or from clipboard).
+// TODO:
+// Note that this only works for non-composites so far (nested shapes
+// don't have their old-to-new object mappings stored).
+// Also, lines don't yet get their attachment points moved to the new offset position
+// if they have more than 2 points.
+bool wxDiagramClipboard::DoCopy(wxDiagram* diagramFrom, wxDiagram* diagramTo, bool newIds,
+ wxDC* dc, int offsetX, int offsetY)
+{
+ OnStartCopy(diagramTo);
+
+ wxHashTable mapping(wxKEY_INTEGER);
+
+ // First copy all node shapes.
+ wxList* shapeList = diagramFrom->GetShapeList();
+ wxNode* node = shapeList->First();
+ while (node)
+ {
+ wxShape* shape = (wxShape*) node->Data();
+ if (((diagramFrom == this) || shape->Selected()) && !shape->IsKindOf(CLASSINFO(wxLineShape)))
+ {
+ wxShape* newShape = shape->CreateNewCopy();
+ newShape->GetLines().Clear();
+ if (newIds)
+ {
+ newShape->AssignNewIds();
+ }
+ mapping.Put((long) shape, (wxObject*) newShape);
+
+ newShape->SetX(newShape->GetX() + offsetX);
+ newShape->SetY(newShape->GetY() + offsetY);
+
+ OnAddShape(diagramTo, newShape, dc);
+
+ }
+ node = node->Next();
+ }
+
+ node = shapeList->First();
+ while (node)
+ {
+ wxShape* shape = (wxShape*) node->Data();
+ if (((diagramFrom == this) || shape->Selected()) && shape->IsKindOf(CLASSINFO(wxLineShape)))
+ {
+ wxLineShape* lineShape = (wxLineShape*) shape;
+ // Only copy a line if its ends are selected too.
+ if ((diagramFrom == this) || (lineShape->GetTo()->Selected() && lineShape->GetFrom()->Selected()))
+ {
+ wxLineShape* newShape = (wxLineShape*) shape->CreateNewCopy();
+ mapping.Put((long) shape, (wxObject*) newShape);
+
+ if (newIds)
+ newShape->AssignNewIds();
+
+ wxShape* fromShape = (wxShape*) mapping.Get((long) lineShape->GetFrom());
+ wxShape* toShape = (wxShape*) mapping.Get((long) lineShape->GetTo());
+
+ wxASSERT_MSG( (fromShape != NULL), "Could not find 'from' shape");
+ wxASSERT_MSG( (toShape != NULL), "Could not find 'to' shape");
+
+ fromShape->AddLine(newShape, toShape, newShape->GetAttachmentFrom(),
+ newShape->GetAttachmentTo());
+
+ OnAddShape(diagramTo, newShape, dc);
+
+ }
+ }
+ node = node->Next();
+ }
+
+ // Now make sure line ordering is correct
+ node = shapeList->First();
+ while (node)
+ {
+ wxShape* shape = (wxShape*) node->Data();
+ if (((diagramFrom == this) || shape->Selected()) && !shape->IsKindOf(CLASSINFO(wxLineShape)))
+ {
+ wxShape* newShape = (wxShape*) mapping.Get((long) shape);
+
+ // Make a list of all the new lines, in the same order as the old lines.
+ // Then apply the list of new lines to the shape.
+ wxList newLines;
+ wxNode* lineNode = shape->GetLines().First();
+ while (lineNode)
+ {
+ wxLineShape* lineShape = (wxLineShape*) lineNode->Data();
+ if ((diagramFrom == this) || (lineShape->GetTo()->Selected() && lineShape->GetFrom()->Selected()))
+ {
+ wxLineShape* newLineShape = (wxLineShape*) mapping.Get((long) lineShape);
+
+ wxASSERT_MSG( (newLineShape != NULL), "Could not find new line shape");
+
+ newLines.Append(newLineShape);
+ }
+
+ lineNode = lineNode->Next();
+ }
+
+ if (newLines.Number() > 0)
+ newShape->ApplyAttachmentOrdering(newLines);
+ }
+ node = node->Next();
+ }
+
+ OnEndCopy(diagramTo);
+
+ return TRUE;
+}
+
+#ifdef __WXMSW__
+// Draw contents to a Windows metafile device context and a bitmap, and copy
+// these to the Windows clipboard
+bool wxDiagramClipboard::CopyToClipboard(double scale)
+{
+ // Make a metafile DC
+ wxMetaFileDC mfDC;
+ if (mfDC.Ok())
+ {
+ mfDC.SetUserScale(scale, scale);
+
+ // Draw on metafile DC
+ Redraw(mfDC);
+
+ int printWidth = mfDC.MaxX() - mfDC.MinX();
+ int printHeight = mfDC.MaxY() - mfDC.MinY();
+ int maxX = (int)mfDC.MaxX();
+ int maxY = (int)mfDC.MaxY();
+ wxMetaFile *mf = mfDC.Close();
+
+ // Set to a bitmap memory DC
+ wxBitmap *newBitmap = new wxBitmap((int)(maxX + 10), (int)(maxY + 10));
+ if (!newBitmap->Ok())
+ {
+ delete newBitmap;
+
+ char buf[200];
+ sprintf(buf, "Sorry, could not allocate clipboard bitmap (%dx%d)", (maxX+10), (maxY+10));
+ wxMessageBox(buf, "Clipboard copy problem");
+ return FALSE;
+ }
+
+ wxMemoryDC memDC;
+ memDC.SelectObject(*newBitmap);
+ memDC.Clear();
+
+ // Now draw on memory bitmap DC
+ Redraw(memDC);
+
+ memDC.SelectObject(wxNullBitmap);
+
+ // Open clipboard and set the data
+ if (wxOpenClipboard())
+ {
+ wxEmptyClipboard();
+
+ // Copy the bitmap to the clipboard
+ wxSetClipboardData(wxDF_BITMAP, newBitmap, 0, 0);
+
+#if 0 // TODO: replace this code (wxEnhMetaFile doesn't have SetClipboard)
+ if (mf)
+ {
+ // Copy the metafile to the clipboard
+ // Allow a small margin
+ bool success = mf->SetClipboard((int)(mfDC.MaxX() + 15), (int)(mfDC.MaxY() + 15));
+ }
+#endif
+
+ // Close clipboard
+ wxCloseClipboard();
+ }
+
+ delete newBitmap;
+ delete mf;
+
+ }
+ return TRUE;
+}
+#endif
+ // __WXMSW__
+
+// Override this to e.g. have the shape added through a Do/Undo command system.
+// By default, we'll just add it directly to the destination diagram.
+bool wxDiagramClipboard::OnAddShape(wxDiagram* diagramTo, wxShape* newShape, wxDC* dc)
+{
+ diagramTo->AddShape(newShape);
+
+ if (dc && (diagramTo != this))
+ {
+ newShape->Select(TRUE, dc);
+ }
+
+ return TRUE;
+}
+
+/*
+ * csDiagramClipboard
+ */
+
+IMPLEMENT_DYNAMIC_CLASS(csDiagramClipboard, wxDiagramClipboard)
+
+// Start/end copying
+bool csDiagramClipboard::OnStartCopy(wxDiagram* diagramTo)
+{
+ // Do nothing if copying to the clipboard
+ if (diagramTo == this)
+ return TRUE;
+
+ // Deselect all objects initially.
+
+ csDiagram* diagram = (csDiagram*) diagramTo;
+ csDiagramDocument* doc = diagram->GetDocument();
+ ((csDiagramView*)doc->GetFirstView())->SelectAll(FALSE);
+
+ m_currentCmd = new csDiagramCommand("Paste", doc);
+
+ return TRUE;
+}
+
+bool csDiagramClipboard::OnEndCopy(wxDiagram* diagramTo)
+{
+ // Do nothing if copying to the clipboard
+ if (diagramTo == this)
+ return TRUE;
+
+ csDiagram* diagram = (csDiagram*) diagramTo;
+ csDiagramDocument* doc = diagram->GetDocument();
+
+ if (m_currentCmd)
+ {
+ if (m_currentCmd->GetStates().Number() == 0)
+ {
+ delete m_currentCmd;
+ }
+ else
+ {
+ doc->GetCommandProcessor()->Submit(m_currentCmd);
+ m_currentCmd = NULL;
+ }
+ }
+ return TRUE;
+}
+
+// Use the command framework to add the shapes, if we're copying to a diagram and
+// not the clipboard.
+bool csDiagramClipboard::OnAddShape(wxDiagram* diagramTo, wxShape* newShape, wxDC* dc)
+{
+ if (diagramTo == this)
+ {
+ diagramTo->AddShape(newShape);
+ }
+ else
+ {
+ csDiagram* diagram = (csDiagram*) diagramTo;
+ csDiagramDocument* doc = diagram->GetDocument();
+
+ if (newShape->IsKindOf(CLASSINFO(wxLineShape)))
+ m_currentCmd->AddState(new csCommandState(ID_CS_ADD_LINE_SELECT, newShape, NULL));
+ else
+ m_currentCmd->AddState(new csCommandState(ID_CS_ADD_SHAPE_SELECT, newShape, NULL));
+ }
+
+ return TRUE;
+}
+
+