wxWidgets/utils/ogl/samples/studio/csprint.cpp
1999-02-07 23:56:40 +00:00

319 lines
8.7 KiB
C++

/////////////////////////////////////////////////////////////////////////////
// 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 (mf)
{
// Copy the metafile to the clipboard
// Allow a small margin
bool success = mf->SetClipboard((int)(mfDC.MaxX() + 15), (int)(mfDC.MaxY() + 15));
}
// 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;
}