123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582 |
- /* GuiDrawingArea.cpp
- *
- * Copyright (C) 1993-2012,2013,2015,2016,2017 Paul Boersma,
- * 2008 Stefan de Konink, 2010 Franz Brausse, 2013 Tom Naughton
- *
- * This code is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * This code is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this work. If not, see <http://www.gnu.org/licenses/>.
- */
- #include "GuiP.h"
- #if gtk
- #include "gdk/gdkkeysyms.h"
- #include <locale.h>
- #endif
- Thing_implement (GuiDrawingArea, GuiControl, 0);
- #if motif
- #define iam_drawingarea \
- Melder_assert (widget -> widgetClass == xmDrawingAreaWidgetClass); \
- GuiDrawingArea me = (GuiDrawingArea) widget -> userData
- #else
- #define iam_drawingarea \
- GuiDrawingArea me = (GuiDrawingArea) _GuiObject_getUserData (widget)
- #endif
- #if gtk
- static void _GuiGtkDrawingArea_destroyCallback (GuiObject widget, gpointer void_me) {
- (void) widget;
- iam (GuiDrawingArea);
- forget (me);
- }
- static gboolean _GuiGtkDrawingArea_exposeCallback (GuiObject widget, GdkEventExpose *expose, gpointer void_me) {
- trace (U"begin");
- iam (GuiDrawingArea);
- Melder_assert (me);
- // TODO: that helps against the damaged regions outside the rect where the
- // Graphics drawing is done, but where does that margin come from in the
- // first place?? Additionally this causes even more flickering
- //gdk_window_clear_area ((GTK_WIDGET (widget)) -> window, expose->area.x, expose->area.y, expose->area.width, expose->area.height);
- if (my d_exposeCallback) {
- struct structGuiDrawingArea_ExposeEvent event { me, 0 };
- event. x = expose -> area. x;
- event. y = expose -> area. y;
- event. width = expose -> area. width;
- event. height = expose -> area. height;
- try {
- //GdkRectangle rect = { event. x, event. y, event. width, event. height };
- //gdk_window_begin_paint_rect ((GTK_WIDGET (widget)) -> window, & rect);
- trace (U"send the expose callback");
- trace (U"locale is ", Melder_peek8to32 (setlocale (LC_ALL, nullptr)));
- my d_exposeCallback (my d_exposeBoss, & event);
- trace (U"the expose callback finished");
- trace (U"locale is ", Melder_peek8to32 (setlocale (LC_ALL, nullptr)));
- //gdk_window_end_paint ((GTK_WIDGET (widget)) -> window);
- //gdk_window_flush ((GTK_WIDGET (widget)) -> window);
- //gdk_flush ();
- } catch (MelderError) {
- Melder_flushError (U"Redrawing not completed");
- }
- trace (U"the expose callback handled drawing");
- return true;
- }
- trace (U"GTK will handle redrawing");
- return false;
- }
- static gboolean _GuiGtkDrawingArea_clickCallback (GuiObject widget, GdkEvent *e, gpointer void_me) {
- iam (GuiDrawingArea);
- if (e -> type != GDK_BUTTON_PRESS) return false;
- if (my d_clickCallback) {
- struct structGuiDrawingArea_ClickEvent event { me, 0 };
- event. button = ((GdkEventButton *) e) -> button;
- event. x = ((GdkEventButton *) e) -> x;
- event. y = ((GdkEventButton *) e) -> y;
- event. shiftKeyPressed = (((GdkEventButton *) e) -> state & GDK_SHIFT_MASK) != 0;
- event. commandKeyPressed = (((GdkEventButton *) e) -> state & GDK_CONTROL_MASK) != 0;
- event. optionKeyPressed = (((GdkEventButton *) e) -> state & GDK_MOD1_MASK) != 0;
- try {
- my d_clickCallback (my d_clickBoss, & event);
- } catch (MelderError) {
- Melder_flushError (U"Mouse click not completely handled.");
- }
- return true;
- }
- return false;
- }
- static gboolean _GuiGtkDrawingArea_keyCallback (GuiObject widget, GdkEvent *gevent, gpointer void_me) {
- iam (GuiDrawingArea);
- trace (U"begin");
- if (my d_keyCallback && gevent -> type == GDK_KEY_PRESS) {
- struct structGuiDrawingArea_KeyEvent event { me, 0 };
- GdkEventKey *gkeyEvent = (GdkEventKey *) gevent;
- event. key = gkeyEvent -> keyval;
- /*
- * Translate with the help of /usr/include/gtk-2.0/gdk/gdkkeysyms.h
- */
- if (event. key == GDK_KEY_Escape) event. key = 27;
- if (event. key == GDK_KEY_Left) event. key = 0x2190;
- if (event. key == GDK_KEY_Up) event. key = 0x2191;
- if (event. key == GDK_KEY_Right) event. key = 0x2192;
- if (event. key == GDK_KEY_Down) event. key = 0x2193;
- event. shiftKeyPressed = (gkeyEvent -> state & GDK_SHIFT_MASK) != 0;
- event. commandKeyPressed = (gkeyEvent -> state & GDK_CONTROL_MASK) != 0;
- event. optionKeyPressed = (gkeyEvent -> state & GDK_MOD1_MASK) != 0;
- event. extraControlKeyPressed = false;
- try {
- my d_keyCallback (my d_keyBoss, & event);
- } catch (MelderError) {
- Melder_flushError (U"Key press not completely handled.");
- }
- /*
- * FIXME: here we should empty the type-ahead buffer
- */
- return true;
- }
- return false; // if the drawing area has no keyCallback, the system will send the key press to a text field.
- }
- static gboolean _GuiGtkDrawingArea_resizeCallback (GuiObject widget, GtkAllocation *allocation, gpointer void_me) {
- iam (GuiDrawingArea);
- if (my d_resizeCallback) {
- struct structGuiDrawingArea_ResizeEvent event { me, 0 };
- trace (U"drawingArea resized to ", allocation -> width, U" x ", allocation -> height, U".");
- event. width = allocation -> width;
- event. height = allocation -> height;
- //g_debug("%d %d", allocation->width, allocation->height);
- try {
- my d_resizeCallback (my d_resizeBoss, & event);
- } catch (MelderError) {
- Melder_flushError (U"Window resizing not completely handled.");
- }
- return true;
- }
- return false;
- }
- #elif motif
- void _GuiWinDrawingArea_destroy (GuiObject widget) {
- iam_drawingarea;
- DestroyWindow (widget -> window);
- forget (me); // NOTE: my widget is not destroyed here
- }
- void _GuiWinDrawingArea_update (GuiObject widget) {
- iam_drawingarea;
- PAINTSTRUCT paintStruct;
- BeginPaint (widget -> window, & paintStruct);
- if (my d_exposeCallback) {
- struct structGuiDrawingArea_ExposeEvent event { me };
- try {
- my d_exposeCallback (my d_exposeBoss, & event);
- } catch (MelderError) {
- Melder_flushError (U"Redrawing not completed");
- }
- }
- EndPaint (widget -> window, & paintStruct);
- }
- void _GuiWinDrawingArea_handleClick (GuiObject widget, int x, int y) {
- iam_drawingarea;
- if (my d_clickCallback) {
- struct structGuiDrawingArea_ClickEvent event { me, 0 };
- event. x = x;
- event. y = y;
- event. shiftKeyPressed = GetKeyState (VK_SHIFT) < 0;
- event. optionKeyPressed = GetKeyState (VK_MENU) < 0;
- event. commandKeyPressed = GetKeyState (VK_CONTROL) < 0;
- try {
- my d_clickCallback (my d_clickBoss, & event);
- } catch (MelderError) {
- Melder_flushError (U"Mouse click not completely handled.");
- }
- }
- }
- void _GuiWinDrawingArea_handleKey (GuiObject widget, TCHAR kar) { // TODO: event?
- iam_drawingarea;
- if (my d_keyCallback) {
- struct structGuiDrawingArea_KeyEvent event { me, 0 };
- event. key = kar;
- if (event. key == VK_RETURN) event. key = 10;
- if (event. key == VK_LEFT) event. key = 0x2190;
- if (event. key == VK_RIGHT) event. key = 0x2192;
- if (event. key == VK_UP) event. key = 0x2191;
- if (event. key == VK_DOWN) event. key = 0x2193;
- event. shiftKeyPressed = GetKeyState (VK_SHIFT) < 0; // TODO: event -> key?
- event. optionKeyPressed = GetKeyState (VK_MENU) < 0;
- event. commandKeyPressed = GetKeyState (VK_CONTROL) < 0;
- try {
- my d_keyCallback (my d_keyBoss, & event);
- } catch (MelderError) {
- Melder_flushError (U"Key press not completely handled.");
- }
- }
- }
- void _GuiWinDrawingArea_shellResize (GuiObject widget) {
- iam_drawingarea;
- if (my d_resizeCallback) {
- struct structGuiDrawingArea_ResizeEvent event { me };
- event. width = widget -> width;
- event. height = widget -> height;
- try {
- my d_resizeCallback (my d_resizeBoss, & event);
- } catch (MelderError) {
- Melder_flushError (U"Window resizing not completely handled.");
- }
- }
- }
- #elif cocoa
- @interface GuiCocoaDrawingArea ()
- @property (nonatomic, assign) BOOL inited;
- @property (nonatomic, retain) NSTrackingArea *trackingArea;
- @end
- @implementation GuiCocoaDrawingArea {
- GuiDrawingArea d_userData;
- }
- - (id) initWithFrame: (NSRect) frame {
- self = [super initWithFrame: frame];
- if (self) {
- _trackingArea = [[[NSTrackingArea alloc]
- initWithRect: [self visibleRect]
- options: NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved | NSTrackingInVisibleRect | NSTrackingActiveAlways
- owner: self
- userInfo: nil]
- autorelease];
- [self addTrackingArea: _trackingArea];
- }
- return self;
- }
- - (void) dealloc { // override
- GuiDrawingArea me = d_userData;
- forget (me);
- [self removeTrackingArea: _trackingArea];
- trace (U"deleting a drawing area");
- [super dealloc];
- }
- - (GuiThing) getUserData {
- return d_userData;
- }
- - (void) setUserData: (GuiThing) userData {
- d_userData = static_cast <GuiDrawingArea> (userData);
- }
- - (void) resizeCallback: (NSRect) rect {
- GuiDrawingArea me = (GuiDrawingArea) d_userData;
- if (me && my d_resizeCallback) {
- struct structGuiDrawingArea_ResizeEvent event = { me, 0, 0 };
- event. width = rect. size. width;
- event. height = rect. size. height;
- try {
- my d_resizeCallback (my d_resizeBoss, & event);
- } catch (MelderError) {
- Melder_flushError (U"Window resizing not completely handled.");
- }
- }
- }
- - (void) drawRect: (NSRect) dirtyRect {
- trace (U"dirtyRect: ", dirtyRect.origin.x, U", ", dirtyRect.origin.y, U", ", dirtyRect.size.width, U", ", dirtyRect.size.height);
- GuiDrawingArea me = (GuiDrawingArea) d_userData;
- if (! _inited) {
- // Last chance to do this. Is there a better place?
- [self resizeCallback: self. frame];
- _inited = YES;
- }
- if (my d_exposeCallback) {
- struct structGuiDrawingArea_ExposeEvent event = { me, 0, 0, 0, 0 };
- try {
- my d_exposeCallback (my d_exposeBoss, & event);
- } catch (MelderError) {
- Melder_flushError (U"Redrawing not completed");
- }
- }
- }
- - (void) setFrame: (NSRect) rect {
- [self resizeCallback: rect];
- [super setFrame: rect];
- }
- - (BOOL) acceptsFirstResponder {
- /*
- * This overridden method tells the event chain whether the drawing area can accept key events.
- * It is important that the Demo window and the RunnerMFC window accept key events.
- * A side effect of accepting key events is that the drawing area obtains the key focus when the user clicks in the drawing area.
- * It is important, however, that the drawing area of the TextGrid window cannot take away the key focus
- * from the text field at the top; therefore, that drawing area should not accept key events.
- * The implementation below is based on the fact that, naturally, the Demo window and the RunnerMFC window
- * have a key callback, and the drawing area of the TextGrid window has not
- * (a side effect of this implementation is that the drawing area of the Manual window does not take away
- * the key focus from the Search field, a situation that cannot hurt).
- */
- GuiDrawingArea me = (GuiDrawingArea) d_userData;
- return !! my d_keyCallback;
- }
- - (void) mouseEntered: (NSEvent *) nsEvent {
- (void) nsEvent;
- [[NSCursor crosshairCursor] push];
- }
- - (void) mouseExited: (NSEvent *) nsEvent{
- (void) nsEvent;
- [[NSCursor currentCursor] pop];
- }
- - (void) mouseDown: (NSEvent *) nsEvent {
- // [self becomeFirstResponder];
- GuiDrawingArea me = (GuiDrawingArea) d_userData;
- if (my d_clickCallback) {
- struct structGuiDrawingArea_ClickEvent event = { me, 0, 0, false, false, false, false, 0 };
- NSPoint local_point = [self convertPoint: [nsEvent locationInWindow] fromView: nil];
- event. x = local_point. x;
- //event. y = [self frame]. size. height - local_point. y;
- event. y = local_point. y;
- NSUInteger modifiers = [nsEvent modifierFlags];
- event. shiftKeyPressed = modifiers & NSShiftKeyMask;
- event. optionKeyPressed = modifiers & NSAlternateKeyMask;
- event. commandKeyPressed = modifiers & NSCommandKeyMask;
- try {
- my d_clickCallback (my d_clickBoss, & event);
- } catch (MelderError) {
- Melder_flushError (U"Mouse click not completely handled.");
- }
- }
- }
- - (void) scrollWheel: (NSEvent *) nsEvent {
- GuiDrawingArea me = (GuiDrawingArea) d_userData;
- if (my d_horizontalScrollBar || my d_verticalScrollBar) {
- if (my d_horizontalScrollBar) {
- GuiCocoaScrollBar *cocoaScrollBar = (GuiCocoaScrollBar *) my d_horizontalScrollBar -> d_widget;
- [cocoaScrollBar scrollBy: [nsEvent scrollingDeltaX]];
- }
- if (my d_verticalScrollBar) {
- GuiCocoaScrollBar *cocoaScrollBar = (GuiCocoaScrollBar *) my d_verticalScrollBar -> d_widget;
- [cocoaScrollBar scrollBy: [nsEvent scrollingDeltaY]];
- }
- } else {
- [super scrollWheel: nsEvent];
- }
- }
- - (void) magnifyWithEvent: (NSEvent *) nsEvent {
- GuiDrawingArea me = (GuiDrawingArea) d_userData;
- if (my d_horizontalScrollBar || my d_verticalScrollBar) {
- if (my d_horizontalScrollBar) {
- GuiCocoaScrollBar *cocoaScrollBar = (GuiCocoaScrollBar *) my d_horizontalScrollBar -> d_widget;
- [cocoaScrollBar magnifyBy: [nsEvent magnification]];
- }
- if (my d_verticalScrollBar) {
- GuiCocoaScrollBar *cocoaScrollBar = (GuiCocoaScrollBar *) my d_verticalScrollBar -> d_widget;
- [cocoaScrollBar magnifyBy: [nsEvent magnification]];
- }
- } else {
- [super magnifyWithEvent: nsEvent];
- }
- }
- - (BOOL) isFlipped {
- return YES;
- }
- - (void) keyDown: (NSEvent *) nsEvent {
- GuiDrawingArea me = (GuiDrawingArea) d_userData;
- if (my d_keyCallback) {
- struct structGuiDrawingArea_KeyEvent event = { me, U'\0', false, false, false, false };
- event. key = [[nsEvent charactersIgnoringModifiers] characterAtIndex: 0];
- if (event. key == NSLeftArrowFunctionKey) event. key = 0x2190;
- if (event. key == NSRightArrowFunctionKey) event. key = 0x2192;
- if (event. key == NSUpArrowFunctionKey) event. key = 0x2191;
- if (event. key == NSDownArrowFunctionKey) event. key = 0x2193;
- trace (U"key ", event. key);
- NSUInteger modifiers = [nsEvent modifierFlags];
- event. shiftKeyPressed = modifiers & NSShiftKeyMask;
- event. optionKeyPressed = modifiers & NSAlternateKeyMask;
- event. commandKeyPressed = modifiers & NSCommandKeyMask;
- try {
- my d_keyCallback (my d_keyBoss, & event);
- } catch (MelderError) {
- Melder_flushError (U"Key press not completely handled.");
- }
- }
- }
- @end
- #endif
- #if gtk
- static gboolean _guiGtkDrawingArea_swipeCallback (GuiObject w, GdkEventScroll *event, gpointer void_me) {
- iam (GuiDrawingArea);
- if (my d_horizontalScrollBar) {
- double hv = gtk_range_get_value (GTK_RANGE (my d_horizontalScrollBar -> d_widget));
- GtkAdjustment *adjustment = gtk_range_get_adjustment (GTK_RANGE (my d_horizontalScrollBar -> d_widget));
- gdouble hi;
- g_object_get (adjustment, "step_increment", & hi, nullptr);
- switch (event -> direction) {
- case GDK_SCROLL_LEFT:
- gtk_range_set_value (GTK_RANGE (my d_horizontalScrollBar -> d_widget), hv - hi);
- break;
- case GDK_SCROLL_RIGHT:
- gtk_range_set_value (GTK_RANGE (my d_horizontalScrollBar -> d_widget), hv + hi);
- break;
- }
- }
- if (my d_verticalScrollBar) {
- double vv = gtk_range_get_value (GTK_RANGE (my d_verticalScrollBar -> d_widget));
- GtkAdjustment *adjustment = gtk_range_get_adjustment (GTK_RANGE (my d_verticalScrollBar -> d_widget));
- gdouble vi;
- g_object_get (adjustment, "step_increment", & vi, nullptr);
- switch (event -> direction) {
- case GDK_SCROLL_UP:
- gtk_range_set_value (GTK_RANGE (my d_verticalScrollBar -> d_widget), vv - vi);
- break;
- case GDK_SCROLL_DOWN:
- gtk_range_set_value (GTK_RANGE (my d_verticalScrollBar -> d_widget), vv + vi);
- break;
- }
- }
- return true;
- }
- #endif
- GuiDrawingArea GuiDrawingArea_create (GuiForm parent, int left, int right, int top, int bottom,
- GuiDrawingArea_ExposeCallback exposeCallback,
- GuiDrawingArea_ClickCallback clickCallback,
- GuiDrawingArea_KeyCallback keyCallback,
- GuiDrawingArea_ResizeCallback resizeCallback, Thing boss,
- uint32 /* flags */)
- {
- autoGuiDrawingArea me = Thing_new (GuiDrawingArea);
- my d_shell = parent -> d_shell;
- my d_parent = parent;
- my d_exposeCallback = exposeCallback;
- my d_exposeBoss = boss;
- my d_clickCallback = clickCallback;
- my d_clickBoss = boss;
- my d_keyCallback = keyCallback;
- my d_keyBoss = boss;
- my d_resizeCallback = resizeCallback;
- my d_resizeBoss = boss;
- #if gtk
- my d_widget = gtk_drawing_area_new ();
- GdkEventMask mask = (GdkEventMask) (GDK_EXPOSURE_MASK // receive exposure events
- | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK // receive click events
- | GDK_BUTTON_MOTION_MASK // receive motion notifies when a button is pressed
- | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK
- | GDK_POINTER_MOTION_HINT_MASK); // receive fewer motion notify events (the cb might take time)
- gtk_widget_set_events (GTK_WIDGET (my d_widget), mask);
- g_signal_connect (G_OBJECT (my d_widget), "expose-event", G_CALLBACK (_GuiGtkDrawingArea_exposeCallback), me.get());
- g_signal_connect (G_OBJECT (my d_widget), "destroy", G_CALLBACK (_GuiGtkDrawingArea_destroyCallback), me.get());
- g_signal_connect (G_OBJECT (my d_widget), "button-press-event", G_CALLBACK (_GuiGtkDrawingArea_clickCallback), me.get());
- g_signal_connect (G_OBJECT (my d_widget), "button-release-event", G_CALLBACK (_GuiGtkDrawingArea_clickCallback), me.get());
- g_signal_connect (G_OBJECT (my d_widget), "motion-notify-event", G_CALLBACK (_GuiGtkDrawingArea_clickCallback), me.get());
- if (parent) {
- Melder_assert (parent -> d_widget);
- g_signal_connect (G_OBJECT (gtk_widget_get_toplevel (GTK_WIDGET (parent -> d_widget))), "key-press-event",
- G_CALLBACK (_GuiGtkDrawingArea_keyCallback), me.get());
- }
- g_signal_connect (G_OBJECT (my d_widget), "size-allocate", G_CALLBACK (_GuiGtkDrawingArea_resizeCallback), me.get());
- _GuiObject_setUserData (my d_widget, me.get());
- my v_positionInForm (my d_widget, left, right, top, bottom, parent);
- gtk_widget_set_double_buffered (GTK_WIDGET (my d_widget), false);
- #elif motif
- my d_widget = _Gui_initializeWidget (xmDrawingAreaWidgetClass, parent -> d_widget, U"drawingArea");
- _GuiObject_setUserData (my d_widget, me.get());
- my d_widget -> window = CreateWindowEx (0, Melder_peek32toW (_GuiWin_getDrawingAreaClassName ()), L"drawingArea",
- WS_CHILD | WS_BORDER | WS_CLIPSIBLINGS,
- my d_widget -> x, my d_widget -> y, my d_widget -> width, my d_widget -> height, my d_widget -> parent -> window, nullptr, theGui.instance, nullptr);
- SetWindowLongPtr (my d_widget -> window, GWLP_USERDATA, (LONG_PTR) my d_widget);
- my v_positionInForm (my d_widget, left, right, top, bottom, parent);
- #elif cocoa
- GuiCocoaDrawingArea *drawingArea = [[GuiCocoaDrawingArea alloc] init];
- my d_widget = (GuiObject) drawingArea;
- my v_positionInForm (my d_widget, left, right, top, bottom, parent);
- [drawingArea setUserData: me.get()];
- if (keyCallback) {
- [[drawingArea window] makeFirstResponder: drawingArea]; // needed in DemoWindow
- }
- #endif
- return me.releaseToAmbiguousOwner();
- }
- GuiDrawingArea GuiDrawingArea_createShown (GuiForm parent, int left, int right, int top, int bottom,
- GuiDrawingArea_ExposeCallback exposeCallback,
- GuiDrawingArea_ClickCallback clickCallback,
- GuiDrawingArea_KeyCallback keyCallback,
- GuiDrawingArea_ResizeCallback resizeCallback, Thing boss,
- uint32 flags)
- {
- GuiDrawingArea me = GuiDrawingArea_create (parent, left, right, top, bottom, exposeCallback, clickCallback, keyCallback, resizeCallback, boss, flags);
- GuiThing_show (me);
- return me;
- }
- GuiDrawingArea GuiDrawingArea_create (GuiScrolledWindow parent, int width, int height,
- GuiDrawingArea_ExposeCallback exposeCallback,
- GuiDrawingArea_ClickCallback clickCallback,
- GuiDrawingArea_KeyCallback keyCallback,
- GuiDrawingArea_ResizeCallback resizeCallback, Thing boss,
- uint32 /* flags */)
- {
- autoGuiDrawingArea me = Thing_new (GuiDrawingArea);
- my d_shell = parent -> d_shell;
- my d_parent = parent;
- my d_exposeCallback = exposeCallback;
- my d_exposeBoss = boss;
- my d_clickCallback = clickCallback;
- my d_clickBoss = boss;
- my d_keyCallback = keyCallback;
- my d_keyBoss = boss;
- my d_resizeCallback = resizeCallback;
- my d_resizeBoss = boss;
- #if gtk
- my d_widget = gtk_drawing_area_new ();
- GdkEventMask mask = (GdkEventMask) (GDK_EXPOSURE_MASK // receive exposure events
- | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK // receive click events
- | GDK_BUTTON_MOTION_MASK // receive motion notifies when a button is pressed
- | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK
- | GDK_POINTER_MOTION_HINT_MASK); // receive fewer motion notify events (the cb might take time)
- gtk_widget_set_events (GTK_WIDGET (my d_widget), mask);
- g_signal_connect (G_OBJECT (my d_widget), "expose-event", G_CALLBACK (_GuiGtkDrawingArea_exposeCallback), me.get());
- g_signal_connect (G_OBJECT (my d_widget), "destroy", G_CALLBACK (_GuiGtkDrawingArea_destroyCallback), me.get());
- g_signal_connect (G_OBJECT (my d_widget), "button-press-event", G_CALLBACK (_GuiGtkDrawingArea_clickCallback), me.get());
- g_signal_connect (G_OBJECT (my d_widget), "button-release-event", G_CALLBACK (_GuiGtkDrawingArea_clickCallback), me.get());
- g_signal_connect (G_OBJECT (my d_widget), "motion-notify-event", G_CALLBACK (_GuiGtkDrawingArea_clickCallback), me.get());
- if (parent) {
- g_signal_connect (G_OBJECT (gtk_widget_get_toplevel (GTK_WIDGET (parent -> d_widget))), "key-press-event",
- G_CALLBACK (_GuiGtkDrawingArea_keyCallback), me.get());
- }
- g_signal_connect (G_OBJECT (my d_widget), "size-allocate", G_CALLBACK (_GuiGtkDrawingArea_resizeCallback), me.get());
- _GuiObject_setUserData (my d_widget, me.get());
- my v_positionInScrolledWindow (my d_widget, width, height, parent);
- gtk_widget_set_double_buffered (GTK_WIDGET (my d_widget), false);
- #elif motif
- my d_widget = _Gui_initializeWidget (xmDrawingAreaWidgetClass, parent -> d_widget, U"drawingArea");
- _GuiObject_setUserData (my d_widget, me.get());
- my d_widget -> window = CreateWindowEx (0, Melder_peek32toW (_GuiWin_getDrawingAreaClassName ()), L"drawingArea",
- WS_CHILD | WS_BORDER | WS_CLIPSIBLINGS,
- 0, 0, my d_widget -> width, my d_widget -> height, my d_widget -> parent -> window, nullptr, theGui.instance, nullptr);
- SetWindowLongPtr (my d_widget -> window, GWLP_USERDATA, (LONG_PTR) my d_widget);
- my v_positionInScrolledWindow (my d_widget, width, height, parent);
- #elif cocoa
- GuiCocoaDrawingArea *drawingArea = [[GuiCocoaDrawingArea alloc] init];
- my d_widget = (GuiObject) drawingArea;
- my v_positionInScrolledWindow (my d_widget, width, height, parent);
- [drawingArea setUserData: me.get()];
- #endif
- return me.releaseToAmbiguousOwner();
- }
- GuiDrawingArea GuiDrawingArea_createShown (GuiScrolledWindow parent, int width, int height,
- GuiDrawingArea_ExposeCallback exposeCallback,
- GuiDrawingArea_ClickCallback clickCallback,
- GuiDrawingArea_KeyCallback keyCallback,
- GuiDrawingArea_ResizeCallback resizeCallback, Thing boss,
- uint32 flags)
- {
- GuiDrawingArea me = GuiDrawingArea_create (parent, width, height, exposeCallback, clickCallback, keyCallback, resizeCallback, boss, flags);
- GuiThing_show (me);
- return me;
- }
- void GuiDrawingArea_setSwipable (GuiDrawingArea me, GuiScrollBar horizontalScrollBar, GuiScrollBar verticalScrollBar) {
- my d_horizontalScrollBar = horizontalScrollBar;
- my d_verticalScrollBar = verticalScrollBar;
- #if gtk
- g_signal_connect (G_OBJECT (my d_widget), "scroll-event", G_CALLBACK (_guiGtkDrawingArea_swipeCallback), me);
- #endif
- }
- void GuiDrawingArea_setExposeCallback (GuiDrawingArea me, GuiDrawingArea_ExposeCallback callback, Thing boss) {
- my d_exposeCallback = callback;
- my d_exposeBoss = boss;
- }
- void GuiDrawingArea_setClickCallback (GuiDrawingArea me, GuiDrawingArea_ClickCallback callback, Thing boss) {
- my d_clickCallback = callback;
- my d_clickBoss = boss;
- }
- void GuiDrawingArea_setResizeCallback (GuiDrawingArea me, GuiDrawingArea_ResizeCallback callback, Thing boss) {
- my d_resizeCallback = callback;
- my d_resizeBoss = boss;
- }
- /* End of file GuiDrawingArea.cpp */
|