git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@1640 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
		
			
				
	
	
		
			319 lines
		
	
	
		
			8.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			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;
 | 
						|
}
 | 
						|
 | 
						|
 |