2 classvar <globalKeyDownAction, <globalKeyUpAction;
6 classvar <currentDrag, <currentDragString;
8 var wasRemoved = false;
10 var <font, <resize = 1, <alpha = 1.0;
12 var <decorator, <layout;
14 var <>userCanClose=true, <>deleteOnClose = true;
17 var <mouseDownAction, <mouseUpAction, <mouseEnterAction, <mouseLeaveAction;
18 var <mouseMoveAction, <mouseOverAction, <mouseWheelAction;
19 var <keyDownAction, <keyUpAction, <keyModifiersChangedAction;
22 var <focusGainedAction, <focusLostAction;
25 var <beginDragAction, <canReceiveDragHandler, <receiveDragHandler;
27 var <toFrontAction, <endFrontAction;
29 var <onClose, <onResize, <onMove;
32 hSizePolicy = [1,2,3,1,2,3,1,2,3];
33 vSizePolicy = [1,1,1,2,2,2,3,3,3];
36 *new { arg parent, bounds;
37 var p = parent.asView;
38 ^super.new( [p, bounds.asRect] ).initQView( p );
41 *newCustom { arg customArgs;
42 ^super.new( customArgs ).initQView( nil );
45 *qtClass { ^'QcDefaultWidget' }
51 ^this.primitiveFailed;
57 this.children.do { |child| child.remove };
60 mapToGlobal { arg point;
62 ^this.primitiveFailed;
65 // ----------------- properties --------------------------
68 this.setProperty( \font, f );
71 toolTip { ^this.getProperty(\toolTip) }
72 toolTip_ { arg t; this.setProperty( \toolTip, t ) }
75 ^this.getProperty( \palette );
79 this.setProperty( \palette, p );
86 background_ { arg color;
87 this.palette = this.palette.window_(color);
88 this.setProperty( \autoFillBackground, true );
91 // NOTE: only for backwards compatibility
92 backColor_ { arg color;
93 this.background = color;
97 ^this.bounds.moveToPoint( this.mapToGlobal( 0@0 ) );
101 ^this.getProperty(\geometry)
105 this.setProperty(\geometry, rect.asRect )
108 sizeHint { ^this.getProperty(\sizeHint) }
110 minSizeHint { ^this.getProperty(\minimumSizeHint) }
112 // a Point can be passed instead of a Size
114 var max = QLimits(\maxWidgetSize);
116 this.setProperty( \maximumSize, Size( min(max,size.width), min(max,size.height) ) );
119 // a Point can be passed instead of a Size
120 minSize_ { arg size; this.setProperty( \minimumSize, size.asSize ); }
122 fixedSize_ { arg size;
124 this.setProperty( \minimumSize, size );
125 this.setProperty( \maximumSize, size );
128 fixedWidth_ { arg width;
129 this.setProperty( \minimumWidth, width );
130 this.setProperty( \maximumWidth, width );
133 fixedHeight_ { arg height;
134 this.setProperty( \minimumHeight, height );
135 this.setProperty( \maximumHeight, height );
138 maxWidth_ { arg width;
139 this.setProperty( \maximumWidth, min( width, QLimits(\maxWidgetSize) ) );
142 minWidth_ { arg width; this.setProperty( \minimumWidth, width ); }
144 maxHeight_ { arg height;
145 this.setProperty( \maximumHeight, min( height, QLimits(\maxWidgetSize) ) );
148 minHeight_ { arg height; this.setProperty( \minimumHeight, height ); }
150 // backwards compatibility
151 relativeOrigin { ^true }
154 this.bounds_( this.bounds.moveTo( x, y ) );
157 resizeTo { arg width, height;
158 this.bounds_( this.bounds.resizeTo( width, height ) );
162 ^this.getProperty(\visible)
165 this.setProperty(\visible, bool, false)
169 ^this.getProperty(\enabled)
172 this.setProperty(\enabled, bool)
176 this.setProperty(\_qc_hSizePolicy, hSizePolicy[anInt-1]);
177 this.setProperty(\_qc_vSizePolicy, vSizePolicy[anInt-1]);
182 var policy = this.getProperty(\focusPolicy);
186 canFocus_ { arg bool;
188 if( bool ) { policy = 16r1 | 16r2 | 16r8 } { policy = 0 };
189 this.setProperty(\focusPolicy, policy);
192 focus { arg flag=true;
194 ^this.primitiveFailed;
198 ^this.getProperty( \focus );
202 _QWidget_AcceptsMouse
203 ^this.primitiveFailed;
206 acceptsMouse_ { arg bool;
207 _QWidget_SetAcceptsMouse
208 ^this.primitiveFailed;
211 focusColor_ { arg color;
212 this.setProperty(\focusColor, color);
216 ^try { this.getProperty(\focusColor) } { Color() };
219 // ------------------ container stuff ----------------------------
221 children { arg class = QView;
222 var ch = super.children( class );
223 ^ch.select { |v| (v.tryPerform(\isClosed) ? false).not };
226 parent { arg class = QView;
227 if (wasRemoved) { ^nil } { ^super.parent(class) };
233 if (wasRemoved.not) {
236 allParents = allParents.add( p );
248 var childWidgets = this.children( QView );
249 childWidgets.do { |child| child.remove };
252 layout_ { arg newLayout;
253 if( newLayout.notNil && (newLayout != layout) ) {
254 this.prSetLayout( newLayout );
259 addFlowLayout { arg margin, gap;
260 this.decorator_( FlowLayout( this.bounds.moveTo(0, 0), margin, gap ) );
264 decorator_ { arg decor;
265 decor.bounds = decor.bounds.moveTo(0, 0);
270 // ................. top window stuff ............................
273 ^this.getProperty( \windowTitle );
277 this.setProperty( \windowTitle, string );
282 ^this.primitiveFailed;
286 if( this.visible ) { this.invokeMethod( \showMinimized, synchronous:false ) };
290 if( this.getProperty( \minimized ) ) { this.invokeMethod( \showNormal, synchronous:false ) };
294 this.invokeMethod( \showFullScreen, synchronous:false );
298 if( this.getProperty( \fullScreen ) ) { this.invokeMethod( \showNormal, synchronous:false ) };
303 this.setProperty( \windowOpacity, aFloat );
307 _QWidget_GetAlwaysOnTop
308 ^this.primitiveFailed;
311 alwaysOnTop_ { arg boolean;
312 _QWidget_SetAlwaysOnTop
313 ^this.primitiveFailed;
319 { this.visible_( false ); }
323 if (wasRemoved) {^true} {^this.isValid.not};
326 notClosed { ^this.isClosed.not }
328 // TODO: deprecate acceptsMouseOver and expose 'mouseTracking' property directly
329 acceptsMouseOver { ^this.getProperty(\_qc_win_mouse_tracking) == true }
330 acceptsMouseOver_ { arg flag; this.setProperty(\_qc_win_mouse_tracking, flag == true) }
332 // ----------------- actions .....................................
335 // NOTE: not all widgets have action() signal
337 this.manageMethodConnection( action, func, 'action()', \doAction );
342 addAction { arg func, selector=\action;
343 this.perform(selector.asSetter, this.perform(selector).addFunc(func));
346 removeAction { arg func, selector=\action;
347 this.perform(selector.asSetter, this.perform(selector).removeFunc(func));
350 *globalKeyDownAction_ { arg action;
351 globalKeyDownAction = action;
352 this.setGlobalEventEnabled( 16r01 /* KeyPress */, true );
356 *globalKeyUpAction_ { arg action;
357 globalKeyUpAction = action;
358 this.setGlobalEventEnabled( 16r02 /* KeyRelease */, true );
361 keyDownAction_ { arg aFunction;
362 keyDownAction = aFunction;
363 this.setEventHandlerEnabled( QObject.keyDownEvent, true );
366 keyUpAction_ { arg aFunction;
367 keyUpAction = aFunction;
368 this.setEventHandlerEnabled( QObject.keyUpEvent, true );
371 keyModifiersChangedAction_ { arg aFunction;
372 keyModifiersChangedAction = aFunction;
373 this.setEventHandlerEnabled( QObject.keyDownEvent, true );
374 this.setEventHandlerEnabled( QObject.keyUpEvent, true );
377 mouseDownAction_ { arg aFunction;
378 mouseDownAction = aFunction;
379 this.setEventHandler( QObject.mouseDownEvent, \mouseDownEvent, true );
380 this.setEventHandler( QObject.mouseDblClickEvent, \mouseDownEvent, true );
383 mouseUpAction_ { arg aFunction;
384 mouseUpAction = aFunction;
385 this.setEventHandler( QObject.mouseUpEvent, \mouseUpEvent, true );
388 mouseMoveAction_ { arg aFunction;
389 mouseMoveAction = aFunction;
390 this.setEventHandler( QObject.mouseMoveEvent, \mouseMoveEvent, true );
393 // mouseOverAction responds to same Qt event as mouseMoveAction,
394 // but on different conditions.
395 // See QView:-mouseMoveEvent method.
396 mouseOverAction_ { arg aFunction;
397 mouseOverAction = aFunction;
398 this.setEventHandler( QObject.mouseMoveEvent, \mouseMoveEvent, true );
399 this.setProperty(\mouseTracking, true);
402 mouseEnterAction_ { arg aFunction;
403 mouseEnterAction = aFunction;
404 this.setEventHandler( QObject.mouseEnterEvent, \mouseEnterEvent, true );
407 mouseLeaveAction_ { arg aFunction;
408 mouseLeaveAction = aFunction;
409 this.setEventHandler( QObject.mouseLeaveEvent, \mouseLeaveEvent, true );
412 mouseWheelAction_ { arg aFunction;
413 mouseWheelAction = aFunction;
414 this.setEventHandler( QObject.mouseWheelEvent, \mouseWheelEvent, true );
417 beginDragAction_ { arg handler;
418 beginDragAction = handler;
419 this.setEventHandler( QObject.mouseDownEvent, \mouseDownEvent, true )
422 canReceiveDragHandler_ { arg handler;
423 canReceiveDragHandler = handler;
424 this.setDragEventsEnabled( true );
427 receiveDragHandler_ { arg handler;
428 receiveDragHandler = handler;
429 this.setDragEventsEnabled( true );
432 toFrontAction_ { arg aFunction;
433 toFrontAction = aFunction;
434 this.setEventHandler( QObject.windowActivateEvent,
435 \onWindowActivateEvent );
438 endFrontAction_ { arg aFunction;
439 endFrontAction = aFunction;
440 this.setEventHandler( QObject.windowDeactivateEvent,
441 \onWindowDeactivateEvent );
444 focusGainedAction_ { arg handler;
445 focusGainedAction = handler;
446 this.setEventHandler( 8 /* QEvent::FocusIn */, \focusInEvent );
449 focusLostAction_ { arg handler;
450 focusLostAction = handler;
451 this.setEventHandler( 9 /* QEvent::FocusOut */, \focusOutEvent );
454 onMove_ { arg aFunction;
456 this.setEventHandler( 13 /* QEvent::Move */, \moveEvent );
459 onResize_ { arg aFunction;
460 onResize = aFunction;
461 this.setEventHandler( 14 /* QEvent::Resize */, \resizeEvent );
465 this.manageFunctionConnection( onClose, func, 'destroyed()', false );
473 defaultKeyDownAction { arg char, modifiers, unicode, keycode; }
475 defaultKeyUpAction { arg char, modifiers, unicode, keycode; }
477 keyDown { arg char, modifiers, unicode, keycode;
478 if( keyDownAction.notNil ) {
479 ^keyDownAction.value( this, char, modifiers, unicode, keycode );
481 ^this.defaultKeyDownAction( char, modifiers, unicode, keycode );
485 keyUp { arg char, modifiers, unicode, keycode;
487 if( keyUpAction.notNil ) {
488 ^keyUpAction.value( this, char, modifiers, unicode, keycode );
490 ^this.defaultKeyUpAction( char, modifiers, unicode, keycode );
494 keyModifiersChanged { arg modifiers;
495 keyModifiersChangedAction.value( this, modifiers);
498 mouseDown { arg x, y, modifiers, buttonNumber, clickCount;
499 ^mouseDownAction.value( this, x, y, modifiers, buttonNumber, clickCount );
502 mouseUp { arg x, y, modifiers, buttonNumber;
503 ^mouseUpAction.value( this, x, y, modifiers, buttonNumber );
506 mouseMove { arg x, y, modifiers;
507 ^mouseMoveAction.value( this, x, y, modifiers );
510 mouseOver { arg x, y;
511 ^mouseOverAction.value( this, x, y );
515 ^mouseEnterAction.value(this);
519 ^mouseLeaveAction.value(this);
522 mouseWheel { arg x, y, modifiers, xDelta, yDelta;
523 ^mouseWheelAction.value( this, x, y, modifiers, xDelta, yDelta );
526 /* ---------------- private ----------------------- */
528 *prSetCurrentDrag { arg obj; currentDrag = obj; currentDragString = obj.asCompileString; }
529 *prClearCurrentDrag { currentDrag = nil; currentDragString = nil; }
531 *setGlobalEventEnabled { arg event, enabled;
532 _QWidget_SetGlobalEventEnabled
535 initQView { arg parent;
537 var handleKeyDown, handleKeyUp, overridesMouseDown, handleDrag;
540 if( parent.decorator.notNil ) { parent.decorator.place(this) }
543 this.setEventHandler( QObject.closeEvent, \onCloseEvent, true );
546 handleKeyDown = handleKeyUp = this.overrides( \keyModifiersChanged );
547 if( handleKeyDown.not )
548 { handleKeyDown = this.overrides( \defaultKeyDownAction ) };
549 if( handleKeyUp.not )
550 { handleKeyUp = this.overrides( \defaultKeyUpAction )};
552 this.setEventHandler( QObject.keyDownEvent, \keyDownEvent, true, enabled: handleKeyDown );
553 this.setEventHandler( QObject.keyUpEvent, \keyUpEvent, true, enabled: handleKeyUp );
556 overridesMouseDown = this.overrides( \mouseDown );
557 if( this.respondsTo(\defaultGetDrag) || overridesMouseDown )
558 {this.setEventHandler( QObject.mouseDownEvent, \mouseDownEvent, true )};
559 if( overridesMouseDown )
560 {this.setEventHandler( QObject.mouseDblClickEvent, \mouseDownEvent, true )};
561 if( this.overrides( \mouseUp ) )
562 {this.setEventHandler( QObject.mouseUpEvent, \mouseUpEvent, true )};
563 if( this.overrides( \mouseMove ) || this.overrides( \mouseOver ) )
564 {this.setEventHandler( QObject.mouseMoveEvent, \mouseMoveEvent, true )};
565 if( this.overrides( \mouseEnter ) )
566 {this.setEventHandler( QObject.mouseEnterEvent, \mouseEnterEvent, true )};
567 if( this.overrides( \mouseLeave ) )
568 {this.setEventHandler( QObject.mouseLeaveEvent, \mouseLeaveEvent, true )};
569 if( this.overrides( \mouseWheel ) )
570 {this.setEventHandler( QObject.wheelEvent, \mouseWheelEvent, true )};
573 handleDrag = this.respondsTo(\defaultCanReceiveDrag) or: {this.respondsTo(\defaultReceiveDrag)};
574 this.setEventHandler( 60, \dragEnterEvent, true, enabled:handleDrag );
575 this.setEventHandler( 61, \dragMoveEvent, true, enabled:handleDrag );
576 this.setEventHandler( 63, \dropEvent, true, enabled:handleDrag );
580 if( userCanClose != false ) {
581 if( deleteOnClose != false ) { this.remove; ^true };
587 onWindowActivateEvent {
588 toFrontAction.value(this);
591 onWindowDeactivateEvent {
592 endFrontAction.value(this);
595 focusInEvent { focusGainedAction.value(this) }
596 focusOutEvent { focusLostAction.value(this) }
598 moveEvent { onMove.value(this) }
599 resizeEvent { onResize.value(this) }
601 keyDownEvent { arg char, modifiers, unicode, keycode, spontaneous;
602 modifiers = QKeyModifiers.toCocoa(modifiers);
604 if( char.size > 0 ) {char = char[0]} {char = 0.asAscii};
607 // this event has never been propagated to parent yet
608 QView.globalKeyDownAction.value( this, char, modifiers, unicode, keycode );
611 if( (keycode == 16r1000020) || (keycode == 16r1000021) ||
612 (keycode == 16r1000022) || (keycode == 16r1000023 ) )
613 { this.keyModifiersChanged( modifiers ) };
615 ^this.keyDown( char, modifiers, unicode, keycode );
618 keyUpEvent { arg char, modifiers, unicode, keycode, spontaneous;
619 modifiers = QKeyModifiers.toCocoa(modifiers);
621 if( char.size > 0 ) {char = char[0]} {char = 0.asAscii};
624 // this event has never been propagated to parent yet
625 QView.globalKeyUpAction.value( this, char, modifiers, unicode, keycode );
628 if( (keycode == 16r1000020) || (keycode == 16r1000021) ||
629 (keycode == 16r1000022) || (keycode == 16r1000023 ) )
630 { this.keyModifiersChanged( modifiers ) };
632 ^this.keyUp( char, modifiers, unicode, keycode );
635 mouseDownEvent { arg x, y, modifiers, buttonNumber, clickCount;
636 // WARNING: QDragView and QListView override this method!
638 if( (modifiers & QKeyModifiers.control) > 0 ) { // if Ctrl / Cmd mod
639 // Try to get drag obj and start a drag.
640 // If successful, block further processing of this event.
641 if( this.beginDrag( x, y ) ) { ^false };
644 // else continue to handle mouse down event
645 modifiers = QKeyModifiers.toCocoa(modifiers);
646 ^this.mouseDown( x, y, modifiers, buttonNumber, clickCount );
649 mouseUpEvent { arg x, y, modifiers, buttonNumber;
650 modifiers = QKeyModifiers.toCocoa(modifiers);
651 ^this.mouseUp( x, y, modifiers, buttonNumber );
654 mouseMoveEvent { arg x, y, modifiers, buttons;
656 modifiers = QKeyModifiers.toCocoa(modifiers);
657 ^this.mouseMove( x, y, modifiers );
659 ^this.mouseOver( x, y )
664 var dummy = 0; // prevent this method from being optimized away
669 var dummy = 0; // prevent this method from being optimized away
673 mouseWheelEvent { arg x, y, modifiers, xDelta, yDelta;
674 modifiers = QKeyModifiers.toCocoa(modifiers);
675 ^this.mouseWheel( x, y, modifiers, xDelta, yDelta );
678 beginDrag { arg x, y;
680 if( beginDragAction.notNil )
681 { obj = beginDragAction.value( this, x, y ) }
682 { obj = this.tryPerform( \defaultGetDrag, x, y ) };
684 QView.prSetCurrentDrag( obj );
686 this.prStartDrag( dragLabel ?? str, obj, str );
692 canReceiveDrag { arg x, y;
693 if( canReceiveDragHandler.notNil )
694 { ^this.canReceiveDragHandler.value( this, x, y ) }
695 { ^( this.tryPerform( \defaultCanReceiveDrag, x, y ) ? false ) };
698 receiveDrag { arg x, y;
699 if( receiveDragHandler.notNil )
700 { this.receiveDragHandler.value( this, x, y ) }
701 { this.tryPerform( \defaultReceiveDrag, x, y ) };
704 prStartDrag { arg label, data, dataAsString;
706 ^this.primitiveFailed;
710 // always accept the event
714 dragMoveEvent { arg x, y;
715 // make sure the event is always consumed
716 ^this.canReceiveDrag( x, y ).switch (
723 dropEvent { arg x, y;
724 this.receiveDrag( x, y );
725 // always accept the event
729 setDragEventsEnabled { arg enabled;
730 this.setEventHandlerEnabled( 60, enabled );
731 this.setEventHandlerEnabled( 61, enabled );
732 this.setEventHandlerEnabled( 63, enabled );
735 prSetLayout { arg layout;
737 ^this.primitiveFailed;
740 manageMethodConnection { arg oldAction, newAction, signal, method, sync=false;
741 if( newAction !== oldAction ) {
743 { oldAction.isNil && newAction.notNil } {this.connectMethod (signal, method, sync)}
744 { oldAction.notNil && newAction.isNil } {this.disconnectMethod (signal, method)}
749 manageFunctionConnection { arg oldAction, newAction, signal, sync=false;
750 if( newAction !== oldAction ) {
751 if( oldAction.notNil ) {this.disconnectFunction (signal, oldAction)};
752 if( newAction.notNil ) {this.connectFunction (signal, newAction, sync)};
756 overrides { arg symMethod;
757 ^ ( this.class.findRespondingMethodFor(symMethod) !=
758 QView.findRespondingMethodFor(symMethod) );
761 nonimpl { arg methodName;
762 this.class.nonimpl( methodName );
765 *nonimpl { arg methodName;
766 this.debug( msg: methodName.asString ++ " is not implemented yet" )
769 *debug { arg level = 1, msg = "";
770 if( QtGUI.debugLevel >= level ) { ("Qt: " ++ this.asString ++ ": " ++ msg).postln }