home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
World of Shareware - Software Farm 2
/
wosw_2.zip
/
wosw_2
/
CPROG
/
WXWIN140.ZIP
/
SRC
/
WX_CANVS.CC
< prev
next >
Wrap
C/C++ Source or Header
|
1993-04-19
|
31KB
|
1,231 lines
/*
* File: wx_canvs.cc
* Purpose: wxCanvas implementation
*
* wxWindows 1.40
* Copyright (c) 1993 Artificial Intelligence Applications Institute,
* The University of Edinburgh
*
* Author: Julian Smart
* Date: 18-4-93
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose is hereby granted without fee, provided
* that the above copyright notice, author statement and this permission
* notice appear in all copies of this software and related documentation.
*
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, EXPRESS,
* IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
*
* IN NO EVENT SHALL THE ARTIFICIAL INTELLIGENCE APPLICATIONS INSTITUTE OR THE
* UNIVERSITY OF EDINBURGH BE LIABLE FOR ANY SPECIAL, INCIDENTAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF THE POSSIBILITY OF
* DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH
* THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <windows.h>
#include <math.h>
#include "common.h"
#include "wx_frame.h"
#include "wx_dc.h"
#include "wx_canvs.h"
#include "wx_event.h"
#include "wx_utils.h"
#include "wx_privt.h"
#ifdef wx_motif
#include "wx_main.h"
#include <Xm/DrawingA.h>
#include <Xm/ScrolledW.h>
#include <Xm/ScrollBar.h>
#define SCROLL_MARGIN 4
void wxCanvasRepaintProc(Widget, XtPointer, XmDrawingAreaCallbackStruct *cbs);
void wxCanvasKeyEvent(Widget, XKeyEvent *);
void wxCanvasInputEvent(Widget, XButtonEvent *event);
#endif
#ifdef wx_xview
#include <xview/screen.h>
extern Xv_Server xview_server;
void wxCanvasRepaintProc(Canvas canvas, Xv_Window paint_window,
Display *dpy, Window xwin, Xv_xrectlist *xrects);
void wxCanvasResizeProc(Canvas canvas, int width, int height);
void wxCanvasEventProc(Xv_Window window, Event *event, Notify_arg arg);
#endif
wxCanvas::wxCanvas(wxFrame *frame, int x, int y, int width, int height, int style)
{
is_retained = ((style & wxRETAINED) == wxRETAINED);
#ifdef wx_motif
hScroll = FALSE;
vScroll = FALSE;
hScrollBar = NULL;
vScrollBar = NULL;
allowRepainting = TRUE;
hScrollingEnabled = TRUE;
vScrollingEnabled = TRUE;
// Can't rely on Xt to return these values, so must store.
canvasWidth = 0;
canvasHeight = 0;
canvasX = 0;
canvasY = 0;
backingPixmap = 0;
pixmapWidth = 0;
pixmapHeight = 0;
hExtent = 0;
vExtent = 0;
button1Pressed = FALSE;
button2Pressed = FALSE;
button3Pressed = FALSE;
pixmapOffsetX = 0;
pixmapOffsetY = 0;
// New translations for getting mouse motion feedback - duh!
String translations =
"<Btn1Motion>: wxCanvasInputEvent() ManagerGadgetButtonMotion()\n\
<Btn2Motion>: wxCanvasInputEvent() ManagerGadgetButtonMotion()\n\
<Btn3Motion>: wxCanvasInputEvent() ManagerGadgetButtonMotion()\n\
<Btn1Down>: wxCanvasInputEvent() ManagerGadgetArm()\n\
<Btn2Down>: wxCanvasInputEvent() ManagerGadgetArm()\n\
<Btn3Down>: wxCanvasInputEvent() ManagerGadgetArm()\n\
<Btn1Up>: wxCanvasInputEvent() ManagerGadgetActivate()\n\
<Btn2Up>: wxCanvasInputEvent() ManagerGadgetActivate()\n\
<Btn3Up>: wxCanvasInputEvent() ManagerGadgetActivate()\n\
<Key>: wxCanvasKeyEvent()";
XtActionsRec actions[2];
actions[0].string = "wxCanvasInputEvent";
actions[0].proc = (XtActionProc)wxCanvasInputEvent;
actions[1].string = "wxCanvasKeyEvent";
actions[1].proc = (XtActionProc)wxCanvasKeyEvent;
XtAppAddActions(wxTheApp->appContext, &actions, 2);
Widget parentWidget = frame->workArea;
scrolledWindow = XtVaCreateManagedWidget("scrolled_window",
xmScrolledWindowWidgetClass, parentWidget,
XmNscrollingPolicy, XmAPPLICATION_DEFINED,
NULL);
Widget drawingArea = XtVaCreateManagedWidget("drawing_area",
xmDrawingAreaWidgetClass, scrolledWindow,
XmNunitType, XmPIXELS,
XmNresizePolicy, XmRESIZE_ANY,
XmNtranslations, XtParseTranslationTable(translations),
NULL);
handle = (char *)drawingArea;
wxWidgetHashTable->Put((long)drawingArea, this);
wxWidgetHashTable->Put((long)scrolledWindow, this);
XtOverrideTranslations(drawingArea,
XtParseTranslationTable("<Configure>: resize()"));
XtAddCallback(drawingArea, XmNexposeCallback, wxCanvasRepaintProc, this);
if (x > -1)
{
canvasX = x;
XtVaSetValues(scrolledWindow,
XmNleftAttachment, XmATTACH_SELF,
XmNx, x,
NULL);
}
if (y > -1)
{
canvasY = y;
XtVaSetValues(scrolledWindow,
XmNtopAttachment, XmATTACH_SELF,
XmNy, y,
NULL);
}
if (width > -1)
{
canvasWidth = width;
XtVaSetValues(scrolledWindow, XmNwidth, width, NULL);
if (!hScroll)
XtVaSetValues(drawingArea, XmNwidth, width - SCROLL_MARGIN, NULL);
}
if (height > -1)
{
canvasHeight = height;
XtVaSetValues(scrolledWindow, XmNheight, height, NULL);
if (!vScroll)
XtVaSetValues(drawingArea, XmNheight, height - SCROLL_MARGIN, NULL);
}
XtRealizeWidget(scrolledWindow);
XtRealizeWidget(drawingArea);
if (!hScroll)
{
Widget hWidget;
XtVaGetValues(scrolledWindow, XmNhorizontalScrollBar, &hWidget, NULL);
}
if (!vScroll)
{
Widget vWidget;
XtVaGetValues(scrolledWindow, XmNverticalScrollBar, &vWidget, NULL);
}
display = XtDisplay(scrolledWindow);
xwindow = XtWindow(drawingArea);
// SetSize(x, y, width, height);
#endif
#ifdef wx_xview
repaint_countdown = 0;
// Since I have found that it's difficult to keep up with
// all XView drag events, this counts down to zero before sending
// an OnEvent message. If you want more sensitivity, reduce this value
// and recompile wxWindows.
DRAG_MAX = 0;
int real_y = frame->y_offset;
if (y > -1)
real_y = y + frame->y_offset; // Allow for possible menu bar
Frame x_frame = (Frame)frame->handle;
Canvas x_canvas = (Canvas)xv_create(x_frame, CANVAS,
// CANVAS_REPAINT_PROC, wxCanvasRepaintProc,
// CANVAS_RESIZE_PROC, wxCanvasResizeProc,
CANVAS_X_PAINT_WINDOW, TRUE,
WIN_CLIENT_DATA, (char *)this,
CANVAS_RETAINED, is_retained,
XV_SHOW, FALSE,
NULL);
xv_set(canvas_paint_window(x_canvas), WIN_EVENT_PROC, wxCanvasEventProc,
WIN_CONSUME_EVENTS,
WIN_ASCII_EVENTS, KBD_USE, KBD_DONE,
LOC_DRAG, LOC_WINENTER, LOC_WINEXIT, WIN_MOUSE_BUTTONS,
NULL,
WIN_CLIENT_DATA, (char *)this, NULL);
handle = (char *)x_canvas;
xv_set(x_canvas, XV_SHOW, TRUE, NULL);
horiz_scroll = NULL;
vert_scroll = NULL;
Xv_Screen screen = xv_get(xview_server, SERVER_NTH_SCREEN, 0);
Xv_Window root_window = xv_get(screen, XV_ROOT);
xwindow = (Window)xv_get(canvas_paint_window(x_canvas), XV_XID);
display = (Display *)xv_get(root_window, XV_DISPLAY);
drag_count = DRAG_MAX;
xrects = NULL;
#endif
#ifdef wx_msw
wxWinType = wxTYPE_XWND;
is_retained = FALSE;
clipping = FALSE;
wxWnd *cparent = NULL;
if (frame)
cparent = (wxWnd *)frame->handle;
DWORD msflags = 0;
if (style & wxBORDER)
msflags |= WS_BORDER;
msflags |= WS_CHILD | WS_VISIBLE;
wxCanvasWnd *wnd = new wxCanvasWnd(cparent, this, x, y, width, height, msflags);
wnd->background_brush = GetStockObject(WHITE_BRUSH);
handle = (char *)wnd;
#endif
if (frame) frame->AddChild(this);
window_parent = frame;
horiz_units = 0;
vert_units = 0;
wx_dc = new wxDC(this);
context = wx_dc;
#ifdef wx_xview
xv_set(x_canvas,
CANVAS_REPAINT_PROC, wxCanvasRepaintProc,
CANVAS_RESIZE_PROC, wxCanvasResizeProc, NULL);
if (x > -1)
xv_set(x_canvas, XV_X, x, NULL);
if (y > -1)
xv_set(x_canvas, XV_Y, real_y, NULL);
if (width > -1)
xv_set(x_canvas, XV_WIDTH, width, NULL);
if (height > -1)
xv_set(x_canvas, XV_HEIGHT, height, NULL);
#endif
}
wxCanvas::~wxCanvas(void)
{
#ifdef wx_motif
if (backingPixmap)
XFreePixmap(XtDisplay((Widget)handle), backingPixmap);
#endif
#ifdef wx_xview
Canvas x_canvas = (Canvas)handle;
Xv_window pw = canvas_paint_window(x_canvas);
(void)xv_set(pw, WIN_CLIENT_DATA, NULL, NULL);
xv_set(x_canvas,
CANVAS_X_PAINT_WINDOW, FALSE, NULL);
if (horiz_scroll)
xv_destroy_safe((Xv_opaque)horiz_scroll);
if (vert_scroll)
xv_destroy_safe((Xv_opaque)vert_scroll);
if (wx_dc)
delete wx_dc;
#endif
}
#ifdef wx_motif
void wxCanvas::PreResize(void)
{
// cout << "Canvas PreResize\n";
// OnPaint();
}
#endif
#ifdef wx_msw
void wxCanvas::PreDelete(HDC dc)
{
wx_dc->SelectOldObjects(dc);
delete wx_dc;
}
#endif
void wxCanvas::SetClippingRegion(float cx, float cy, float cw, float ch)
{
wx_dc->SetClippingRegion(cx, cy, cw, ch);
}
void wxCanvas::DestroyClippingRegion(void)
{
wx_dc->DestroyClippingRegion();
}
wxDC *wxCanvas::GetDC(void)
{
return context;
}
void wxCanvas::SetClientSize(int w, int h)
{
#ifdef wx_motif
Widget drawingArea = (Widget)handle;
if (w > -1)
{
canvasWidth = w;
XtVaSetValues(scrolledWindow, XmNwidth, w, NULL);
if (!hScroll)
XtVaSetValues(drawingArea, XmNwidth, w - SCROLL_MARGIN, NULL);
}
if (h > -1)
{
canvasHeight = h;
XtVaSetValues(scrolledWindow, XmNheight, h, NULL);
if (!vScroll)
XtVaSetValues(drawingArea, XmNheight, h - SCROLL_MARGIN, NULL);
}
allowRepainting = FALSE;
XSync(XtDisplay(drawingArea), FALSE);
XEvent event;
while (XtAppPending(wxTheApp->appContext))
{
XFlush(XtDisplay(drawingArea));
XtAppNextEvent(wxTheApp->appContext, &event);
XtDispatchEvent(&event);
}
allowRepainting = TRUE;
Refresh();
OnSize(w, h);
#else
wxWindow::SetClientSize(w, h);
#endif
}
void wxCanvas::GetClientSize(int *w, int *h)
{
#ifdef wx_motif
// Doesn't return the right value!
// XtVaGetValues(scrolledWindow, XmNwidth, w, XmNheight, h, NULL);
*w = canvasWidth;
*h = canvasHeight;
#else
wxWindow::GetClientSize(w, h);
#endif
}
void wxCanvas::SetSize(int x, int y, int w, int h)
{
#ifdef wx_motif
Widget drawingArea = (Widget)handle;
if (x > -1)
{
canvasX = x;
XtVaSetValues(scrolledWindow,
XmNleftAttachment, XmATTACH_SELF,
XmNx, x, NULL);
}
if (y > -1)
{
canvasY = y;
XtVaSetValues(scrolledWindow,
XmNtopAttachment, XmATTACH_SELF,
XmNy, y, NULL);
}
if (w > -1)
{
canvasWidth = w;
XtVaSetValues(scrolledWindow, XmNwidth, w, NULL);
if (!hScroll)
XtVaSetValues(drawingArea, XmNwidth, w - SCROLL_MARGIN, NULL);
}
if (h > -1)
{
canvasHeight = h;
XtVaSetValues(scrolledWindow, XmNheight, h, NULL);
if (!vScroll)
XtVaSetValues(drawingArea, XmNheight, h - SCROLL_MARGIN, NULL);
}
allowRepainting = FALSE;
XSync(XtDisplay(drawingArea), FALSE);
XEvent event;
while (XtAppPending(wxTheApp->appContext))
{
XFlush(XtDisplay(drawingArea));
XtAppNextEvent(wxTheApp->appContext, &event);
XtDispatchEvent(&event);
}
allowRepainting = TRUE;
Refresh();
#endif
#ifdef wx_xview
int real_y = y;
if (window_parent)
real_y += ((wxFrame *)window_parent)->y_offset; // Allow for possible menu bar
Xv_opaque object = (Xv_opaque)handle;
(void)xv_set(object, XV_X, x, XV_Y, real_y, XV_WIDTH, w, XV_HEIGHT, h, NULL);
#endif
#ifdef wx_msw
int currentX, currentY;
GetPosition(¤tX, ¤tY);
if (x == -1)
x = currentX;
if (y == -1)
y = currentY;
wxWnd *wnd = (wxWnd *)handle;
if (wnd)
MoveWindow(wnd->handle, x, y, w, h, TRUE);
#endif
OnSize(w, h);
}
void wxCanvas::GetSize(int *w, int *h)
{
#ifdef wx_motif
// XtVaGetValues(scrolledWindow, XmNwidth, w, XmNheight, h, NULL);
*w = canvasWidth;
*h = canvasHeight;
#else
wxWindow::GetSize(w, h);
#endif
}
void wxCanvas::GetPosition(int *x, int *y)
{
#ifdef wx_motif
// XtVaGetValues(scrolledWindow, XmNx, x, XmNy, y, NULL);
*x = canvasX;
*y = canvasY;
#else
wxWindow::GetPosition(x, y);
#endif
}
#ifdef wx_motif
/* Calls OnPaint or uses retained pixmap,
* as necessary
*/
void wxCanvas::Refresh(void)
{
Dimension canvasWidth2, canvasHeight2;
XtVaGetValues(scrolledWindow, XmNwidth, &canvasWidth2, XmNheight, &canvasHeight2, NULL);
int canvasWidth1 = max(canvasWidth, canvasWidth2);
int canvasHeight1 = max(canvasHeight, canvasHeight2);
if (hScroll)
{
XtVaSetValues(hScrollBar, XmNsliderSize,
(int)(max(min(canvasWidth1/horiz_units, hExtent/horiz_units), 1)), NULL);
}
if (vScroll)
{
XtVaSetValues(vScrollBar, XmNsliderSize,
(int)(max(min(canvasHeight1/vert_units, vExtent/vert_units), 1)), NULL);
}
int x, y;
ViewStart(&x, &y);
if (is_retained && backingPixmap)
{
Widget drawingArea = (Widget)handle;
XCopyArea(XtDisplay(drawingArea), backingPixmap, XtWindow(drawingArea), GetDC()->gc,
pixmapOffsetX, pixmapOffsetY,
pixmapWidth, pixmapHeight,
0, 0);
}
else
{
OnPaint();
}
}
void wxScrollCallback(Widget scrollbar, int orientation, XmScrollBarCallbackStruct *cbs)
{
Widget scrolledWindow = XtParent(scrollbar);
wxCanvas *canvas = (wxCanvas *)wxWidgetHashTable->Get((long)scrolledWindow);
if (canvas)
{
if (orientation == XmHORIZONTAL)
{
if (canvas->hScrollingEnabled && !canvas->is_retained)
canvas->Clear();
if (canvas->GetDC())
canvas->GetDC()->device_origin_x = -(cbs->value * canvas->horiz_units);
if (canvas->is_retained)
canvas->pixmapOffsetX = (cbs->value * canvas->horiz_units);
}
else
{
if (canvas->vScrollingEnabled && !canvas->is_retained)
canvas->Clear();
if (canvas->GetDC())
canvas->GetDC()->device_origin_y = -(cbs->value * canvas->vert_units);
if (canvas->is_retained)
canvas->pixmapOffsetY = (cbs->value * canvas->vert_units);
}
canvas->Refresh();
}
}
#endif
/*
* horizontal/vertical: number of pixels per unit (e.g. pixels per text line)
* x/y_length: : no. units per scrollbar
* x/y_page: : no. units per page scrolled
*/
void wxCanvas::SetScrollbars(int horizontal, int vertical,
int x_length, int y_length,
int x_page, int y_page)
{
horiz_units = horizontal;
vert_units = vertical;
#ifdef wx_motif
Bool scrollingInitialized = (hScrollBar || vScrollBar);
Dimension canvasWidth2, canvasHeight2;
XtVaGetValues(scrolledWindow, XmNwidth, &canvasWidth2, XmNheight, &canvasHeight2, NULL);
int canvasWidth1 = max(canvasWidth, canvasWidth2);
int canvasHeight1 = max(canvasHeight, canvasHeight2);
Widget drawingArea = (Widget)handle;
if (horizontal > 0)
{
hExtent = horizontal*x_length;
if (!hScroll)
{
hScrollBar = XtVaCreateManagedWidget("hsb",
xmScrollBarWidgetClass, scrolledWindow,
XmNorientation, XmHORIZONTAL,
NULL);
XtAddCallback(hScrollBar, XmNvalueChangedCallback, wxScrollCallback, XmHORIZONTAL);
XtAddCallback(hScrollBar, XmNdragCallback, wxScrollCallback, XmHORIZONTAL);
}
XtVaSetValues(hScrollBar,
XmNincrement, 1,
XmNpageIncrement, x_page,
XmNmaximum, x_length,
XmNvalue, 0,
XmNsliderSize, (int)(max(min(canvasWidth1/horizontal, x_length), 1)),
NULL);
if (GetDC())
GetDC()->device_origin_x = 0;
if (is_retained)
pixmapOffsetX = 0;
hScroll = TRUE;
}
else
{
hExtent = 0;
hScroll = FALSE;
}
if (vertical > 0)
{
vExtent = vertical*y_length;
if (!vScroll)
{
vScrollBar = XtVaCreateManagedWidget("vsb",
xmScrollBarWidgetClass, scrolledWindow,
XmNorientation, XmVERTICAL,
NULL);
XtAddCallback(vScrollBar, XmNvalueChangedCallback, wxScrollCallback, XmVERTICAL);
XtAddCallback(vScrollBar, XmNdragCallback, wxScrollCallback, XmVERTICAL);
}
XtVaSetValues(vScrollBar,
XmNincrement, 1,
XmNpageIncrement, y_page,
XmNmaximum, y_length,
XmNvalue, 0,
XmNsliderSize, (int)(max(min(canvasHeight1/vertical, y_length), 1)),
NULL);
if (GetDC())
GetDC()->device_origin_y = 0;
if (is_retained)
pixmapOffsetY = 0;
vScroll = TRUE;
}
else
{
vExtent = 0;
vScroll = FALSE;
}
if (!scrollingInitialized)
{
XmScrolledWindowSetAreas(scrolledWindow, hScrollBar, vScrollBar, drawingArea);
if (hScrollBar)
XtRealizeWidget(hScrollBar);
if (vScrollBar)
XtRealizeWidget(vScrollBar);
}
/*
* Retained pixmap stuff
*
*/
if (is_retained && (hExtent > 0) && (vExtent > 0))
{
if ((hExtent != pixmapWidth) || (vExtent != pixmapHeight))
{
pixmapWidth = hExtent;
pixmapHeight = vExtent;
if (backingPixmap)
XFreePixmap(XtDisplay(drawingArea), backingPixmap);
backingPixmap = XCreatePixmap(XtDisplay(drawingArea),
RootWindowOfScreen(XtScreen(drawingArea)), hExtent, vExtent,
DefaultDepthOfScreen(XtScreen(drawingArea)));
Clear();
OnPaint();
}
}
// This necessary to make scrollbars appear, for some reason!
int w, h, x, y;
GetSize(&w, &h);
GetPosition(&x, &y);
SetSize(x, y, w, h);
#endif
#ifdef wx_xview
Canvas canvas = (Canvas)handle;
if (!horiz_scroll && horizontal > 0)
horiz_scroll = xv_create(canvas, SCROLLBAR,
SCROLLBAR_DIRECTION, SCROLLBAR_HORIZONTAL,NULL);
if (horizontal > 0)
{
int canvas_width = horizontal*x_length + 1;
(void)xv_set(horiz_scroll,
SCROLLBAR_PIXELS_PER_UNIT, horizontal,
SCROLLBAR_OBJECT_LENGTH, x_length,
SCROLLBAR_PAGE_LENGTH, x_page,
SCROLLBAR_VIEW_LENGTH, x_page,
NULL);
(void)xv_set(canvas, CANVAS_WIDTH, canvas_width,
CANVAS_AUTO_EXPAND, FALSE,
CANVAS_AUTO_SHRINK, FALSE,
NULL);
}
if (vertical > 0 && !vert_scroll)
vert_scroll = xv_create(canvas, SCROLLBAR,
SCROLLBAR_DIRECTION, SCROLLBAR_VERTICAL, NULL);
if (vertical > 0)
{
int canvas_height = vertical*y_length + 1;
(void)xv_set(vert_scroll,
SCROLLBAR_PIXELS_PER_UNIT, vertical,
SCROLLBAR_OBJECT_LENGTH, y_length,
SCROLLBAR_PAGE_LENGTH, y_page,
SCROLLBAR_VIEW_LENGTH, y_page,
NULL);
(void)xv_set(canvas, CANVAS_HEIGHT, canvas_height,
CANVAS_AUTO_EXPAND, FALSE,
CANVAS_AUTO_SHRINK, FALSE,
NULL);
}
#endif
#ifdef wx_msw
wxWnd *wnd = (wxWnd *)handle;
if (wnd)
{
wnd->xscroll_pixels_per_line = horizontal;
wnd->yscroll_pixels_per_line = vertical;
wnd->xscroll_lines = x_length;
wnd->yscroll_lines = y_length;
wnd->xscroll_lines_per_page = x_page;
wnd->yscroll_lines_per_page = y_page;
SetScrollRange(wnd->handle, SB_HORZ, 0, x_length, TRUE);
SetScrollRange(wnd->handle, SB_VERT, 0, y_length, TRUE);
}
#endif
}
/*
* Scroll to given position (scroll position, not pixel position)
*/
void wxCanvas::Scroll(int x_pos, int y_pos)
{
int old_x, old_y;
ViewStart(&old_x, &old_y);
if (((x_pos == -1) || (x_pos == old_x)) && ((y_pos == -1) || (y_pos == old_y)))
return;
#ifdef wx_motif
Bool clearCanvas = FALSE;
if (hScroll)
{
XtVaSetValues(hScrollBar, XmNvalue, x_pos, NULL);
if (hScrollingEnabled && !is_retained)
clearCanvas = TRUE;
if (GetDC())
GetDC()->device_origin_x = -(x_pos * horiz_units);
if (is_retained)
pixmapOffsetX = (x_pos * horiz_units);
}
if (vScroll)
{
XtVaSetValues(vScrollBar, XmNvalue, y_pos, NULL);
if (vScrollingEnabled && !is_retained)
clearCanvas = TRUE;
if (GetDC())
GetDC()->device_origin_y = -(y_pos * vert_units);
if (is_retained)
pixmapOffsetY = (y_pos * vert_units);
}
if (clearCanvas)
Clear();
Refresh();
#endif
#ifdef wx_xview
if (x_pos > -1 && horiz_scroll)
(void)xv_set(horiz_scroll, SCROLLBAR_VIEW_START, x_pos, NULL);
if (y_pos > -1 && vert_scroll)
(void)xv_set(vert_scroll, SCROLLBAR_VIEW_START, y_pos, NULL);
#endif
#ifdef wx_msw
wxWnd *wnd = (wxWnd *)handle;
if (x_pos > -1)
{
wnd->xscroll_position = x_pos;
SetScrollPos(wnd->handle, SB_HORZ, x_pos, TRUE );
}
if (y_pos > -1)
{
wnd->yscroll_position = y_pos;
SetScrollPos(wnd->handle, SB_VERT, y_pos, TRUE );
}
InvalidateRect(wnd->handle, NULL, TRUE);
UpdateWindow(wnd->handle);
#endif
}
void wxCanvas::SetCountdown(int n)
{
#ifdef wx_xview
repaint_countdown = n;
#endif
}
void wxCanvas::EnableScrolling(Bool x_scroll, Bool y_scroll)
{
#ifdef wx_motif
hScrollingEnabled = x_scroll;
vScrollingEnabled = y_scroll;
#endif
#ifdef wx_msw
wxWnd *wnd = (wxWnd *)handle;
wnd->x_scrolling_enabled = x_scroll;
wnd->y_scrolling_enabled = y_scroll;
#endif
}
void wxCanvas::GetVirtualSize(int *x, int *y)
{
#ifdef wx_motif
if (hExtent == 0)
*x = canvasWidth;
else
*x = hExtent;
if (vExtent == 0)
*y = canvasHeight;
else
*y = vExtent;
#endif
#ifdef wx_xview
Canvas canvas = (Canvas)handle;
*x = (int)xv_get(canvas, CANVAS_WIDTH);
*y = (int)xv_get(canvas, CANVAS_HEIGHT);
#endif
#ifdef wx_msw
wxWnd *wnd = (wxWnd *)handle;
if (wnd)
{
*x = wnd->xscroll_pixels_per_line * wnd->xscroll_lines;
*y = wnd->yscroll_pixels_per_line * wnd->yscroll_lines;
}
#endif
}
#ifdef wx_xview
void wxCanvasRepaintProc(Canvas x_canvas, Xv_Window paint_win,
Display *display, Window xwin, Xv_xrectlist *xrects)
{
// cout << "Canvas paint: " << xrects->count << " rectangles\n";
wxCanvas *canvas = (wxCanvas *)xv_get(x_canvas, WIN_CLIENT_DATA);
if (canvas && canvas->repaint_countdown > 0)
{
canvas->repaint_countdown --;
return;
}
if (canvas && display && xwin)
{
if (xrects && canvas->is_retained)
{
canvas->xrects = xrects;
XSetClipRectangles(canvas->display, canvas->GetDC()->gc, 0, 0, xrects->rect_array, xrects->count, Unsorted);
}
canvas->paint_window = paint_win;
canvas->display = display;
canvas->xwindow = xwin;
canvas->OnPaint();
canvas->xrects = NULL;
XGCValues gc_val;
gc_val.clip_mask = None;
XChangeGC(canvas->display, canvas->GetDC()->gc, GCClipMask, &gc_val);
}
}
void wxCanvasResizeProc(Canvas x_canvas, int width, int height)
{
wxCanvas *canvas = (wxCanvas *)xv_get(x_canvas, WIN_CLIENT_DATA);
if (canvas)
{
Xv_Window pw = canvas_paint_window(x_canvas);
canvas->paint_window = pw;
canvas->xwindow = (Window)xv_get(pw, XV_XID);
canvas->OnSize(width, height);
}
}
void wxCanvasEventProc(Xv_Window window, Event *x_event, Notify_arg arg)
{
wxCanvas *canvas = (wxCanvas *)xv_get(window, WIN_CLIENT_DATA);
if (canvas)
{
canvas->paint_window = window;
canvas->xwindow = (Window)xv_get(window, XV_XID);
if (event_id(x_event) == KBD_USE)
canvas->OnSetFocus();
else if (event_id(x_event) == KBD_DONE)
canvas->OnKillFocus();
else if (event_is_ascii(x_event))
{
canvas->OnChar(x_event->ie_code);
}
else
{
wxEvent event(x_event);
if (canvas->GetDC())
{
event.x = canvas->GetDC()->DeviceToLogicalX(event_x(x_event));
event.y = canvas->GetDC()->DeviceToLogicalY(event_y(x_event));
}
if (event.Dragging())
{
// Don't respond to ALL drag events since we can't necessarily
// keep up with them (dependent on application, really - define
// DRAG_MAX differently if necessary)
if (canvas->drag_count > 0)
{
canvas->drag_count --;
}
else
{
canvas->drag_count = canvas->DRAG_MAX;
canvas->OnEvent(event);
}
}
else canvas->OnEvent(event);
}
}
}
#endif
#ifdef wx_motif
void wxCanvasRepaintProc(Widget drawingArea, XtPointer clientData, XmDrawingAreaCallbackStruct *cbs)
{
wxCanvas *canvas = (wxCanvas *)clientData;
if (canvas && (cbs->reason == XmCR_EXPOSE) && canvas->allowRepainting)
{
// cout << "Canvas repaint\n";
canvas->display = XtDisplay(drawingArea);
canvas->Refresh();
}
}
void wxCanvasKeyEvent(Widget drawingArea, XKeyEvent *event)
{
wxCanvas *canvas = (wxCanvas *)wxWidgetHashTable->Get((long)drawingArea);
switch (event->type)
{
case KeyPress:
{
KeySym keySym;
XComposeStatus compose;
(void)XLookupString(event, wxBuffer, 20, &keySym, &compose);
canvas->OnChar(wxBuffer[0]);
break;
}
case FocusIn:
{
canvas->OnSetFocus();
break;
}
case FocusOut:
{
canvas->OnKillFocus();
}
}
}
void wxCanvasInputEvent(Widget drawingArea, XButtonEvent *event)
{
wxCanvas *canvas = (wxCanvas *)wxWidgetHashTable->Get((long)drawingArea);
switch (event->type)
{
case ButtonPress:
case ButtonRelease:
case MotionNotify:
{
wxEvent wxevent;
wxevent.event_handle = event;
if (canvas->GetDC())
{
wxevent.x = canvas->GetDC()->DeviceToLogicalX(event->x);
wxevent.y = canvas->GetDC()->DeviceToLogicalY(event->y);
}
if (event->type == ButtonPress)
{
if (event->button == Button1)
canvas->button1Pressed = TRUE;
else if (event->button == Button2)
canvas->button2Pressed = TRUE;
else if (event->button == Button3)
canvas->button3Pressed = TRUE;
}
else if (event->type == ButtonRelease)
{
if (event->button == Button1)
canvas->button1Pressed = FALSE;
else if (event->button == Button2)
canvas->button2Pressed = FALSE;
else if (event->button == Button3)
canvas->button3Pressed = FALSE;
}
wxevent.button1Pressed = canvas->button1Pressed;
wxevent.button2Pressed = canvas->button2Pressed;
wxevent.button3Pressed = canvas->button3Pressed;
canvas->OnEvent(wxevent);
break;
}
}
}
#endif
// Where the current view starts from
void wxCanvas::ViewStart(int *x, int *y)
{
#ifdef wx_motif
int xx, yy;
if (hScroll)
XtVaGetValues(hScrollBar, XmNvalue, &xx, NULL);
else xx = 0;
if (vScroll)
XtVaGetValues(vScrollBar, XmNvalue, &yy, NULL);
else yy = 0;
*x = xx;
*y = yy;
#endif
#ifdef wx_xview
if (horiz_scroll)
*x = (int)xv_get(horiz_scroll, SCROLLBAR_VIEW_START);
else *x = 0;
if (vert_scroll)
*y = (int)xv_get(vert_scroll, SCROLLBAR_VIEW_START);
else *y = 0;
#endif
#ifdef wx_msw
wxWnd *wnd = (wxWnd *)handle;
*x = wnd->xscroll_position;
*y = wnd->yscroll_position;
#endif
}
// Use this to set the canvas's 'context' member to
// a user-supplied dc
void wxCanvas::SetContext(wxDC *dc)
{
context = dc;
}
// Reset 'context' back to the canvas' context
void wxCanvas::ResetContext(void)
{
context = wx_dc;
}
void wxCanvas::Clear(void)
{
wx_dc->Clear();
}
void wxCanvas::DrawLine(float x1, float y1, float x2, float y2)
{
wx_dc->DrawLine(x1, y1, x2, y2);
}
void wxCanvas::DrawPoint(float x, float y)
{
wx_dc->DrawPoint(x, y);
}
void wxCanvas::DrawPolygon(int n, wxPoint points[], float xoffset, float yoffset)
{
wx_dc->DrawPolygon(n, points, xoffset, yoffset);
}
void wxCanvas::DrawPolygon(wxList *list, float xoffset, float yoffset)
{
wx_dc->DrawPolygon(list, xoffset, yoffset);
}
void wxCanvas::DrawLines(int n, wxPoint points[], float xoffset, float yoffset)
{
wx_dc->DrawLines(n, points, xoffset, yoffset);
}
void wxCanvas::DrawLines(wxList *list, float xoffset, float yoffset)
{
wx_dc->DrawLines(list, xoffset, yoffset);
}
void wxCanvas::DrawRectangle(float x, float y, float width, float height)
{
wx_dc->DrawRectangle(x, y, width, height);
}
void wxCanvas::DrawRoundedRectangle(float x, float y, float width, float height, float radius)
{
wx_dc->DrawRoundedRectangle(x, y, width, height, radius);
}
void wxCanvas::DrawEllipse(float x, float y, float width, float height)
{
wx_dc->DrawEllipse(x, y, width, height);
}
void wxCanvas::SetFont(wxFont *the_font)
{
wx_dc->SetFont(the_font);
}
void wxCanvas::SetPen(wxPen *pen)
{
wx_dc->SetPen(pen);
}
void wxCanvas::SetTextForeground(wxColour *colour)
{
wx_dc->SetTextForeground(colour);
}
void wxCanvas::SetTextBackground(wxColour *colour)
{
wx_dc->SetTextBackground(colour);
}
void wxCanvas::SetBrush(wxBrush *brush)
{
wx_dc->SetBrush(brush);
}
void wxCanvas::DrawText(char *text, float x, float y)
{
wx_dc->DrawText(text, x, y);
}
void wxCanvas::SetBackground(wxBrush *brush)
{
wx_dc->SetBackground(brush);
}
void wxCanvas::SetLogicalFunction(int function)
{
wx_dc->SetLogicalFunction(function);
}
// Make a 3-point spline
void wxCanvas::DrawSpline(float x1, float y1, float x2, float y2, float x3, float y3)
{
wx_dc->DrawSpline(x1, y1, x2, y2, x3, y3);
}
void wxCanvas::DrawSpline(wxList *list)
{
wx_dc->DrawSpline(list);
}
int wxCanvas::GetTextFamily(void)
{
return wx_dc->GetTextFamily();
}
int wxCanvas::GetTextStyle(void)
{
return wx_dc->GetTextStyle();
}
int wxCanvas::GetTextWeight(void)
{
return wx_dc->GetTextWeight();
}
float wxCanvas::GetTextHeight(void)
{
return wx_dc->GetTextHeight();
}
float wxCanvas::GetTextWidth(void)
{
return wx_dc->GetTextWidth();
}
void wxCanvas::GetTextExtent(char *string, float *x, float *y)
{
wx_dc->GetTextExtent(string, x, y);
}
#ifdef wx_msw
void wxWnd::DeviceToLogical(float *x, float *y)
{
if (is_canvas)
{
wxCanvas *canvas = (wxCanvas *)wx_window;
*x = canvas->wx_dc->DeviceToLogicalX((int)*x);
*y = canvas->wx_dc->DeviceToLogicalY((int)*y);
}
}
wxCanvasWnd::wxCanvasWnd(wxWnd *parent, wxWindow *wx_win,
int x, int y, int width, int height, DWORD style):
wxSubWnd(parent, "wxCanvasClass", wx_win, x, y, width, height, style)
{
is_canvas = TRUE;
// ShowScrollBar(handle, SB_BOTH, TRUE);
}
BOOL wxCanvasWnd::OnEraseBkgnd(HDC pDC)
{
if (background_brush)
{
RECT rect;
GetClientRect(handle, &rect);
int mode = SetMapMode(pDC, MM_TEXT);
FillRect(pDC, &rect, background_brush);
SetMapMode(pDC, mode);
wxCanvas *canvas = (wxCanvas *)wx_window;
SetViewportExtEx(pDC, VIEWPORT_EXTENT, VIEWPORT_EXTENT, NULL);
SetWindowExtEx(pDC, canvas->wx_dc->window_ext_x, canvas->wx_dc->window_ext_y, NULL);
return TRUE;
}
else return FALSE;
}
#endif