void ExplainCanvas::SaveAsImage(const wxString &fileName, wxBitmapType imageType) { if (GetDiagram()->GetCount() == 0) { wxMessageBox(_("Nothing to be saved!"), _("Save As an image"), wxOK | wxICON_INFORMATION); return; } int width = 0, height = 0; GetVirtualSize(&width, &height); /* * Create the bitmap from the Explain window */ wxMemoryDC memDC; wxBitmap tempBitmap(width, height); memDC.SelectObject(tempBitmap); memDC.Clear(); // Draw the diagram on the bitmap (Memory Device Context) GetDiagram()->Redraw(memDC); memDC.SelectObject(wxNullBitmap); if (!tempBitmap.SaveFile(fileName, imageType)) { wxLogError(_("Could not write file \"%s\": error code %d."), fileName.c_str(), wxSysErrorCode()); } }
void wxShapeCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) { wxPaintDC dc(this); PrepareDC(dc); dc.SetBackground(wxBrush(GetBackgroundColour(), wxSOLID)); dc.Clear(); if (GetDiagram()) GetDiagram()->Redraw(dc); }
void csCanvas::OnEndDragLeft(double x, double y, int WXUNUSED(keys)) { ReleaseMouse(); wxClientDC dc(this); PrepareDC(dc); // Select all images within the rectangle float min_x, max_x, min_y, max_y; min_x = wxMin(x, sg_initialX); max_x = wxMax(x, sg_initialX); min_y = wxMin(y, sg_initialY); max_y = wxMax(y, sg_initialY); wxObjectList::compatibility_iterator node = GetDiagram()->GetShapeList()->GetFirst(); while (node) { wxShape *shape = (wxShape *)node->GetData(); if (shape->GetParent() == NULL && !shape->IsKindOf(CLASSINFO(wxControlPoint))) { float image_x = shape->GetX(); float image_y = shape->GetY(); if (image_x >= min_x && image_x <= max_x && image_y >= min_y && image_y <= max_y) { shape->Select(true, &dc); GetView()->SelectShape(shape, true); } } node = node->GetNext(); } }
//******************************************************************************* int CBCGPDiagramView::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CView::OnCreate(lpCreateStruct) == -1) return -1; m_pWndDiagramCtrl = CreateDiagram (); if (m_pWndDiagramCtrl == NULL) { TRACE0("CBCGPDiagramView::OnCreate: Diagram control is not created\n"); return -1; } ASSERT_VALID (m_pWndDiagramCtrl); ASSERT (m_pWndDiagramCtrl->IsKindOf (RUNTIME_CLASS (CBCGPDiagramVisualContainerCtrl))); if (!m_pWndDiagramCtrl->Create (CBCGPRect(), this, ID_Diagram_CTRL)) { TRACE0("CBCGPDiagramView::OnCreate: cannot create Diagram control\n"); return -1; } CBCGPDiagramVisualContainer* pDiagram = GetDiagram(); if (pDiagram != NULL) { pDiagram->EnableScrollBars(); } return 0; }
ExplainCanvas::ExplainCanvas(wxWindow *parent) : wxShapeCanvas(parent) { SetDiagram(new wxDiagram); GetDiagram()->SetCanvas(this); SetBackgroundColour(*wxWHITE); popup = NULL; }
void wxShapeCanvas::OnPaint(wxPaintEvent &WXUNUSED(event)) { #if OGL_USE_BUFFERED_PAINT RecreateBuffer(); wxBufferedPaintDC dc(this, m_bufferBitmap); #else wxPaintDC dc(this); #endif PrepareDC(dc); DrawBackground(dc, true); if (GetDiagram()) GetDiagram()->Redraw(dc); // Necessary or it unscales again if there's a zoom level dc.SetUserScale(1.0, 1.0); }
void wxShapeCanvas::OnMouseEvent(wxMouseEvent& event) { wxClientDC dc(this); PrepareDC(dc); wxPoint logPos(event.GetLogicalPosition(dc)); double x, y; x = (double) logPos.x; y = (double) logPos.y; int keys = 0; if (event.ShiftDown()) keys = keys | KEY_SHIFT; if (event.ControlDown()) keys = keys | KEY_CTRL; bool dragging = event.Dragging(); // Check if we're within the tolerance for mouse movements. // If we're very close to the position we started dragging // from, this may not be an intentional drag at all. if (dragging) { int dx = abs(dc.LogicalToDeviceX((long) (x - m_firstDragX))); int dy = abs(dc.LogicalToDeviceY((long) (y - m_firstDragY))); if (m_checkTolerance && (dx <= GetDiagram()->GetMouseTolerance()) && (dy <= GetDiagram()->GetMouseTolerance())) { return; } else // If we've ignored the tolerance once, then ALWAYS ignore // tolerance in this drag, even if we come back within // the tolerance range. m_checkTolerance = false; } // Dragging - note that the effect of dragging is left entirely up // to the object, so no movement is done unless explicitly done by // object. if (dragging && m_draggedShape && m_dragState == StartDraggingLeft) { m_dragState = ContinueDraggingLeft; // If the object isn't m_draggable, transfer message to canvas if (m_draggedShape->Draggable()) m_draggedShape->GetEventHandler()->OnBeginDragLeft((double)x, (double)y, keys, m_draggedAttachment); else { m_draggedShape = NULL; OnBeginDragLeft((double)x, (double)y, keys); } m_oldDragX = x; m_oldDragY = y; } else if (dragging && m_draggedShape && m_dragState == ContinueDraggingLeft) { // Continue dragging m_draggedShape->GetEventHandler()->OnDragLeft(false, m_oldDragX, m_oldDragY, keys, m_draggedAttachment); m_draggedShape->GetEventHandler()->OnDragLeft(true, (double)x, (double)y, keys, m_draggedAttachment); m_oldDragX = x; m_oldDragY = y; } else if (event.LeftUp() && m_draggedShape && m_dragState == ContinueDraggingLeft) { m_dragState = NoDragging; m_checkTolerance = true; m_draggedShape->GetEventHandler()->OnDragLeft(false, m_oldDragX, m_oldDragY, keys, m_draggedAttachment); m_draggedShape->GetEventHandler()->OnEndDragLeft((double)x, (double)y, keys, m_draggedAttachment); m_draggedShape = NULL; } else if (dragging && m_draggedShape && m_dragState == StartDraggingRight) { m_dragState = ContinueDraggingRight; if (m_draggedShape->Draggable()) m_draggedShape->GetEventHandler()->OnBeginDragRight((double)x, (double)y, keys, m_draggedAttachment); else { m_draggedShape = NULL; OnBeginDragRight((double)x, (double)y, keys); } m_oldDragX = x; m_oldDragY = y; } else if (dragging && m_draggedShape && m_dragState == ContinueDraggingRight) { // Continue dragging m_draggedShape->GetEventHandler()->OnDragRight(false, m_oldDragX, m_oldDragY, keys, m_draggedAttachment); m_draggedShape->GetEventHandler()->OnDragRight(true, (double)x, (double)y, keys, m_draggedAttachment); m_oldDragX = x; m_oldDragY = y; } else if (event.RightUp() && m_draggedShape && m_dragState == ContinueDraggingRight) { m_dragState = NoDragging; m_checkTolerance = true; m_draggedShape->GetEventHandler()->OnDragRight(false, m_oldDragX, m_oldDragY, keys, m_draggedAttachment); m_draggedShape->GetEventHandler()->OnEndDragRight((double)x, (double)y, keys, m_draggedAttachment); m_draggedShape = NULL; } // All following events sent to canvas, not object else if (dragging && !m_draggedShape && m_dragState == StartDraggingLeft) { m_dragState = ContinueDraggingLeft; OnBeginDragLeft((double)x, (double)y, keys); m_oldDragX = x; m_oldDragY = y; } else if (dragging && !m_draggedShape && m_dragState == ContinueDraggingLeft) { // Continue dragging OnDragLeft(false, m_oldDragX, m_oldDragY, keys); OnDragLeft(true, (double)x, (double)y, keys); m_oldDragX = x; m_oldDragY = y; } else if (event.LeftUp() && !m_draggedShape && m_dragState == ContinueDraggingLeft) { m_dragState = NoDragging; m_checkTolerance = true; OnDragLeft(false, m_oldDragX, m_oldDragY, keys); OnEndDragLeft((double)x, (double)y, keys); m_draggedShape = NULL; } else if (dragging && !m_draggedShape && m_dragState == StartDraggingRight) { m_dragState = ContinueDraggingRight; OnBeginDragRight((double)x, (double)y, keys); m_oldDragX = x; m_oldDragY = y; } else if (dragging && !m_draggedShape && m_dragState == ContinueDraggingRight) { // Continue dragging OnDragRight(false, m_oldDragX, m_oldDragY, keys); OnDragRight(true, (double)x, (double)y, keys); m_oldDragX = x; m_oldDragY = y; } else if (event.RightUp() && !m_draggedShape && m_dragState == ContinueDraggingRight) { m_dragState = NoDragging; m_checkTolerance = true; OnDragRight(false, m_oldDragX, m_oldDragY, keys); OnEndDragRight((double)x, (double)y, keys); m_draggedShape = NULL; } // Non-dragging events else if (event.IsButton()) { m_checkTolerance = true; // Find the nearest object int attachment = 0; wxShape *nearest_object = FindShape(x, y, &attachment); if (nearest_object) // Object event { if (event.LeftDown()) { m_draggedShape = nearest_object; m_draggedAttachment = attachment; m_dragState = StartDraggingLeft; m_firstDragX = x; m_firstDragY = y; } else if (event.LeftUp()) { // N.B. Only register a click if the same object was // identified for down *and* up. if (nearest_object == m_draggedShape) nearest_object->GetEventHandler()->OnLeftClick((double)x, (double)y, keys, attachment); m_draggedShape = NULL; m_dragState = NoDragging; } else if (event.LeftDClick()) { nearest_object->GetEventHandler()->OnLeftDoubleClick((double)x, (double)y, keys, attachment); m_draggedShape = NULL; m_dragState = NoDragging; } else if (event.RightDown()) { m_draggedShape = nearest_object; m_draggedAttachment = attachment; m_dragState = StartDraggingRight; m_firstDragX = x; m_firstDragY = y; } else if (event.RightUp()) { if (nearest_object == m_draggedShape) nearest_object->GetEventHandler()->OnRightClick((double)x, (double)y, keys, attachment); m_draggedShape = NULL; m_dragState = NoDragging; } } else // Canvas event (no nearest object) { if (event.LeftDown()) { m_draggedShape = NULL; m_dragState = StartDraggingLeft; m_firstDragX = x; m_firstDragY = y; } else if (event.LeftUp()) { OnLeftClick((double)x, (double)y, keys); m_draggedShape = NULL; m_dragState = NoDragging; } else if (event.RightDown()) { m_draggedShape = NULL; m_dragState = StartDraggingRight; m_firstDragX = x; m_firstDragY = y; } else if (event.RightUp()) { OnRightClick((double)x, (double)y, keys); m_draggedShape = NULL; m_dragState = NoDragging; } } } }
void wxShapeCanvas::Snap(double *x, double *y) { GetDiagram()->Snap(x, y); }
void wxShapeCanvas::Redraw(wxDC& dc) { GetDiagram()->Redraw(dc); }
bool wxShapeCanvas::GetQuickEditMode() { return GetDiagram()->GetQuickEditMode(); }
void wxShapeCanvas::RemoveShape(wxShape *object) { GetDiagram()->RemoveShape(object); }
void wxShapeCanvas::InsertShape(wxShape *object) { GetDiagram()->InsertShape(object); }
void wxShapeCanvas::AddShape(wxShape *object, wxShape *addAfter) { GetDiagram()->AddShape(object, addAfter); }
wxShape *wxShapeCanvas::FindShape(double x, double y, int *attachment, wxClassInfo *info, wxShape *notObject, wxClassInfo *notinfo) //wxShape *wxShapeCanvas::FindShape(double x, double y, int *attachment, wxClassInfo *info, wxShape *notObject) { double nearest = 100000.0; int nearest_attachment = 0; wxShape *nearest_object = NULL; // Go backward through the object list, since we want: // (a) to have the control points drawn LAST to overlay // the other objects // (b) to find the control points FIRST if they exist wxObjectList::compatibility_iterator current = GetDiagram()->GetShapeList()->GetLast(); while (current) { wxShape *object = (wxShape *)current->GetData(); double dist; int temp_attachment; // First pass for lines, which might be inside a container, so we // want lines to take priority over containers. This first loop // could fail if we clickout side a line, so then we'll // try other shapes. if (object->IsShown() && object->IsKindOf(CLASSINFO(wxLineShape)) && object->HitTest(x, y, &temp_attachment, &dist) && ((info == NULL) || object->IsKindOf(info)) && ((notinfo == NULL) || !object->IsKindOf(notinfo)) && (!notObject || !notObject->HasDescendant(object))) { // A line is trickier to spot than a normal object. // For a line, since it's the diagonal of the box // we use for the hit test, we may have several // lines in the box and therefore we need to be able // to specify the nearest point to the centre of the line // as our hit criterion, to give the user some room for // manouevre. if (dist < nearest) { nearest = dist; nearest_object = object; nearest_attachment = temp_attachment; } } if (current) current = current->GetPrevious(); } current = GetDiagram()->GetShapeList()->GetLast(); while (current) { wxShape *object = (wxShape *)current->GetData(); double dist; int temp_attachment; // On second pass, only ever consider non-composites or divisions. If children want to pass // up control to the composite, that's up to them. if (object->IsShown() && (object->IsKindOf(CLASSINFO(wxDivisionShape)) || !object->IsKindOf(CLASSINFO(wxCompositeShape))) && object->HitTest(x, y, &temp_attachment, &dist) && ((info == NULL) || object->IsKindOf(info)) && (!notObject || !notObject->HasDescendant(object))) { if (!object->IsKindOf(CLASSINFO(wxLineShape))) { // If we've hit a container, and we have already found a line in the // first pass, then ignore the container in case the line is in the container. // Check for division in case line straddles divisions (i.e. is not wholly contained). if (!nearest_object || !(object->IsKindOf(CLASSINFO(wxDivisionShape)) || WhollyContains(object, nearest_object))) { nearest_object = object; nearest_attachment = temp_attachment; current = GetDiagram()->GetShapeList()->GetFirst()->GetPrevious(); // finish loop } } } if (current) current = current->GetPrevious(); } *attachment = nearest_attachment; return nearest_object; }
void ExplainCanvas::SetExplainString(const wxString &str) { Clear(); ExplainShape *last = 0; int maxLevel = 0; wxStringTokenizer lines(str, wxT("\n")); while (lines.HasMoreTokens()) { wxString tmp = lines.GetNextToken(); wxString line = tmp.Strip(wxString::both); int braceCount = 0; do { const wxChar *cp = line.c_str(); while (*cp) { if (*cp == '(') braceCount++; else if (*cp == ')') braceCount--; cp++; } if (braceCount > 0) { wxString tmp = lines.GetNextToken(); line += wxT(" ") + tmp.Strip(wxString::both); braceCount = 0; } else break; } while (lines.HasMoreTokens()); long level = (tmp.Length() - line.Length() + 4) / 6; if (last) { if (level) { if (line.Left(4) == wxT("-> ")) line = line.Mid(4); else { last->SetCondition(line); continue; } } while (last && level <= last->GetLevel()) last = last->GetUpper(); } ExplainShape *s = ExplainShape::Create(level, last, line); if (!s) continue; s->SetCanvas(this); InsertShape(s); s->Show(true); if (level > maxLevel) maxLevel = level; if (!last) rootShape = s; last = s; } int x0 = (int)(rootShape->GetWidth() * 3); int y0 = (int)(rootShape->GetHeight() * 3 / 2); int xoffs = (int)(rootShape->GetWidth() * 3); int yoffs = (int)(rootShape->GetHeight() * 5 / 4); wxNode *current = GetDiagram()->GetShapeList()->GetFirst(); while (current) { ExplainShape *s = (ExplainShape *)current->GetData(); if (!s->totalShapes) s->totalShapes = 1; if (s->GetUpper()) s->GetUpper()->totalShapes += s->totalShapes; current = current->GetNext(); } current = GetDiagram()->GetShapeList()->GetLast(); while (current) { ExplainShape *s = (ExplainShape *)current->GetData(); s->SetX(y0 + (maxLevel - s->GetLevel()) * xoffs); ExplainShape *upper = s->GetUpper(); if (upper) { s->SetY(upper->GetY() + upper->usedShapes * yoffs); upper->usedShapes += s->totalShapes; wxLineShape *l = new ExplainLine(s, upper); l->Show(true); AddShape(l); } else { s->SetY(y0); } current = current->GetPrevious(); } #define PIXPERUNIT 20 int w = (maxLevel * xoffs + x0 * 2 + PIXPERUNIT - 1) / PIXPERUNIT; int h = (rootShape->totalShapes * yoffs + y0 * 2 + PIXPERUNIT - 1) / PIXPERUNIT; SetScrollbars(PIXPERUNIT, PIXPERUNIT, w, h); }
void ExplainCanvas::Clear() { GetDiagram()->DeleteAllShapes(); }