Back to index

plt-scheme  4.2.1
Canvas.cc
Go to the documentation of this file.
00001 /*                                                      -*- C++ -*-
00002  *
00003  * Purpose: canvas panel item
00004  *
00005  * Authors: Markus Holzem and Julian Smart
00006  *
00007  * Copyright: (C) 2004-2009 PLT Scheme Inc.
00008  * Copyright: (C) 1995, AIAI, University of Edinburgh (Julian)
00009  * Copyright: (C) 1995, GNU (Markus)
00010  *
00011  * This program is free software; you can redistribute it and/or modify
00012  * it under the terms of the GNU General Public License as published by
00013  * the Free Software Foundation; either version 2 of the License, or
00014  * (at your option) any later version.
00015  *
00016  * This program is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  * GNU General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU General Public License
00022  * along with this program; if not, write to the Free Software
00023  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00024  * 02110-1301 USA.
00025  */
00026 
00027 #ifdef __GNUG__
00028 #pragma implementation "Canvas.h"
00029 #endif
00030 
00031 #define  Uses_XtIntrinsic
00032 #define  Uses_wxCanvas
00033 #define  Uses_wxWindowDC
00034 #define  Uses_wxTypeTree
00035 #include "wx.h"
00036 #define  Uses_EnforcerWidget
00037 #define  Uses_ScrollWinWidget
00038 #define  Uses_CanvasWidget
00039 #define  Uses_ArrowWidget
00040 #include "widgets.h"
00041 
00042 #include "wxgl.h"
00043 #ifdef USE_GL
00044 extern Visual *wxGetGLCanvasVisual(wxGLConfig *cfg);
00045 Visual *wx_common_use_visual;
00046 #endif
00047 
00048 //-----------------------------------------------------------------------------
00049 // create and destroy canvas
00050 //-----------------------------------------------------------------------------
00051 
00052 wxCanvas::wxCanvas(wxWindow *parent, int x, int y, int width, int height,
00053                  int style, char *name, wxGLConfig *gl_cfg) : wxItem(NULL)
00054 {
00055     __type = wxTYPE_CANVAS;
00056 
00057     h_size = h_units = v_size = v_units = 1;
00058     h_units_per_page = v_units_per_page = 50;
00059 
00060     Create((wxPanel *)parent, x, y, width, height, style, name, gl_cfg);
00061 }
00062 
00063 Bool wxCanvas::Create(wxPanel *panel, int x, int y, int width, int height,
00064                     int style, char *name, wxGLConfig *gl_cfg)
00065 {
00066     wxWindow_Xintern *ph;
00067     Widget wgt;
00068 
00069     bgcol = (style & wxTRANSPARENT_WIN) ? wxGREY : wxWHITE;
00070 
00071     ChainToPanel(panel, style, name);
00072 
00073     ph = parent->GetHandle();
00074 
00075     // create frame
00076     wgt = XtVaCreateWidget
00077        (name, 
00078         xfwfEnforcerWidgetClass, 
00079         ph->handle,
00080         XtNbackground,  wxGREY_PIXEL,
00081         XtNforeground,  wxBLACK_PIXEL,
00082         XtNfont,        font->GetInternalFont(),
00083         XtNtraversalTranslationDone, TRUE,
00084         XtNhighlightThickness, ((style & wxNO_CAPTION) ? 1 : 0),
00085         XtNframeWidth, 0,
00086         XtNmultipleKids, !!(style & wxCOMBO_SIDE),
00087         NULL);
00088     if (!(style & wxINVISIBLE))
00089       XtManageChild(wgt);
00090     else
00091       XtRealizeWidget(wgt);
00092     X->frame = wgt;
00093     // create scrolled area
00094     wgt = XtVaCreateManagedWidget
00095        ("viewport", xfwfScrolledWindowWidgetClass, X->frame,
00096         XtNhideHScrollbar, TRUE,
00097         XtNhideVScrollbar, TRUE,
00098         XtNtraversalTranslationDone, TRUE,
00099         XtNframeWidth, ((style & wxBORDER) ? 1 : 0),
00100         XtNedgeBars, TRUE,
00101         XtNframeType, XfwfPlain,
00102         XtNshadowWidth, 0,
00103         XtNshadowScheme, XfwfColor,
00104         XtNhighlightThickness, 0,
00105         XtNspacing, 0,
00106         XtNbackground,  wxGREY_PIXEL,
00107         XtNforeground,  wxDARK_GREY_PIXEL,
00108         XtNbottomShadowColor, wxDARK_GREY_PIXEL,
00109         XtNhighlightColor, wxCTL_HIGHLIGHT_PIXEL,
00110         XtNlocation, ((style & wxCOMBO_SIDE) ? "0 0 1.0 - 16 1.0" : "0 0 1.0 1.0"),
00111         NULL);
00112     X->scroll = wgt;
00113     // Create combo, if requested
00114     if (style & wxCOMBO_SIDE) {
00115       Widget combo;
00116       combo = XtVaCreateManagedWidget
00117        ("choice_button", xfwfArrowWidgetClass, X->frame,
00118         XtNbackground,  wxGREY_PIXEL,
00119         XtNforeground,  wxBLACK_PIXEL,
00120         XtNdirection,   XfwfBottom,
00121         XtNrepeat,      FALSE,
00122         XtNarrowShadow, 0,
00123         XtNframeWidth, 2,
00124         XtNframeType, XfwfRaised,
00125         XtNlocation,    "1.0 - 16 0 16 1.0",
00126         XtNhighlightThickness, 0,
00127         NULL);
00128       
00129       XtInsertEventHandler
00130        (combo,
00131         KeyPressMask | KeyReleaseMask |
00132         ButtonPressMask |   // for OnEvent
00133         ButtonReleaseMask |
00134         ButtonMotionMask |
00135         PointerMotionMask | PointerMotionHintMask,
00136         FALSE,
00137         (XtEventHandler)wxWindow::WindowEventHandler,
00138         (XtPointer)saferef,
00139         XtListHead);
00140 
00141       X->extra = combo;
00142     }
00143     // create canvas
00144 #ifdef USE_GL
00145     wx_common_use_visual = wxGetGLCanvasVisual(gl_cfg);
00146 #endif
00147     wgt = XtVaCreateManagedWidget
00148       ("canvas", xfwfCanvasWidgetClass, X->scroll,
00149        XtNbackingStore, (style & wxBACKINGSTORE) ? Always : NotUseful,
00150        XtNborderWidth,  0,
00151        XtNbackground,  ((style & wxTRANSPARENT_WIN) ? wxGREY_PIXEL : wxWHITE_PIXEL),
00152        XtNhighlightThickness, 0,
00153        XtNframeWidth, 0,
00154        XtNtraversalOn, FALSE,
00155        NULL);
00156 #ifdef USE_GL
00157     wx_common_use_visual = NULL;
00158 #endif
00159     X->handle = wgt;
00160     // In case this window or the parent is hidden; we
00161     // need windows to create DCs
00162     XtRealizeWidget(X->frame);
00163     XtRealizeWidget(X->scroll);
00164     XtRealizeWidget(X->handle);
00165 
00166     // Initialize CanvasDC
00167     CreateDC();
00168 #ifdef USE_GL
00169     dc->SetGLConfig(gl_cfg);
00170 #endif
00171     dc->SetBackground(wxWHITE); // white brush as default for canvas background
00172     // position in panel
00173     panel->PositionItem(this, x, y,
00174                      (width  > -1 ? width  : /* wxCANVAS_WIDTH */ 0),
00175                      (height > -1 ? height : /* wxCANVAS_HEIGHT */ 0));
00176 
00177 #if 0
00178     // resize canvas
00179     Position xx, yy; int ww, hh;
00180     XfwfCallComputeInside(X->scroll, &xx, &yy, &ww, &hh);
00181     h_size = ww; v_size = hh; SetScrollArea(h_size, v_size);
00182 #endif
00183 
00184     if (style & (wxHSCROLL | wxVSCROLL)) {
00185       EnableScrolling(style & wxHSCROLL, style & wxVSCROLL);
00186       SetScrollbars(style & wxHSCROLL, style & wxVSCROLL,
00187                   0, 0, 1, 1, 0, 0, FALSE);
00188     }
00189 
00190     // add event handlers
00191     AddEventHandlers();
00192     // propagate key events from frame to canvas widget
00193     XtVaSetValues(X->frame, XtNpropagateTarget, X->handle, NULL);
00194 
00195     if (style & wxINVISIBLE)
00196       Show(FALSE);
00197 
00198     // ready
00199     return TRUE;
00200 }
00201 
00202 wxCanvas::~wxCanvas(void)
00203 {
00204 }
00205 
00206 void wxCanvas::SetBackgroundToGray(void)
00207 {
00208   XtVaSetValues(X->handle, XtNbackground,  wxGREY_PIXEL, NULL);
00209   bgcol = NULL;
00210 }
00211 
00212 void wxCanvas::SetCanvasBackground(wxColor *c)
00213 {
00214   if (!bgcol || !c)
00215     return;
00216   
00217   if (c && c->IsMutable()) {
00218     c = new wxColour(c);
00219     c->Lock(1);
00220   }
00221    
00222   bgcol = c;
00223 
00224   XtVaSetValues(X->handle, XtNbackground,  c->GetPixel(), NULL);
00225 }
00226 
00227 wxColour *wxCanvas::GetCanvasBackground()
00228 {
00229   return bgcol;
00230 }
00231 
00232 void wxCanvas::Paint(void)
00233 {
00234   if (!(style & wxNO_AUTOCLEAR)) {
00235     /* Need to erase, first */
00236     wxColor *c;
00237     c = dc->GetBackground();
00238     dc->SetBackground(bgcol ? bgcol : wxGREY);
00239     dc->Clear();
00240     dc->SetBackground(c);
00241   }
00242 
00243   OnPaint();
00244 }
00245 
00246 //-----------------------------------------------------------------------------
00247 // handle scrollbars, pointer, and virtual size
00248 //-----------------------------------------------------------------------------
00249 
00250 void wxCanvas::GetVirtualSize(int *x, int *y)
00251 {
00252     Dimension ww, hh;
00253     XtVaGetValues(X->handle, XtNwidth, &ww, XtNheight, &hh, NULL);
00254     *x = ww; *y = hh;
00255 }
00256 
00257 void wxCanvas::GetRefreshSize(int *w, int *h)
00258 {
00259   GetVirtualSize(w, h);
00260 }
00261 
00262 void wxCanvas::Scroll(int x_pos, int y_pos)
00263 {
00264   if (misc_flags & 8) {
00265     /* Not managing */
00266     wxItem::Scroll(x_pos, y_pos);
00267   } else {
00268     /* Managing */
00269     /* Get the actual scroll step, which is the client size, rather
00270        than h_units/v_unit */
00271     int cw, ch;
00272     GetClientSize(&cw, &ch);
00273     wxItem::Scroll(x_pos * cw, y_pos * ch);
00274   }
00275 }
00276 
00277 void wxCanvas::ScrollPercent(double x, double y)
00278 {
00279   if (misc_flags & 8) {
00280     /* Not managing  - do nothing */
00281   } else {
00282     /* Managing */
00283     int xp, yp, vw, vh, cw, ch;
00284     GetVirtualSize(&vw, &vh);
00285     GetClientSize(&cw, &ch);
00286 
00287     if (vw > cw)
00288       vw -= cw;
00289     else
00290       vw = 0;
00291     if (vh > ch)
00292       vh -= ch;
00293     else
00294       vh = 0;
00295 
00296     if (x >= 0)
00297       xp = (int)floor(x * vw);
00298     else
00299       xp = -1;
00300     
00301     if (y >= 0)
00302       yp = (int)floor(y * vh);
00303     else
00304       yp = -1;
00305     
00306     wxItem::Scroll(xp, yp);
00307   }
00308 }
00309 
00310 void wxCanvas::SetScrollbars(int h_pixels, int v_pixels, int x_len, int y_len,
00311                           int x_page, int y_page, int x_pos, int y_pos,
00312                           Bool setVirtualSize)
00313 {
00314     if (!(GetWindowStyleFlag() & wxHSCROLL))
00315       h_pixels = -1;
00316     if (!(GetWindowStyleFlag() & wxVSCROLL))
00317       v_pixels = -1;
00318 
00319     if (x_len < 1) h_pixels = -1;
00320     if (y_len < 0) v_pixels = -1;
00321 
00322     if (setVirtualSize) {
00323       Arg a[4];
00324 
00325       XtVaSetValues(X->scroll, XtNautoAdjustScrollbars, 1, NULL);
00326 
00327       misc_flags -= (misc_flags & 8);
00328 
00329       if (h_pixels > 0) {
00330        h_units          = h_pixels;
00331        h_size           = h_units * x_len;
00332        h_units_per_page = hs_page = x_page;
00333        hs_width         = x_len;
00334       } else
00335        hs_width = 0;
00336       if (v_pixels > 0) {
00337        v_units          = v_pixels;
00338        v_size           = v_units * y_len;
00339        v_units_per_page = vs_page = y_page;
00340        vs_width         = y_len;
00341       } else
00342        vs_width = 0;
00343        
00344       /* size = 0 safety: */
00345       if (!h_size)
00346        h_size = 1;
00347       if (!v_size)
00348        v_size = 1;
00349 
00350       // adjust size and position of canvas
00351       a[0].name = XtNabs_height;
00352       a[0].value = v_pixels > 0 ? ((Dimension)v_size) : 0;
00353       a[1].name = XtNrel_height;
00354       *(float *)(void *)&(a[1].value) = (float)(v_pixels > 0 ? 0.0 : 1.0);
00355       a[2].name = XtNabs_width;
00356       a[2].value = h_pixels > 0 ? ((Dimension)h_size) : 0;
00357       a[3].name = XtNrel_width;
00358       *(float *)(void *)&(a[3].value) = (float)(h_pixels > 0 ? 0.0 : 1.0);
00359 
00360       XtSetValues(X->handle, a, 4);
00361 
00362       wxItem::Scroll(x_pos, y_pos);
00363       // set scroll steps of scrollbars
00364       if (X->scroll) {
00365        XtVaSetValues(X->scroll,
00366                     XtNhScrollAmount, h_units,
00367                     XtNvScrollAmount, v_units,
00368                     NULL);
00369       }
00370     } else {
00371       Arg a[8];
00372 
00373       XtVaSetValues(X->scroll, XtNautoAdjustScrollbars, 0, NULL);
00374 
00375       a[0].name = XtNabs_height;
00376       a[0].value = 0;
00377       a[1].name = XtNrel_height;
00378       *(float *)(void *)&(a[1].value) = 1.0;
00379       a[2].name = XtNabs_width;
00380       a[2].value = 0;
00381       a[3].name = XtNrel_width;
00382       *(float *)(void *)&(a[3].value) = 1.0;
00383       a[4].name = XtNabs_x;
00384       a[4].value = 0;
00385       a[5].name = XtNabs_y;
00386       a[5].value = 0;
00387       a[6].name = XtNrel_x;
00388       *(float *)(void *)&(a[6].value) = 0.0;
00389       a[7].name = XtNrel_y;
00390       *(float *)(void *)&(a[7].value) = 0.0;
00391 
00392       XtSetValues(X->handle, a, 8);
00393 
00394       misc_flags |= 8;
00395       if (h_pixels > 0) {
00396        hs_width = x_len;
00397        hs_page = x_page;
00398        SetScrollPos(wxHORIZONTAL, x_pos);
00399       } else {
00400        hs_width = 0;
00401        hs_page = 1;
00402        SetScrollPos(wxHORIZONTAL, 0);
00403       }
00404 
00405       if (v_pixels > 0) {
00406        vs_width = y_len;
00407        vs_page = y_page;
00408        SetScrollPos(wxVERTICAL, y_pos);
00409       } else {
00410        vs_width = 0;
00411        vs_page = 1;
00412        SetScrollPos(wxVERTICAL, 0);
00413       }
00414     }
00415 }
00416 
00417 void wxCanvas::ViewStart(int *x, int *y)
00418 {
00419     Position xx, yy;
00420 
00421     XtVaGetValues(X->handle, XtNx, &xx, XtNy, &yy, NULL);
00422     *x = -xx; *y = -yy;
00423 }
00424 
00425 void wxCanvas::WarpPointer(int x, int y)
00426 {
00427   XWarpPointer(XtDisplay(X->handle), None, XtWindow(X->handle), 0, 0, 0, 0, x, y);
00428 }
00429 
00430 void wxCanvas::ChangeToGray(Bool gray)
00431 {
00432   if (X->extra)
00433     XtVaSetValues(X->extra, XtNdrawgrayArrow, (Boolean)gray, NULL);
00434   if (GetWindowStyleFlag() & wxVSCROLL) {
00435     XtVaSetValues(X->scroll, XtNforeground, gray ? wxGREY_PIXEL : wxDARK_GREY_PIXEL, NULL);
00436   }
00437   wxItem::ChangeToGray(gray);
00438   if (!bgcol)
00439     Refresh();
00440 }
00441 
00442 void wxCanvas::Layout(void)
00443 {
00444 #ifdef WX_USE_CAIRO
00445   dc->ReleaseCairoDev(); /* in case resize makes a larger area */
00446 #endif
00447   wxWindow::Layout();
00448 }
00449 
00450 //-----------------------------------------------------------------------------
00451 // handle scrolling with keys
00452 //-----------------------------------------------------------------------------
00453 
00454 void wxCanvas::OnChar(wxKeyEvent *event)
00455 {
00456     int start_x, start_y;
00457 
00458     ViewStart(&start_x, &start_y);
00459 
00460     switch (event->KeyCode()) {
00461     case WXK_PRIOR:
00462        Scroll(start_x, max(0, start_y-v_units_per_page));
00463        break;
00464     case WXK_NEXT:
00465        Scroll(start_x, start_y + v_units_per_page);
00466        break;
00467     case WXK_UP:
00468        if (start_y >= 1)
00469            Scroll(start_x, start_y - 1);
00470        break;
00471     case WXK_DOWN:
00472        Scroll(start_x, start_y + 1);
00473        break;
00474     case WXK_LEFT:
00475        if (event->ControlDown()) {
00476            Scroll(max(0, start_x-h_units_per_page), start_y);
00477        } else {
00478            if (start_x >= 1)
00479               Scroll(start_x - 1, start_y);
00480        }
00481        break;
00482     case WXK_RIGHT:
00483        if (event->ControlDown())
00484            Scroll(start_x + h_units_per_page, start_y);
00485        else
00486            Scroll(start_x + 1, start_y);
00487        break;
00488     case WXK_HOME:
00489        Scroll(0, 0);
00490        break;
00491     }
00492 }
00493 
00494 Bool wxCanvas::WantsFocus(void)
00495 {
00496   if (GetWindowStyleFlag() & wxNEVER_FOCUS)
00497     return FALSE;
00498   else
00499     return TRUE;
00500 }