#ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "wxTurtleGraphics.h" #include "TextEditor.h" #include #define WX_TURTLEGRAPHICS_CPP 1 using namespace std; #define SCREEN_WIDTH 1 #define SCREEN_HEIGHT 2 #define BACK_GROUND 3 #define IN_SPLITSCREEN 4 #define IN_GRAPHICS_MODE 5 // ---------------------------------------------------------------------------- // Custom Events // ---------------------------------------------------------------------------- /* The edit event */ #if 0 BEGIN_DECLARE_EVENT_TYPES() DECLARE_EVENT_TYPE(wxEVT_EDIT_CUSTOM_COMMAND, 7777) END_DECLARE_EVENT_TYPES() DEFINE_EVENT_TYPE(wxEVT_EDIT_CUSTOM_COMMAND) #define EVT_EDIT_CUSTOM_COMMAND(id, fn) \ DECLARE_EVENT_TABLE_ENTRY( \ wxEVT_EDIT_CUSTOM_COMMAND, id, -2, \ (wxObjectEventFunction)(wxEventFunction)(wxCommandEventFunction)&fn, \ (wxObject *) NULL \ ), #endif /* Used for multithread event handling, as well as for a dummy event otherwise */ BEGIN_DECLARE_EVENT_TYPES() DECLARE_EVENT_TYPE(wxEVT_LOGO_CUSTOM_COMMAND, 7777) END_DECLARE_EVENT_TYPES() DEFINE_EVENT_TYPE(wxEVT_LOGO_CUSTOM_COMMAND) #define EVT_LOGO_CUSTOM_COMMAND(id, fn) \ DECLARE_EVENT_TABLE_ENTRY( \ wxEVT_LOGO_CUSTOM_COMMAND, id, -1, \ (wxObjectEventFunction)(wxEventFunction)(wxCommandEventFunction)&fn, \ (wxObject *) NULL \ ), // ---------------------------------------------------------------------------- // Globals // ---------------------------------------------------------------------------- float fillScale; pen_info p; int TurtleFrame::back_ground = 0; int TurtleFrame::screen_height = 0; int TurtleFrame::screen_width = 0; int TurtleFrame::in_graphics_mode = 0; int TurtleFrame::in_splitscreen = 0; pen_info TurtleFrame::xgr_pen = p; int drawToWindow = 0; // for redraw_graphics from gui "thread" wxDC *windowDC = 0; wxMemoryDC *m_memDC; #define USE_MEMDC 1 int pictureleft = 0, pictureright = 0, picturetop = 0, picturebottom = 0; // Keep track of max range for printing. int TurtleCanvas::mousePosition_x; int TurtleCanvas::mousePosition_y; int TurtleCanvas::clickPosition_x; int TurtleCanvas::clickPosition_y; int TurtleCanvas::mouse_down_left; int TurtleCanvas::mouse_down_middle; int TurtleCanvas::mouse_down_right; int TurtleCanvas::mouse_down_last; wxColour TurtleCanvas::colors[NUMCOLORS+SPECIAL_COLORS]; int R, G, B; // Global print data, to remember settings during the session wxPrintData *g_printData = (wxPrintData*) NULL ; // Global page setup data wxPageSetupDialogData* g_pageSetupData = (wxPageSetupDialogData*) NULL; // Used for printing TurtleWindowPrintout *turtlePrintout; extern "C" int drawToPrinter; wxDC *printerDC; wxBitmap *tempBitmap; // have already called prepareToDraw int prepared = 0; TurtleFrame *turtleFrame; int turtleIndex = 0; int putInQueue = 0; #if 0 wxCommandEvent editEvent = wxCommandEvent(wxEVT_EDIT_CUSTOM_COMMAND); #endif char * file; // the location of the turtle extern "C" int turtlePosition_x; extern "C" int turtlePosition_y; #define LINEPAUSE 30 // ---------------------------------------------------------------------------- // Debug Functions // ---------------------------------------------------------------------------- /* We'll use 16 named colors for now (see xgraphics.h). The ordering here corresponds to the zero-based argument to setpencolor that gives that color -- pink is 12, turquoise is 10 etc. */ /* void PrintLines(){ struct line l; unsigned int turtleIndex = 0; for (; turtleIndexSetMarginTopLeft(wxPoint(15, 15)); g_pageSetupData->SetMarginBottomRight(wxPoint(15, 15)); #ifndef __WXMAC__ /* needed for wxWidgets 2.6 */ wxSetWorkingDirectory(wxStandardPaths::Get().GetDocumentsDir()); #endif mousePosition_x = 0; mousePosition_y = 0; clickPosition_x = 0; clickPosition_y = 0; mouse_down_left = 0; mouse_down_middle = 0; mouse_down_right = 0; mouse_down_last = 0; // initialize the TurtleCanvas::colors int i; TurtleCanvas::colors[SPECIAL_COLORS] = wxColour(0, 0, 0); TurtleCanvas::colors[SPECIAL_COLORS+1] = wxColour(0, 0, 255); TurtleCanvas::colors[SPECIAL_COLORS+2] = wxColour(0, 255, 0); TurtleCanvas::colors[SPECIAL_COLORS+3] = wxColour(0, 255, 255); TurtleCanvas::colors[SPECIAL_COLORS+4] = wxColour(255, 0, 0); TurtleCanvas::colors[SPECIAL_COLORS+5] = wxColour(255, 0, 255); TurtleCanvas::colors[SPECIAL_COLORS+6] = wxColour(255, 255, 0); TurtleCanvas::colors[SPECIAL_COLORS+7] = wxColour(255, 255, 255); TurtleCanvas::colors[SPECIAL_COLORS+8] = wxColour(155, 96, 59); TurtleCanvas::colors[SPECIAL_COLORS+9] = wxColour(197, 136, 18); TurtleCanvas::colors[SPECIAL_COLORS+10] = wxColour(100, 162, 64); TurtleCanvas::colors[SPECIAL_COLORS+11] = wxColour(120, 187, 187); TurtleCanvas::colors[SPECIAL_COLORS+12] = wxColour(255, 149, 119); TurtleCanvas::colors[SPECIAL_COLORS+13] = wxColour(144, 113, 208); TurtleCanvas::colors[SPECIAL_COLORS+14] = wxColour(255, 163, 0); TurtleCanvas::colors[SPECIAL_COLORS+15] = wxColour(183, 183, 183); for(i=SPECIAL_COLORS+16;ixgr_pen.vis = 0; int screen_width, screen_height; parent->GetSize(&screen_width, &screen_height); setInfo(SCREEN_WIDTH, screen_width); setInfo(SCREEN_HEIGHT, screen_height); turtleFrame->xgr_pen.xpos = screen_width/2; turtleFrame->xgr_pen.ypos = screen_height/2; pictureleft = pictureright = screen_width/2; picturetop = picturebottom = screen_height/2; turtleFrame->xgr_pen.color = 7; turtleFrame->xgr_pen.pw = 1; turtleFrame->xgr_pen.pen_mode = PEN_DOWN; #if USE_MEMDC m_memDC=new wxMemoryDC(); //make a bitmap the maximum size of the screen (the monitor, not the drawing area) int m_w,m_h; //monitor screen width and height wxDisplaySize(&m_w,&m_h); m_bitmap = new wxBitmap(m_w, m_h); PrepareDC(*m_memDC); wxBrush myBrush(TurtleCanvas::colors[turtleFrame->back_ground +SPECIAL_COLORS],wxSOLID); m_memDC->SelectObject(*m_bitmap); m_memDC->SetBackgroundMode( wxSOLID ); m_memDC->SetBackground( myBrush ); m_memDC->Clear(); //compute origin based on screen size vs monitor size //(BIGWIDTH - SMALLWIDTH)/2 m_memDC->SetDeviceOrigin( (m_w - screen_width)/2, (m_h - screen_height)/2 ); wxFont f(FONT_CFG(wx_font_face, wx_font_size)); m_memDC->SetFont(f); #endif } TurtleCanvas::~TurtleCanvas() { turtleGraphics = 0; } void TurtleCanvas::OnPaint(wxPaintEvent &WXUNUSED(event)) { wxdprintf("OnPaint starts\n"); wxPaintDC dc(this); OnDraw(dc); wxdprintf("OnPaint ends\n"); } void TurtleCanvas::OnSize(wxSizeEvent& event) { wxdprintf("OnSize starts\n"); int m_w,m_h; int screen_width, screen_height; wxDisplaySize(&m_w,&m_h); logoFrame->GetSize(&screen_width, &screen_height); setInfo(SCREEN_WIDTH, screen_width); setInfo(SCREEN_HEIGHT, screen_height); #if USE_MEMDC m_memDC->SetDeviceOrigin(m_w/2 - screen_width/2, m_h/2 - screen_height/2); #endif wxClientDC dc(this); OnDraw(dc); wxdprintf("OnSize ends\n"); } extern FLONUM turtle_x, turtle_y, turtle_heading; extern "C" FLONUM x_scale, y_scale; extern "C" BOOLEAN user_turtle_shown; extern "C" FIXNUM g_round(FLONUM n); void TurtleCanvas::DrawTurtle(wxDC &dc) { FLONUM real_heading; int left_x, left_y, right_x, right_y, top_x, top_y; double cos_real_heading, sin_real_heading; FLONUM delta_x, delta_y; if (!user_turtle_shown) { return; } const FLONUM degrad = 0.017453292520; const int screen_width = wxGetInfo(SCREEN_WIDTH); const int screen_height = wxGetInfo(SCREEN_HEIGHT); const int screen_top = 0; const int screen_left = 0; const FLONUM turtle_side = 19.0; const FLONUM turtle_half_bottom = 6.0; const int screen_x_center = (screen_left + (screen_width)/2); const int screen_y_center = (screen_top + (screen_height)/2); real_heading = -turtle_heading + 90.0; cos_real_heading = cos((FLONUM)(real_heading*degrad)); sin_real_heading = sin((FLONUM)(real_heading*degrad)); delta_x = x_scale*(FLONUM)(sin_real_heading*turtle_half_bottom); delta_y = y_scale*(FLONUM)(cos_real_heading*turtle_half_bottom); left_x = g_round(turtle_x - delta_x); left_y = g_round(turtle_y + delta_y); right_x = g_round(turtle_x + delta_x); right_y = g_round(turtle_y - delta_y); top_x = g_round(turtle_x + x_scale*(FLONUM)(cos_real_heading*turtle_side)); top_y = g_round(turtle_y + y_scale*(FLONUM)(sin_real_heading*turtle_side)); /* move to right, draw to left, draw to top, draw to right */ //move_to(screen_x_center + right_x, screen_y_center - right_y); //line_to(screen_x_center + left_x, screen_y_center - left_y); dc.SetPen(wxPen(colors[turtleFrame->xgr_pen.color+SPECIAL_COLORS], turtleFrame->xgr_pen.pw, wxSOLID)); dc.DrawLine(screen_x_center + right_x, screen_y_center - right_y, screen_x_center + left_x, screen_y_center - left_y); //line_to(screen_x_center + top_x, screen_y_center - top_y); dc.DrawLine(screen_x_center + left_x, screen_y_center - left_y, screen_x_center + top_x, screen_y_center - top_y); //line_to(screen_x_center + right_x, screen_y_center - right_y); dc.DrawLine(screen_x_center + top_x, screen_y_center - top_y, screen_x_center + right_x, screen_y_center - right_y); } void TurtleCanvas::OnDraw(wxDC &dc) { int x, y; //dc.DestroyClippingRegion(); GetSize(&x, &y); #if USE_MEMDC dc.Blit(0,0,x,y,m_memDC,0,0); DrawTurtle(dc); return; #endif int unset_windowDC = 0; if(windowDC == 0) { //OnSize may be triggered multiple times... windowDC = &dc; unset_windowDC++; } drawToWindow++; redraw_graphics(); drawToWindow--; if(unset_windowDC) { windowDC = 0; unset_windowDC--; } } void TurtleCanvas::OnFocus (wxFocusEvent & event){ wxTerminal::terminal->SetFocus(); } void TurtleCanvas::LoseFocus (wxFocusEvent & event){ } void TurtleCanvas::SetOwner(wxFrame * owner) { m_owner = owner; } wxFrame * TurtleCanvas::GetOwner() { return m_owner; } wxDC * TurtleCanvas::GetDC() { return dc; } void TurtleCanvas::OnEraseBackGround(wxEraseEvent& event) { wxdprintf("Executing OnEraseBackGround\n"); } void TurtleCanvas::drawOneLine(struct line *l, wxDC *dc) { wxPen myPen; wxColour xorColor; if (l->pm==PEN_ERASE) { myPen = wxPen(TurtleCanvas::colors[turtleFrame->back_ground+ SPECIAL_COLORS], l->pw, wxSOLID); } else if (l->pm==PEN_REVERSE) { unsigned int pr, pg, pb, br, bg, bb; get_palette(l->color, &pr, &pg, &pb); get_palette(turtleFrame->back_ground, &br, &bg, &bb); xorColor=wxColour((pr^br)/256, (pg^bg)/256, (pb^bb)/256); myPen = wxPen(xorColor, l->pw, wxSOLID); } else if(drawToPrinter && turtleFrame->back_ground==0 && l->color==7){ myPen = wxPen( wxT("black"), l->pw, wxSOLID); } else { myPen = wxPen(TurtleCanvas::colors[l->color+SPECIAL_COLORS], l->pw, wxSOLID); } dc->SetPen(myPen); if(l->pm==PEN_REVERSE){ dc->SetLogicalFunction(wxXOR); } else { dc->SetLogicalFunction(wxCOPY); } if(l->vis) { dc->DrawLine(l->x1,l->y1,l->x2,l->y2); dc->DrawPoint(l->x2,l->y2); /* draw endpoint */ if (!drawToPrinter && !drawToWindow) { if (l->x2 < pictureleft) pictureleft = l->x2; if (l->x2 > pictureright) pictureright = l->x2; if (l->y2 < picturetop) picturetop = l->y2; if (l->y2 > picturebottom) picturebottom = l->y2; } } turtlePosition_x = l->x2; turtlePosition_y = l->y2; dc->SetPen(wxNullPen); } extern "C" int turtle_shown; extern "C" void draw_turtle(); extern int editor_active; //from TextEditor.cpp void TurtleCanvas::editCall(){ editor_active = 1; editWindow->Clear(); topsizer->Show(wxTerminal::terminal, 0); topsizer->Show(turtleGraphics, 0); topsizer->Show(editWindow, 1); logoFrame->SetUpEditMenu(); topsizer->Layout(); editWindow->SetFocus(); FILE * filestream; filestream = fopen(file, "r"); if (filestream == NULL) { filestream = fopen(file, "w"); } fclose(filestream); editWindow->Load(wxString(file,wxConvUTF8)); //need to busy wait and handle events... while(editor_active) { if(check_wx_stop(1, 0)) break; wxMilliSleep(10); } } extern "C" void mouse_down(int); void TurtleCanvas::OnLeftDown(wxMouseEvent& event) { mouse_down_left = 1; mouse_down_last = 1; clickPosition_x = mousePosition_x; clickPosition_y = mousePosition_y; mouse_down(0); event.Skip(); //allow native handler to set focus } void TurtleCanvas::OnLeftUp(wxMouseEvent& event) { mouse_down_left = 0; event.Skip(); //allow native handler to set focus } void TurtleCanvas::OnMiddleDown(wxMouseEvent& event) { mouse_down_middle = 3; mouse_down_last = 3; clickPosition_x = mousePosition_x; clickPosition_y = mousePosition_y; mouse_down(0); event.Skip(); //allow native handler to set focus } void TurtleCanvas::OnMiddleUp(wxMouseEvent& event) { mouse_down_middle = 0; event.Skip(); //allow native handler to set focus } void TurtleCanvas::OnRightDown(wxMouseEvent& event) { mouse_down_right = 2; mouse_down_last = 2; clickPosition_x = mousePosition_x; clickPosition_y = mousePosition_y; mouse_down(0); event.Skip(); //allow native handler to set focus } void TurtleCanvas::OnRightUp(wxMouseEvent& event) { mouse_down_right = 0; event.Skip(); //allow native handler to set focus } void TurtleCanvas::OnMouseMove(wxMouseEvent& event){ mousePosition_x = event.m_x; mousePosition_y = event.m_y; event.Skip(); //allow native handler to set focus } extern "C" pen_info* getPen(); void TurtleCanvas::realClearScreen(wxDC *dc) { wxBrush myBrush(TurtleCanvas::colors[turtleFrame->back_ground+ SPECIAL_COLORS],wxSOLID); if(drawToPrinter && turtleFrame->back_ground==0){ myBrush.SetColour(_T("white")); } dc->SetBackgroundMode( wxSOLID ); dc->SetBackground( myBrush ); dc->Clear(); if (!drawToPrinter && !drawToWindow) { pictureleft = pictureright = getInfo(SCREEN_WIDTH)/2; picturetop = picturebottom = getInfo(SCREEN_HEIGHT)/2; } } void TurtleCanvas::realFloodFill(int color, wxDC *dc) { wxColour c; //fprintf(stderr, "realFloodFill: (x,y): (%d, %d)\n", turtlePosition_x, turtlePosition_y); dc->GetPixel(turtlePosition_x, turtlePosition_y, &c); wxBrush brush(TurtleCanvas::colors[color+SPECIAL_COLORS]); dc->SetBrush(brush); if (drawToPrinter) { dc->SetUserScale(1.0, 1.0); dc->FloodFill((long)(turtlePosition_x*fillScale), (long)(turtlePosition_y*fillScale) , c); dc->SetUserScale(fillScale, fillScale); } else { dc->FloodFill(turtlePosition_x, turtlePosition_y , c); } // dc->FloodFill(dc->LogicalToDeviceX(turtlePosition_x), dc->LogicalToDeviceY(turtlePosition_y) , c); } void TurtleCanvas::realdoFilled(int fillcolor, int count, struct mypoint *points, wxDC *dc) { wxPen myPen; wxPoint *wxpoints = (wxPoint*)malloc(count*sizeof(wxPoint)); wxPoint *wxptr; struct mypoint *ptr; for (wxptr = wxpoints, ptr = points; ptr < &points[count]; wxptr++, ptr++) { wxptr->x = ptr->x; wxptr->y = ptr->y; } if(drawToPrinter && turtleFrame->back_ground==0 && turtleFrame->xgr_pen.color==7){ myPen = wxPen( wxT("black"), turtleFrame->xgr_pen.pw, wxSOLID); } else { myPen = wxPen(colors[turtleFrame->xgr_pen.color+SPECIAL_COLORS], turtleFrame->xgr_pen.pw, wxSOLID); } dc->SetPen(myPen); wxBrush brush(TurtleCanvas::colors[fillcolor+SPECIAL_COLORS], wxSOLID); dc->SetBrush(brush); dc->DrawPolygon(count, wxpoints); free(wxpoints); } extern "C" FLONUM y_scale; extern "C" void wx_get_label_size(int *w, int *h) { /* returns size in pixels; converted to turtle steps in wxterm.c */ int descent, extlead; m_memDC->GetTextExtent(wxString("M", wxConvUTF8, wxString::npos), w, h, &descent, &extlead); } extern "C" void wx_adjust_label_height() { //take the font name, change the size based on scrunch int px_height = y_scale * label_height; int descent, extlead; int cw,ch; wxFont label_font = m_memDC->GetFont(); //now, initial guess for pt size is height / 1.5 int font_size = px_height * 3 / 2; label_font.SetPointSize(font_size); m_memDC->SetFont(label_font); m_memDC->GetTextExtent(wxString("M", wxConvUTF8, wxString::npos), &cw, &ch, &descent, &extlead); //now... first figure out whether we undershot or overshot... //this determines which direction to change the size int tmp_height = ch; wxFont tmp_font = label_font; if(tmp_height < px_height) { //increase the point size until we get two consecutive font sizes //where one is below px_height and one is above px_height int expected; while(tmp_height < px_height) { expected = tmp_font.GetPointSize() + 1; while(tmp_font.GetPointSize() != expected && expected <= 100){ expected++; tmp_font.SetPointSize(expected); } if (expected == 100) break; m_memDC->SetFont(tmp_font); m_memDC->GetTextExtent(wxString("M", wxConvUTF8, wxString::npos), &cw, &tmp_height, &descent, &extlead); if(tmp_height >= px_height) break; label_font.SetPointSize(expected); ch = tmp_height; } } else { //same as above, but decrease instead int expected; while(tmp_height > px_height) { expected = tmp_font.GetPointSize() - 1; while(tmp_font.GetPointSize() != expected && expected >= 2){ expected--; tmp_font.SetPointSize(expected); } if (expected == 2) break; m_memDC->SetFont(tmp_font); m_memDC->GetTextExtent(wxString("M", wxConvUTF8, wxString::npos), &cw, &tmp_height, &descent, &extlead); if(tmp_height <= px_height) break; label_font.SetPointSize(expected); ch = tmp_height; } } //now we have two fonts and two heights, we pick the closest one! int curr_diff = ch - px_height; int tmp_diff = tmp_height - px_height; if(curr_diff < 0) curr_diff = -curr_diff; if(tmp_diff < 0) tmp_diff = -tmp_diff; // fprintf(stderr, "ph: %d, cpt: %d, ch: %d, tpt: %d, th: %d \n", px_height, label_font.GetPointSize(), ch, tmp_font.GetPointSize(), tmp_height); if(curr_diff < tmp_diff) { m_memDC->SetFont(label_font); } else if(curr_diff > tmp_diff) { m_memDC->SetFont(tmp_font); } else { // if difference are the same, pick the smaller one if(ch < tmp_height) { m_memDC->SetFont(label_font); } else { m_memDC->SetFont(tmp_font); } } } bool TurtleCanvas::SetFont(const wxFont &f) { m_memDC->SetFont(f); wx_adjust_label_height(); return TRUE; } void TurtleCanvas::realDrawLabel(char *data, wxDC *dc) { wxString s(data, wxConvUTF8); wxCoord wid, ht; dc->GetTextExtent(s, &wid, &ht); dc->SetBackgroundMode(wxTRANSPARENT); if (turtleFrame->back_ground == 0 && drawToPrinter) { dc->SetTextBackground(TurtleCanvas::colors[SPECIAL_COLORS+7]); if (turtleFrame->xgr_pen.color == 7) dc->SetTextForeground(TurtleCanvas::colors[SPECIAL_COLORS+0]); else dc->SetTextForeground(TurtleCanvas::colors [turtleFrame->xgr_pen.color+SPECIAL_COLORS]); } else { dc->SetTextBackground(TurtleCanvas::colors[turtleFrame->back_ground+ SPECIAL_COLORS]); dc->SetTextForeground(TurtleCanvas::colors[turtleFrame->xgr_pen.color+ SPECIAL_COLORS]); } dc->DrawText(s, getPen()->xpos, getPen()->ypos-ht); if (!drawToPrinter) { if (getPen()->xpos < pictureleft) pictureleft = getPen()->xpos; if (getPen()->xpos+wid > pictureright) pictureright = getPen()->xpos+wid; if (getPen()->ypos-ht < picturetop) picturetop = getPen()->ypos-ht; if (getPen()->ypos > picturebottom) picturebottom = getPen()->ypos; } } /* A setter function for various turtle graphics properties */ void TurtleCanvas::setInfo(int type, int val){ switch (type){ case SCREEN_WIDTH: turtleFrame->screen_width = val; break; case SCREEN_HEIGHT: turtleFrame->screen_height = val; break; case BACK_GROUND: turtleFrame->back_ground = val; break; case IN_SPLITSCREEN: turtleFrame->in_splitscreen = val; break; case IN_GRAPHICS_MODE: turtleFrame->in_graphics_mode = val; break; } } /* A getter function for various turtle graphics properties */ int TurtleCanvas::getInfo(int type){ switch (type){ case SCREEN_WIDTH: return turtleFrame->screen_width; break; case SCREEN_HEIGHT: return turtleFrame->screen_height; break; case BACK_GROUND: return turtleFrame->back_ground; break; case IN_SPLITSCREEN: return turtleFrame->in_splitscreen; break; case IN_GRAPHICS_MODE: return turtleFrame->in_graphics_mode; break; } return -1; } void TurtleCanvas::OnPageSetup(wxCommandEvent& WXUNUSED(event)) { (*g_pageSetupData) = *g_printData; wxPageSetupDialog pageSetupDialog(this, g_pageSetupData); pageSetupDialog.ShowModal(); (*g_printData) = pageSetupDialog.GetPageSetupDialogData().GetPrintData(); (*g_pageSetupData) = pageSetupDialog.GetPageSetupDialogData(); } void TurtleCanvas::PrintTurtleWindow(wxCommandEvent& WXUNUSED(event)) { wxPrintDialogData printDialogData(* g_printData); wxPrinter printer(& printDialogData); TurtleWindowPrintout printout(_T("Turtle Graphics")); if (!printer.Print(turtleFrame, &printout, true /*prompt*/)) { if (wxPrinter::GetLastError() == wxPRINTER_ERROR) wxMessageBox(_T("There was a problem printing.\nPerhaps your current printer is not set correctly?"), _T("Printing"), wxOK); } else { (*g_printData) = printer.GetPrintDialogData().GetPrintData(); } } void TurtleCanvas::TurtlePrintPreview(wxCommandEvent& WXUNUSED(event)) { // Pass two printout objects: for preview, and possible printing. wxPrintDialogData printDialogData(* g_printData); wxPrintPreview *preview = new wxPrintPreview(new TurtleWindowPrintout, new TurtleWindowPrintout, & printDialogData); if (!preview->Ok()) { delete preview; wxMessageBox(_T("There was a problem previewing.\nPerhaps your current printer is not set correctly?"), _T("Previewing"), wxOK); return; } preview->SetZoom(100); wxPreviewFrame *frame = new wxPreviewFrame(preview, wxTerminal::terminal->terminal, _T("Turtle Graphics Preview"), wxPoint(100, 100), wxSize(600, 650)); frame->Centre(wxBOTH); frame->Initialize(); frame->Show(); } // ---------------------------------------------------------------------------- // TurtleFrame Class // ---------------------------------------------------------------------------- BEGIN_EVENT_TABLE(TurtleFrame, wxFrame) END_EVENT_TABLE() // frame constructor TurtleFrame::TurtleFrame(wxFrame * parent, const wxString& title, const wxPoint& pos, const wxSize& size) : wxFrame(/*(wxFrame *)NULL*/ parent, -1, title, pos, size, wxDEFAULT_FRAME_STYLE | wxNO_FULL_REPAINT_ON_RESIZE) { m_canvas = new TurtleCanvas( this ); } void TurtleFrame::OnQuit(wxCommandEvent& WXUNUSED(event)) { Close(TRUE); } TurtleCanvas * TurtleFrame::GetCanvas() { return m_canvas; } // ---------------------------------------------------------------------------- // Functions called from the interpreter thread // ---------------------------------------------------------------------------- extern "C" void nop() { } extern "C" void set_palette(int color, unsigned int r, unsigned int g, unsigned int b){ TurtleCanvas::colors[color+SPECIAL_COLORS] = wxColour(r/256,g/256,b/256); } extern "C" void get_palette(int color, unsigned int *r, unsigned int *g, unsigned int *b){ wxColour colour(TurtleCanvas::colors[color+SPECIAL_COLORS]); *r = colour.Red()*256; *g = colour.Green()*256; *b = colour.Blue()*256; } extern "C" void save_pen(pen_info *p) { memcpy(((char *)(p)),((char *)(&turtleFrame->xgr_pen)), sizeof(pen_info)); } extern "C" void restore_pen(pen_info *p) { memcpy(((char *)(&turtleFrame->xgr_pen)),((char *)(p)), sizeof(pen_info)); } extern "C" void set_pen_patter(){ nop(); } extern "C" void logofill() { if (drawToPrinter) TurtleCanvas::realFloodFill(turtleFrame->xgr_pen.color, printerDC); else if (drawToWindow) TurtleCanvas::realFloodFill(turtleFrame->xgr_pen.color, windowDC); else { #if USE_MEMDC TurtleCanvas::realFloodFill(turtleFrame->xgr_pen.color, m_memDC); #else wxDC *dc = new wxClientDC(turtleGraphics); TurtleCanvas::realFloodFill(turtleFrame->xgr_pen.color, dc); delete dc; #endif } } extern "C" void wx_refresh() { #if USE_MEMDC if(turtleGraphics) { turtleGraphics->Refresh(); turtleGraphics->Update(); } #endif } /* Clear the turtle graphics screen, and put in splitscreen if we are currently in full text mode */ extern "C" void wx_clear() { if (drawToPrinter) TurtleCanvas::realClearScreen(printerDC); else if (drawToWindow) TurtleCanvas::realClearScreen(windowDC); else { #if USE_MEMDC TurtleCanvas::realClearScreen(m_memDC); #else wxDC *dc = new wxClientDC(turtleGraphics); TurtleCanvas::realClearScreen(dc); delete dc; #endif if(!TurtleFrame::in_graphics_mode) wxSplitScreen(); } return; } extern "C" char record_buffer[]; extern "C" void wxPrepare(){ if (drawToPrinter || drawToWindow) { return; } if(!turtleFrame->in_graphics_mode) { wxSplitScreen(); } if(!prepared){ record_buffer[sizeof(int)] = 0; wx_clear(); prepared = 1; } return; } /* Have turtle graphics draw the given line */ extern "C" void wxDrawLine(int x1, int y1, int x2, int y2, int vis){ static int numLines = 0; if (!drawToPrinter && !drawToWindow) { if (numLines == LINEPAUSE) { wxMilliSleep(1); numLines = 0; } else numLines++; } wxDC *dc; struct line l; l.x1 = x1; l.y1 = y1; l.x2 = x2; l.y2 = y2; l.vis = vis; l.color = turtleFrame->xgr_pen.color; l.pm = turtleFrame->xgr_pen.pen_mode; l.pw = turtleFrame->xgr_pen.pw; if (drawToPrinter) TurtleCanvas::drawOneLine(&l, printerDC); else if (drawToWindow) TurtleCanvas::drawOneLine(&l, windowDC); else { #if USE_MEMDC TurtleCanvas::drawOneLine(&l, m_memDC); #else dc = new wxClientDC(turtleGraphics); TurtleCanvas::drawOneLine(&l, dc); delete dc; #endif } return; } extern "C" void doFilled(int fillcolor, int count, struct mypoint *points) { if (drawToPrinter) TurtleCanvas::realdoFilled(fillcolor, count, points, printerDC); else if (drawToWindow) TurtleCanvas::realdoFilled(fillcolor, count, points, windowDC); else { #if USE_MEMDC TurtleCanvas::realdoFilled(fillcolor, count, points, m_memDC); #else wxDC *dc = new wxClientDC(turtleGraphics); TurtleCanvas::realdoFilled(fillcolor, count, points, dc); delete dc; #endif } } /* Set the pen width. Notice this only takes one number, because wx only allows us to set the width and not the pen height */ extern "C" void wxSetPenWidth(int width){ turtleFrame->xgr_pen.pw = width; } extern "C" enum s_md {SCREEN_TEXT, SCREEN_SPLIT, SCREEN_FULL} screen_mode; //the event calling this never seems to trigger... void TurtleCanvas::OnChar(wxKeyEvent& event) { wxTerminal::terminal->OnChar(event); } /* Put the logoframe into splitscreen mode*/ extern "C" void wxSplitScreen(){ turtleFrame->in_graphics_mode = 1; turtleFrame->in_splitscreen = 1; topsizer->Show(wxTerminal::terminal, 1); topsizer->Show(turtleGraphics, 1); topsizer->Show(editWindow, 0); topsizer->Layout(); wxTerminal::terminal->SetFocus(); wxTerminal::terminal->deferUpdate(0); screen_mode = SCREEN_SPLIT; } /* Put the logoframe into full screen mode */ extern "C" void wxFullScreen(){ turtleFrame->in_graphics_mode = 1; turtleFrame->in_splitscreen = 0; topsizer->Show(wxTerminal::terminal, 0); topsizer->Show(turtleGraphics, 1); topsizer->Show(editWindow, 0); topsizer->Layout(); wxTerminal::terminal->SetFocus(); wxTerminal::terminal->deferUpdate(1); screen_mode = SCREEN_FULL; } /* Put the logoframe into text screen mode*/ extern "C" void wxTextScreen(){ turtleFrame->in_graphics_mode = 0; turtleFrame->in_splitscreen = 0; topsizer->Show(wxTerminal::terminal, 1); topsizer->Show(turtleGraphics, 0); topsizer->Show(editWindow, 0); topsizer->Layout(); wxTerminal::terminal->SetFocus(); wxTerminal::terminal->deferUpdate(0); screen_mode = SCREEN_TEXT; } extern "C" void wxlPrintPict(){ wxCommandEvent event(wxEVT_LOGO_CUSTOM_COMMAND); turtleGraphics->PrintTurtleWindow(event); } extern "C" void wxlPrintPreviewPict(){ wxCommandEvent event(wxEVT_LOGO_CUSTOM_COMMAND); turtleGraphics->TurtlePrintPreview(event); } extern "C" void wxlPrintText(){ wxCommandEvent event(wxEVT_LOGO_CUSTOM_COMMAND); logoFrame->OnPrintText(event); } extern "C" void wxlPrintPreviewText(){ wxCommandEvent event(wxEVT_LOGO_CUSTOM_COMMAND); logoFrame->OnPrintTextPrev(event); } void getMousePosition (int * x, int * y) { *x = TurtleCanvas::mousePosition_x - wxGetInfo(SCREEN_WIDTH)/2; *y = wxGetInfo(SCREEN_HEIGHT)/2 - TurtleCanvas::mousePosition_y; } void getClickPosition (int * x, int * y) { *x = TurtleCanvas::clickPosition_x - wxGetInfo(SCREEN_WIDTH)/2; *y = wxGetInfo(SCREEN_HEIGHT)/2 - TurtleCanvas::clickPosition_y; } extern "C" int wxGetMouseX() { int x, y; getMousePosition(&x,&y); return x; } extern "C" int wxGetMouseY() { int x, y; getMousePosition(&x,&y); return y; } extern "C" int wxGetClickX() { int x, y; getClickPosition(&x,&y); return x; } extern "C" int wxGetClickY() { int x, y; getClickPosition(&x,&y); return y; } extern "C" int wxGetButton () { return TurtleCanvas::mouse_down_left + TurtleCanvas::mouse_down_middle + TurtleCanvas::mouse_down_right; } extern "C" int wxGetLastButton () { return TurtleCanvas::mouse_down_last; } /* Show the text editor and have it load the given file */ extern "C" int wxEditFile(char * f){ file = f; alreadyDone = 0; //turtleGraphics->ProcessEvent(editEvent); turtleGraphics->editCall(); return editWindow->doSave; } extern "C" pen_info* getPen(){ return &turtleFrame->xgr_pen; } extern "C" void wxSetInfo(int type, int val) { TurtleCanvas::setInfo(type, val); } extern "C" int wxGetInfo(int type) { return TurtleCanvas::getInfo(type); } extern "C" void wxLabel(char * string) { if (drawToPrinter) TurtleCanvas::realDrawLabel(string, printerDC); else if (drawToWindow) TurtleCanvas::realDrawLabel(string, windowDC); else { #if USE_MEMDC TurtleCanvas::realDrawLabel(string, m_memDC); #else wxDC *dc = new wxClientDC(turtleGraphics); TurtleCanvas::realDrawLabel(string, dc); delete dc; #endif } } void TurtleCanvas::exitApplication() { } // ---------------------------------------------------------------------------- // TurtleWindowPrintout // ---------------------------------------------------------------------------- extern int turtle_shown; bool TurtleWindowPrintout::OnPrintPage(int page) { int w,h; wxDC *dc=GetDC(); int oldshown = turtle_shown; if (!dc) return false; #if !defined(__WXMAC__) && !defined(__WXMSW__) //using a memdc for printer here /* * Create our bitmap for copying */ dc->GetSize(&w, &h); wxMemoryDC *printMemDC = new wxMemoryDC(); wxBitmap *printBitmap = new wxBitmap(w,h); printMemDC->SelectObject(*printBitmap); printerDC = printMemDC; #else printerDC = dc; #endif #if 0 //#ifndef __WXMAC__ /* needed for wxWidgets 2.6 */ int maxX = pictureright - pictureleft; int maxY = picturebottom - picturetop; FitThisSizeToPageMargins(wxSize(maxX, maxY), *g_pageSetupData); wxRect fitRect = GetLogicalPageMarginsRect(*g_pageSetupData); wxCoord xoff = (fitRect.width - maxX) / 2 - pictureleft; //wxCoord xoff = (fitRect.width - maxX) / 2; wxCoord yoff = (fitRect.height - maxY) / 2 - picturetop; //wxCoord yoff = (fitRect.height - maxY) / 2; OffsetLogicalOrigin(xoff, yoff); #else float maxX = pictureright - pictureleft; float maxY = picturebottom - picturetop; // Let's have at least 50 device units margin float marginX = 50; float marginY = 50; // Get the size of the DC in pixels #if defined(__WXMAC__) || defined(__WXMSW__) dc->GetSize(&w, &h); //this is now done above with memDC #endif // Calculate a suitable scaling factor float scaleX=(float)((w-2*marginX)/maxX); float scaleY=(float)((h-2*marginY)/maxY); // Use x or y scaling factor, whichever fits on the DC float actualScale = wxMin(scaleX,scaleY); // Calculate the position on the DC for centring the graphic float posX = (float)((w - actualScale*maxX)/2)-pictureleft*actualScale; float posY = (float)((h - actualScale*maxY)/2)-picturetop*actualScale; // Set the scale and origin printerDC->SetUserScale(actualScale, actualScale); printerDC->SetDeviceOrigin( (long)posX, (long)posY ); fillScale = actualScale; #endif drawToPrinter = 1; turtle_shown = 0; redraw_graphics(); turtle_shown = oldshown; drawToPrinter = 0; #if !defined(__WXMAC__) && !defined(__WXMSW__) //now print the bitmap to the dc //actualPrinterDC->Blit(0,0,w,h,printMemDC,0,0); //appears not to work dc->DrawBitmap(*printBitmap, 0, 0); //delete bitmap and memorydc delete printBitmap; delete printMemDC; #endif return true; } bool TurtleWindowPrintout::OnBeginDocument(int startPage, int endPage) { if (!wxPrintout::OnBeginDocument(startPage, endPage)) return false; return true; } void TurtleWindowPrintout::GetPageInfo(int *minPage, int *maxPage, int *selPageFrom, int *selPageTo) { *minPage = 1; *maxPage = 1; *selPageFrom = 1; *selPageTo = 1; } bool TurtleWindowPrintout::HasPage(int pageNum) { return (pageNum == 1); }